(s, *, GUARD=8)
| 269 | del defaultdict |
| 270 | |
| 271 | def _dec_str_to_int_inner(s, *, GUARD=8): |
| 272 | # Yes, BYTELIM is "large". Large enough that CPython will usually |
| 273 | # use the Karatsuba _str_to_int_inner to convert the string. This |
| 274 | # allowed reducing the cutoff for calling _this_ function from 3.5M |
| 275 | # to 2M digits. We could almost certainly do even better by |
| 276 | # fine-tuning this and/or using a larger output base than 256. |
| 277 | BYTELIM = 100_000 |
| 278 | D = decimal.Decimal |
| 279 | result = bytearray() |
| 280 | # See notes at end of file for discussion of GUARD. |
| 281 | assert GUARD > 0 # if 0, `decimal` can blow up - .prec 0 not allowed |
| 282 | |
| 283 | def inner(n, w): |
| 284 | #assert n < D256 ** w # required, but too expensive to check |
| 285 | if w <= BYTELIM: |
| 286 | # XXX Stefan Pochmann discovered that, for 1024-bit ints, |
| 287 | # `int(Decimal)` took 2.5x longer than `int(str(Decimal))`. |
| 288 | # Worse, `int(Decimal) is still quadratic-time for much |
| 289 | # larger ints. So unless/until all that is repaired, the |
| 290 | # seemingly redundant `str(Decimal)` is crucial to speed. |
| 291 | result.extend(int(str(n)).to_bytes(w)) # big-endian default |
| 292 | return |
| 293 | w1 = w >> 1 |
| 294 | w2 = w - w1 |
| 295 | if 0: |
| 296 | # This is maximally clear, but "too slow". `decimal` |
| 297 | # division is asymptotically fast, but we have no way to |
| 298 | # tell it to reuse the high-precision reciprocal it computes |
| 299 | # for pow256[w2], so it has to recompute it over & over & |
| 300 | # over again :-( |
| 301 | hi, lo = divmod(n, pow256[w2][0]) |
| 302 | else: |
| 303 | p256, recip = pow256[w2] |
| 304 | # The integer part will have a number of digits about equal |
| 305 | # to the difference between the log10s of `n` and `pow256` |
| 306 | # (which, since these are integers, is roughly approximated |
| 307 | # by `.adjusted()`). That's the working precision we need, |
| 308 | ctx.prec = max(n.adjusted() - p256.adjusted(), 0) + GUARD |
| 309 | hi = +n * +recip # unary `+` chops back to ctx.prec digits |
| 310 | ctx.prec = decimal.MAX_PREC |
| 311 | hi = hi.to_integral_value() # lose the fractional digits |
| 312 | lo = n - hi * p256 |
| 313 | # Because we've been uniformly rounding down, `hi` is a |
| 314 | # lower bound on the correct quotient. |
| 315 | assert lo >= 0 |
| 316 | # Adjust quotient up if needed. It usually isn't. In random |
| 317 | # testing on inputs through 5 billion digit strings, the |
| 318 | # test triggered once in about 200 thousand tries. |
| 319 | count = 0 |
| 320 | if lo >= p256: |
| 321 | count = 1 |
| 322 | lo -= p256 |
| 323 | hi += 1 |
| 324 | if lo >= p256: |
| 325 | # Complete correction via an exact computation. I |
| 326 | # believe it's not possible to get here provided |
| 327 | # GUARD >= 3. It's tested by reducing GUARD below |
| 328 | # that. |
nothing calls this directly
no test coverage detected
searching dependent graphs…