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