Given integers c, e and p with c > 0, compute an integer approximation to 10**p * log(c*10**e), with an absolute error of at most 1. Assumes that c*10**e is not exactly 1.
(c, e, p)
| 5782 | return _div_nearest(log_tenpower+log_d, 100) |
| 5783 | |
| 5784 | def _dlog(c, e, p): |
| 5785 | """Given integers c, e and p with c > 0, compute an integer |
| 5786 | approximation to 10**p * log(c*10**e), with an absolute error of |
| 5787 | at most 1. Assumes that c*10**e is not exactly 1.""" |
| 5788 | |
| 5789 | # Increase precision by 2. The precision increase is compensated |
| 5790 | # for at the end with a division by 100. |
| 5791 | p += 2 |
| 5792 | |
| 5793 | # rewrite c*10**e as d*10**f with either f >= 0 and 1 <= d <= 10, |
| 5794 | # or f <= 0 and 0.1 <= d <= 1. Then we can compute 10**p * log(c*10**e) |
| 5795 | # as 10**p * log(d) + 10**p*f * log(10). |
| 5796 | l = len(str(c)) |
| 5797 | f = e+l - (e+l >= 1) |
| 5798 | |
| 5799 | # compute approximation to 10**p*log(d), with error < 27 |
| 5800 | if p > 0: |
| 5801 | k = e+p-f |
| 5802 | if k >= 0: |
| 5803 | c *= 10**k |
| 5804 | else: |
| 5805 | c = _div_nearest(c, 10**-k) # error of <= 0.5 in c |
| 5806 | |
| 5807 | # _ilog magnifies existing error in c by a factor of at most 10 |
| 5808 | log_d = _ilog(c, 10**p) # error < 5 + 22 = 27 |
| 5809 | else: |
| 5810 | # p <= 0: just approximate the whole thing by 0; error < 2.31 |
| 5811 | log_d = 0 |
| 5812 | |
| 5813 | # compute approximation to f*10**p*log(10), with error < 11. |
| 5814 | if f: |
| 5815 | extra = len(str(abs(f)))-1 |
| 5816 | if p + extra >= 0: |
| 5817 | # error in f * _log10_digits(p+extra) < |f| * 1 = |f| |
| 5818 | # after division, error < |f|/10**extra + 0.5 < 10 + 0.5 < 11 |
| 5819 | f_log_ten = _div_nearest(f*_log10_digits(p+extra), 10**extra) |
| 5820 | else: |
| 5821 | f_log_ten = 0 |
| 5822 | else: |
| 5823 | f_log_ten = 0 |
| 5824 | |
| 5825 | # error in sum < 11+27 = 38; error after division < 0.38 + 0.5 < 1 |
| 5826 | return _div_nearest(f_log_ten + log_d, 100) |
| 5827 | |
| 5828 | class _Log10Memoize(object): |
| 5829 | """Class to compute, store, and allow retrieval of, digits of the |