Integer approximation to M*log(x/M), with absolute error boundable in terms only of x/M. Given positive integers x and M, return an integer approximation to M * log(x/M). For L = 8 and 0.1 <= x/M <= 10 the difference between the approximation and the exact result is at most 22. Fo
(x, M, L = 8)
| 5703 | return q + (2*r + (q&1) > b) |
| 5704 | |
| 5705 | def _ilog(x, M, L = 8): |
| 5706 | """Integer approximation to M*log(x/M), with absolute error boundable |
| 5707 | in terms only of x/M. |
| 5708 | |
| 5709 | Given positive integers x and M, return an integer approximation to |
| 5710 | M * log(x/M). For L = 8 and 0.1 <= x/M <= 10 the difference |
| 5711 | between the approximation and the exact result is at most 22. For |
| 5712 | L = 8 and 1.0 <= x/M <= 10.0 the difference is at most 15. In |
| 5713 | both cases these are upper bounds on the error; it will usually be |
| 5714 | much smaller.""" |
| 5715 | |
| 5716 | # The basic algorithm is the following: let log1p be the function |
| 5717 | # log1p(x) = log(1+x). Then log(x/M) = log1p((x-M)/M). We use |
| 5718 | # the reduction |
| 5719 | # |
| 5720 | # log1p(y) = 2*log1p(y/(1+sqrt(1+y))) |
| 5721 | # |
| 5722 | # repeatedly until the argument to log1p is small (< 2**-L in |
| 5723 | # absolute value). For small y we can use the Taylor series |
| 5724 | # expansion |
| 5725 | # |
| 5726 | # log1p(y) ~ y - y**2/2 + y**3/3 - ... - (-y)**T/T |
| 5727 | # |
| 5728 | # truncating at T such that y**T is small enough. The whole |
| 5729 | # computation is carried out in a form of fixed-point arithmetic, |
| 5730 | # with a real number z being represented by an integer |
| 5731 | # approximation to z*M. To avoid loss of precision, the y below |
| 5732 | # is actually an integer approximation to 2**R*y*M, where R is the |
| 5733 | # number of reductions performed so far. |
| 5734 | |
| 5735 | y = x-M |
| 5736 | # argument reduction; R = number of reductions performed |
| 5737 | R = 0 |
| 5738 | while (R <= L and abs(y) << L-R >= M or |
| 5739 | R > L and abs(y) >> R-L >= M): |
| 5740 | y = _div_nearest((M*y) << 1, |
| 5741 | M + _sqrt_nearest(M*(M+_rshift_nearest(y, R)), M)) |
| 5742 | R += 1 |
| 5743 | |
| 5744 | # Taylor series with T terms |
| 5745 | T = -int(-10*len(str(M))//(3*L)) |
| 5746 | yshift = _rshift_nearest(y, R) |
| 5747 | w = _div_nearest(M, T) |
| 5748 | for k in range(T-1, 0, -1): |
| 5749 | w = _div_nearest(M, k) - _div_nearest(yshift*w, M) |
| 5750 | |
| 5751 | return _div_nearest(w*y, M) |
| 5752 | |
| 5753 | def _dlog10(c, e, p): |
| 5754 | """Given integers c, e and p with c > 0, p >= 0, compute an integer |
no test coverage detected
searching dependent graphs…