Beispiel #1
0
def _calc_spouge_coefficients(a, prec):
    """
    Calculate Spouge coefficients for approximation with parameter a.
    Return a list of big integers representing the coefficients in
    fixed-point form with a precision of prec bits.
    """

    # We'll store the coefficients as fixed-point numbers but calculate
    # them as Floats for convenience. The initial terms are huge, so we
    # need to allocate extra bits to ensure full accuracy. The integer
    # part of the largest term has size ~= exp(a) or 2**(1.4*a)
    floatprec = prec + int(a*1.4)
    Float.store()
    Float.setprec(floatprec)

    c = [0] * a
    b = exp(a-1)
    e = exp(1)
    c[0] = make_fixed(sqrt(2*pi_float()), prec)
    for k in range(1, a):
        # print "%02f" % (100.0 * k / a), "% done"
        c[k] = make_fixed(((-1)**(k-1) * (a-k)**k) * b / sqrt(a-k), prec)
        # Divide off e and k instead of computing exp and k! from scratch
        b = b / (e * k)

    Float.revert()
    return c
Beispiel #2
0
def cos_sin(x):
    """
    cos_sin(x) calculates both the cosine and the sine of x rounded
    to the nearest Float value, and returns the tuple (cos(x), sin(x)).
    """
    if not isinstance(x, Float):
        x = Float(x)
    bits_from_unit = abs(bitcount(x.man) + x.exp)
    prec = Float._prec + bits_from_unit + 15
    xf = make_fixed(x, prec)
    n, rx = _trig_reduce(xf, prec)
    case = n % 4
    one = 1 << prec
    if case == 0:
        s = _sin_series(rx, prec)
        c = _sqrt_fixed(one - ((s * s) >> prec), prec)
    elif case == 1:
        c = -_sin_series(rx, prec)
        s = _sqrt_fixed(one - ((c * c) >> prec), prec)
    elif case == 2:
        s = -_sin_series(rx, prec)
        c = -_sqrt_fixed(one - ((s * s) >> prec), prec)
    elif case == 3:
        c = _sin_series(rx, prec)
        s = -_sqrt_fixed(one - ((c * c) >> prec), prec)
    return Float((c, -prec)), Float((s, -prec))
Beispiel #3
0
def _lower_gamma_series(are, aim, zre, zim, prec):
    are = make_fixed(are, prec)
    aim = make_fixed(aim, prec)
    zre = make_fixed(zre, prec)
    zim = make_fixed(zim, prec)
    one = 1 << prec
    cre = sre = one
    cim = sim = 0
    while abs(cre) > 3 or abs(cim) > 3:
        # c = (c * z) << prec
        cre, cim = (cre*zre-cim*zim)>>prec, (cim*zre+cre*zim)>>prec
        # c = c / (a+k)
        are += one
        mag = ((are**2 + aim**2) >> prec)
        cre, cim = (cre*are + cim*aim)//mag, (cim*are - cre*aim)//mag
        sre += cre
        sim += cim
        #k += 1
    sre = Float((sre, -prec))
    sim = Float((sim, -prec))
    return ComplexFloat(sre, sim)
Beispiel #4
0
def _spouge_sum(x, prec, a, c):
    if isinstance(x, Float):
        # Regular fixed-point summation
        x = make_fixed(x, prec)
        s = c[0]
        for k in xrange(1, a):
            s += (c[k] << prec) // (x + (k << prec))
        return Float((s, -prec))
    elif isinstance(x, (Rational, int, long)):
        # Here we can save some work
        if isinstance(x, (int, long)):
            p, q = x, 1
        else:
            p, q = x.p, x.q
        s = c[0]
        for k in xrange(1, a):
            s += c[k] * q // (p+q*k)
        return Float((s, -prec))
    elif isinstance(x, ComplexFloat):
        """
        For a complex number a + b*I, we have

              c_k          (a+k)*c_k     b * c_k
        -------------  =   ---------  -  ------- * I
        (a + b*I) + k          M            M

                       2    2      2   2              2
        where M = (a+k)  + b   = (a + b ) + (2*a*k + k )
        """
        re = make_fixed(x.real, prec)
        im = make_fixed(x.imag, prec)
        sre, sim = c[0], 0
        mag = ((re**2)>>prec) + ((im**2)>>prec)
        for k in xrange(1, a):
            M = mag + re*(2*k) + ((k**2) << prec)
            sre += (c[k] * (re + (k << prec))) // M
            sim -= (c[k] * im) // M
        return ComplexFloat(Float((sre, -prec)), Float((sim, -prec)))
Beispiel #5
0
def _atan_series_2(x):
    prec = Float._prec
    prec = prec + 15
    x = make_fixed(x, prec)
    one = 1 << prec
    x2 = (x * x) >> prec
    y = (x2 << prec) // (one + x2)
    s = a = one
    for n in xrange(1, 1000000):
        a = ((a * y) >> prec) * (2 * n) // (2 * n + 1)
        if a < 100:
            break
        s += a
    return Float(((y * s) // x, -prec))
Beispiel #6
0
def _atan_series_1(x):
    prec = Float._prec
    # Increase absolute precision when extremely close to 0
    bc = bitcount(x.man)
    diff = -(bc + x.exp)
    if diff > 10:
        if 3 * diff - 4 > prec:  # x**3 term vanishes; atan(x) ~x
            return +x
        prec = prec + diff
    prec += 15  # XXX: better estimate for number of guard bits
    x = make_fixed(x, prec)
    x2 = (x * x) >> prec
    one = 1 << prec
    s = a = x
    for n in xrange(1, 1000000):
        a = (a * x2) >> prec
        s += a // ((-1) ** n * (n + n + 1))
        if -100 < a < 100:
            break
    return Float((s, -prec))
Beispiel #7
0
def exp(x):
    """
    exp(x) -- compute the exponential function of the real or complex
    number x
    """
    if isinstance(x, (ComplexFloat, complex)):
        mag = exp(x.real)
        re, im = cos_sin(x.imag)
        return ComplexFloat(mag * re, mag * im)
    else:
        if not isinstance(x, Float):
            x = Float(x)
        # extra precision needs to be similar in magnitude to log_2(|x|)
        prec = Float._prec + 4 + max(0, bitcount(x.man) + x.exp)
        t = make_fixed(x, prec)
        if abs(x) > 1:
            lg2 = log2_fixed(prec)
            n, t = divmod(t, lg2)
        else:
            n = 0
        y = _exp_series(t, prec)
        return Float((y, -prec + n))