def _pi_agm(prec): from functions import _sqrt_fixed2 prec += 50 a = 1 << prec if "verbose" in global_options: print " computing initial square root..." b = _sqrt_fixed2(a >> 1, prec) t = a >> 2 p = 1 step = 1 while 1: an = (a+b)>>1 adiff = a - an if "verbose" in global_options: base = global_options.get("verbose_base", 10) try: logdiff = _clog(adiff, base) except ValueError: logdiff = 0 digits = int(prec/_clog(base,2) - logdiff) print " iteration", step, ("(accuracy ~= %i base-%i digits)" % (digits, base)) if p > 16 and abs(adiff) < 1000: break prod = (a*b)>>prec b = _sqrt_fixed2(prod, prec) t = t - p*((adiff**2) >> prec) p = 2*p a = an step += 1 if "verbose" in global_options: print " final division" return ((((a+b)**2) >> 2) // t) >> 50
def gamma_fixed(prec): # XXX: may need even more extra precision prec += 30 # choose p such that exp(-4*(2**p)) < 2**-n p = int(_clog((prec/4) * _clog(2), 2)) + 1 n = 1<<p; r=one=1<<prec H, A, B, npow, k, d = 0, 0, 0, 1, 1, 1 while r: A += (r * H) >> prec B += r r = r * (n*n) // (k*k) H += one // k k += 1 S = ((A<<prec) // B) - p*log2_fixed(prec) return S >> 30
def _log_newton(x, prec): # 50-bit approximation r = int(_clog(Float((x, -prec), 64)) * 2.0 ** 50) prevp = 50 for p in _quadratic_steps(50, prec + 8): rb = _lshift(r, p - prevp) e = _exp_series(-rb, p) r = rb + ((_rshift(x, prec - p) * e) >> p) - (1 << p) prevp = p return r >> 8
def log(x, b=None): """ log(x) -> the natural (base e) logarithm of x log(x, b) -> the base b logarithm of x """ # Basic input management if b is not None: Float._prec += 3 if b == 2: blog = log2_float() elif b == 10: blog = log10_float() else: blog = log(b) l = log(x) / blog Float._prec -= 3 return l if x == 0: raise ValueError, "logarithm of 0" if isinstance(x, (ComplexFloat, complex)): mag = abs(x) phase = atan2(x.imag, x.real) return ComplexFloat(log(mag), phase) if not isinstance(x, Float): x = Float(x) if x < 0: return log(ComplexFloat(x)) if x == 1: return Float((0, 0)) bc = bitcount(x.man) # Estimated precision needed for log(t) + n*log(2) prec = Float._prec + int(_clog(1 + abs(bc + x.exp), 2)) + 10 # Watch out for the case when x is very close to 1 if -1 < bc + x.exp < 2: near_one = abs(x - 1) if near_one == 0: return Float((0, 0)) prec += -(near_one.exp) - bitcount(near_one.man) # Separate mantissa and exponent, calculate fixed-point # approximation and put it all together t = _rshift(x.man, bc - prec) l = _log_newton(t, prec) a = (x.exp + bc) * log2_fixed(prec) return Float((l + a, -prec))
def _exp_series(x, prec): r = int(2.2 * prec ** 0.42) # XXX: more careful calculation of guard bits guards = r + 3 if prec > 60: guards += int(_clog(prec)) prec2 = prec + guards x = _rshift(x, r - guards) s = (1 << prec2) + x a = x k = 2 # Sum exp(x/2**r) while 1: a = ((a * x) >> prec2) // k if not a: break s += a k += 1 # Calculate s**(2**r) by repeated squaring for j in range(r): s = (s * s) >> prec2 return s >> guards