MCPcopy Index your code
hub / github.com/python/cpython / _ilog

Function _ilog

Lib/_pydecimal.py:5705–5751  ·  view source on GitHub ↗

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)

Source from the content-addressed store, hash-verified

5703 return q + (2*r + (q&1) > b)
5704
5705def _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
5753def _dlog10(c, e, p):
5754 """Given integers c, e and p with c > 0, p >= 0, compute an integer

Callers 3

_dlog10Function · 0.85
_dlogFunction · 0.85
getdigitsMethod · 0.85

Calls 5

absFunction · 0.85
_div_nearestFunction · 0.85
_sqrt_nearestFunction · 0.85
_rshift_nearestFunction · 0.85
strFunction · 0.85

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…