Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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))
Exemple #5
0
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