예제 #1
0
def machin(coefs, prec, hyperbolic=False):
    """
    Evaluate a Machin-like formula, i.e., a linear combination of
    acot(n) or acoth(n) for specific integer values of n, using fixed-
    point arithmetic. The input should be a list [(c, n), ...], giving
    c*acot[h](n) + ...
    """
    extraprec = 10
    s = MPZ_ZERO
    for a, b in coefs:
        s += MPZ(a) * acot_fixed(MPZ(b), prec + extraprec, hyperbolic)
    return (s >> extraprec)
예제 #2
0
def from_man_exp(man, exp, prec=None, rnd=round_fast):
    """Create raw mpf from (man, exp) pair. The mantissa may be signed.
    If no precision is specified, the mantissa is stored exactly."""
    man = MPZ(man)
    sign = 0
    if man < 0:
        sign = 1
        man = -man
    if man < 1024:
        bc = bctable[int(man)]
    else:
        bc = bitcount(man)
    if not prec:
        if not man:
            return fzero
        if not man & 1:
            if man & 2:
                return (sign, man >> 1, exp + 1, bc - 1)
            t = trailtable[int(man & 255)]
            if not t:
                while not man & 255:
                    man >>= 8
                    exp += 8
                    bc -= 8
                t = trailtable[int(man & 255)]
            man >>= t
            exp += t
            bc -= t
        return (sign, man, exp, bc)
    return normalize(sign, man, exp, bc, prec, rnd)
예제 #3
0
def from_bstr(x):
    man, exp = str_to_man_exp(x, base=2)
    man = MPZ(man)
    sign = 0
    if man < 0:
        man = -man
        sign = 1
    bc = bitcount(man)
    return normalize(sign, man, exp, bc, bc, round_floor)
예제 #4
0
파일: libintmath.py 프로젝트: jarmoza/twic2
def stirling2(n, k):
    """
    Stirling number of the second kind.
    """
    if n < 0 or k < 0:
        raise ValueError
    if k >= n:
        return MPZ(n == k)
    if k <= 1:
        return MPZ(k == 1)
    s = MPZ_ZERO
    t = MPZ_ONE
    for j in xrange(k + 1):
        if (k + j) & 1:
            s -= t * MPZ(j)**n
        else:
            s += t * MPZ(j)**n
        t = t * (k - j) // (j + 1)
    return s // ifac(k)
예제 #5
0
def bspe(a, b):
    """
    Sum series for exp(1)-1 between a, b, returning the result
    as an exact fraction (p, q).
    """
    if b - a == 1:
        return MPZ_ONE, MPZ(b)
    m = (a + b) // 2
    p1, q1 = bspe(a, m)
    p2, q2 = bspe(m, b)
    return p1 * q2 + p2, q1 * q2
예제 #6
0
def bsp_acot(q, a, b, hyperbolic):
    if b - a == 1:
        a1 = MPZ(2 * a + 3)
        if hyperbolic or a & 1:
            return MPZ_ONE, a1 * q**2, a1
        else:
            return -MPZ_ONE, a1 * q**2, a1
    m = (a + b) // 2
    p1, q1, r1 = bsp_acot(q, a, m, hyperbolic)
    p2, q2, r2 = bsp_acot(q, m, b, hyperbolic)
    return q2 * p1 + r1 * p2, q1 * q2, r1 * r2
예제 #7
0
파일: gammazeta.py 프로젝트: xinjie0831/AMC
def mpf_zeta_int(s, prec, rnd=round_fast):
    """
    Optimized computation of zeta(s) for an integer s.
    """
    wp = prec + 20
    s = int(s)
    if s in zeta_int_cache and zeta_int_cache[s][0] >= wp:
        return mpf_pos(zeta_int_cache[s][1], prec, rnd)
    if s < 2:
        if s == 1:
            raise ValueError("zeta(1) pole")
        if not s:
            return mpf_neg(fhalf)
        return mpf_div(mpf_bernoulli(-s + 1, wp), from_int(s - 1), prec, rnd)
    # 2^-s term vanishes?
    if s >= wp:
        return mpf_perturb(fone, 0, prec, rnd)
    # 5^-s term vanishes?
    elif s >= wp * 0.431:
        t = one = 1 << wp
        t += 1 << (wp - s)
        t += one // (MPZ_THREE**s)
        t += 1 << max(0, wp - s * 2)
        return from_man_exp(t, -wp, prec, rnd)
    else:
        # Fast enough to sum directly?
        # Even better, we use the Euler product (idea stolen from pari)
        m = (float(wp) / (s - 1) + 1)
        if m < 30:
            needed_terms = int(2.0**m + 1)
            if needed_terms < int(wp / 2.54 + 5) / 10:
                t = fone
                for k in list_primes(needed_terms):
                    #print k, needed_terms
                    powprec = int(wp - s * math.log(k, 2))
                    if powprec < 2:
                        break
                    a = mpf_sub(fone, mpf_pow_int(from_int(k), -s, powprec),
                                wp)
                    t = mpf_mul(t, a, wp)
                return mpf_div(fone, t, wp)
    # Use Borwein's algorithm
    n = int(wp / 2.54 + 5)
    d = borwein_coefficients(n)
    t = MPZ_ZERO
    s = MPZ(s)
    for k in xrange(n):
        t += (((-1)**k * (d[k] - d[n])) << wp) // (k + 1)**s
    t = (t << wp) // (-d[n])
    t = (t << wp) // ((1 << wp) - (1 << (wp + 1 - s)))
    if (s in zeta_int_cache
            and zeta_int_cache[s][0] < wp) or (s not in zeta_int_cache):
        zeta_int_cache[s] = (wp, from_man_exp(t, -wp - wp))
    return from_man_exp(t, -wp - wp, prec, rnd)
예제 #8
0
파일: gammazeta.py 프로젝트: xinjie0831/AMC
def apery_fixed(prec):
    prec += 20
    d = MPZ_ONE << prec
    term = MPZ(77) << prec
    n = 1
    s = MPZ_ZERO
    while term:
        s += term
        d *= (n**10)
        d //= (((2 * n + 1)**5) * (2 * n)**5)
        term = (-1)**n * (205 * (n**2) + 250 * n + 77) * d
        n += 1
    return s >> (20 + 6)
예제 #9
0
def mpc_nthroot_fixed(a, b, n, prec):
    # a, b signed integers at fixed precision prec
    start = 50
    a1 = int(rshift(a, prec - n * start))
    b1 = int(rshift(b, prec - n * start))
    try:
        r = (a1 + 1j * b1)**(1.0 / n)
        re = r.real
        im = r.imag
        re = MPZ(int(re))
        im = MPZ(int(im))
    except OverflowError:
        a1 = from_int(a1, start)
        b1 = from_int(b1, start)
        fn = from_int(n)
        nth = mpf_rdiv_int(1, fn, start)
        re, im = mpc_pow((a1, b1), (nth, fzero), start)
        re = to_int(re)
        im = to_int(im)
    extra = 10
    prevp = start
    extra1 = n
    for p in giant_steps(start, prec + extra):
        # this is slow for large n, unlike int_pow_fixed
        re2, im2 = complex_int_pow(re, im, n - 1)
        re2 = rshift(re2, (n - 1) * prevp - p - extra1)
        im2 = rshift(im2, (n - 1) * prevp - p - extra1)
        r4 = (re2 * re2 + im2 * im2) >> (p + extra1)
        ap = rshift(a, prec - p)
        bp = rshift(b, prec - p)
        rec = (ap * re2 + bp * im2) >> p
        imc = (-ap * im2 + bp * re2) >> p
        reb = (rec << p) // r4
        imb = (imc << p) // r4
        re = (reb + (n - 1) * lshift(re, p - prevp)) // n
        im = (imb + (n - 1) * lshift(im, p - prevp)) // n
        prevp = p
    return re, im
예제 #10
0
파일: libintmath.py 프로젝트: jarmoza/twic2
def stirling1(n, k):
    """
    Stirling number of the first kind.
    """
    if n < 0 or k < 0:
        raise ValueError
    if k >= n:
        return MPZ(n == k)
    if k < 1:
        return MPZ_ZERO
    L = [MPZ_ZERO] * (k + 1)
    L[1] = MPZ_ONE
    for m in xrange(2, n + 1):
        for j in xrange(min(k, m), 0, -1):
            L[j] = (m - 1) * L[j] + L[j - 1]
    return (-1)**(n + k) * L[k]
예제 #11
0
def atan_newton(x, prec):
    if prec >= 100:
        r = math.atan((x >> (prec - 53)) / 2.0**53)
    else:
        r = math.atan(x / 2.0**prec)
    prevp = 50
    r = MPZ(int(r * 2.0**53) >> (53 - prevp))
    extra_p = 50
    for wp in giant_steps(prevp, prec):
        wp += extra_p
        r = r << (wp - prevp)
        cos, sin = cos_sin_fixed(r, wp)
        tan = (sin << wp) // cos
        a = ((tan - rshift(x, prec - wp)) << wp) // ((MPZ_ONE << wp) +
                                                     ((tan**2) >> wp))
        r = r - a
        prevp = wp
    return rshift(r, prevp - prec)
예제 #12
0
def str_to_man_exp(x, base=10):
    """Helper function for from_str."""
    # Verify that the input is a valid float literal
    float(x)
    # Split into mantissa, exponent
    x = x.lower()
    parts = x.split('e')
    if len(parts) == 1:
        exp = 0
    else:  # == 2
        x = parts[0]
        exp = int(parts[1])
    # Look for radix point in mantissa
    parts = x.split('.')
    if len(parts) == 2:
        a, b = parts[0], parts[1].rstrip('0')
        exp -= len(b)
        x = a + b
    x = MPZ(int(x, base))
    return x, exp
예제 #13
0
파일: libintmath.py 프로젝트: jarmoza/twic2
def numeral_gmpy(n, base=10, size=0, digits=stddigits):
    """Represent the integer n as a string of digits in the given base.
    Recursive division is used to make this function about 3x faster
    than Python's str() for converting integers to decimal strings.

    The 'size' parameters specifies the number of digits in n; this
    number is only used to determine splitting points and need not be
    exact."""
    if n < 0:
        return "-" + numeral(-n, base, size, digits)
    # gmpy.digits() may cause a segmentation fault when trying to convert
    # extremely large values to a string. The size limit may need to be
    # adjusted on some platforms, but 1500000 works on Windows and Linux.
    if size < 1500000:
        return gmpy.digits(n, base)
    # Divide in half
    half = (size // 2) + (size & 1)
    A, B = divmod(n, MPZ(base)**half)
    ad = numeral(A, base, half, digits)
    bd = numeral(B, base, half, digits).rjust(half, "0")
    return ad + bd
예제 #14
0
def bs_chudnovsky(a, b, level, verbose):
    """
    Computes the sum from a to b of the series in the Chudnovsky
    formula. Returns g, p, q where p/q is the sum as an exact
    fraction and g is a temporary value used to save work
    for recursive calls.
    """
    if b - a == 1:
        g = MPZ((6 * b - 5) * (2 * b - 1) * (6 * b - 1))
        p = b**3 * CHUD_C**3 // 24
        q = (-1)**b * g * (CHUD_A + CHUD_B * b)
    else:
        if verbose and level < 4:
            print "  binary splitting", a, b
        mid = (a + b) // 2
        g1, p1, q1 = bs_chudnovsky(a, mid, level + 1, verbose)
        g2, p2, q2 = bs_chudnovsky(mid, b, level + 1, verbose)
        p = p1 * p2
        g = g1 * g2
        q = q1 * p2 + q2 * g1
    return g, p, q
예제 #15
0
def nthroot_fixed(y, n, prec, exp1):
    start = 50
    try:
        y1 = rshift(y, prec - n * start)
        r = MPZ(int(y1**(1.0 / n)))
    except OverflowError:
        y1 = from_int(y1, start)
        fn = from_int(n)
        fn = mpf_rdiv_int(1, fn, start)
        r = mpf_pow(y1, fn, start)
        r = to_int(r)
    extra = 10
    extra1 = n
    prevp = start
    for p in giant_steps(start, prec + extra):
        pm, pe = int_pow_fixed(r, n - 1, prevp)
        r2 = rshift(pm, (n - 1) * prevp - p - pe - extra1)
        B = lshift(y, 2 * p - prec + extra1) // r2
        r = (B + (n - 1) * lshift(r, p - prevp)) // n
        prevp = p
    return r
예제 #16
0
파일: libintmath.py 프로젝트: jarmoza/twic2
def eulernum(m, _cache={0: MPZ_ONE}):
    r"""
    Computes the Euler numbers `E(n)`, which can be defined as
    coefficients of the Taylor expansion of `1/cosh x`:

    .. math ::

        \frac{1}{\cosh x} = \sum_{n=0}^\infty \frac{E_n}{n!} x^n

    Example::

        >>> [int(eulernum(n)) for n in range(11)]
        [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521]
        >>> [int(eulernum(n)) for n in range(11)]   # test cache
        [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521]

    """
    # for odd m > 1, the Euler numbers are zero
    if m & 1:
        return MPZ_ZERO
    f = _cache.get(m)
    if f:
        return f
    MAX = MAX_EULER_CACHE
    n = m
    a = [MPZ(_) for _ in [0, 0, 1, 0, 0, 0]]
    for n in range(1, m + 1):
        for j in range(n + 1, -1, -2):
            a[j + 1] = (j - 1) * a[j] + (j + 1) * a[j + 2]
        a.append(0)
        suma = 0
        for k in range(n + 1, -1, -2):
            suma += a[k + 1]
            if n <= MAX:
                _cache[n] = ((-1)**(n // 2)) * (suma // 2**n)
        if n == m:
            return ((-1)**(n // 2)) * suma // 2**n
예제 #17
0
파일: libintmath.py 프로젝트: jarmoza/twic2
def sqrt_fixed(x, prec):
    return isqrt_fast(x << prec)


sqrt_fixed2 = sqrt_fixed

if BACKEND == 'gmpy':
    if gmpy.version() >= '2':
        isqrt_small = isqrt_fast = isqrt = gmpy.isqrt
        sqrtrem = gmpy.isqrt_rem
    else:
        isqrt_small = isqrt_fast = isqrt = gmpy.sqrt
        sqrtrem = gmpy.sqrtrem
elif BACKEND == 'sage':
    isqrt_small = isqrt_fast = isqrt = \
        getattr(sage_utils, "isqrt", lambda n: MPZ(n).isqrt())
    sqrtrem = lambda n: MPZ(n).sqrtrem()
else:
    isqrt_small = isqrt_small_python
    isqrt_fast = isqrt_fast_python
    isqrt = isqrt_python
    sqrtrem = sqrtrem_python


def ifib(n, _cache={}):
    """Computes the nth Fibonacci number as an integer, for
    integer n."""
    if n < 0:
        return (-1)**(-n + 1) * ifib(-n)
    if n in _cache:
        return _cache[n]
예제 #18
0
파일: libintmath.py 프로젝트: jarmoza/twic2
 def gmpy_trailing(n):
     """Count the number of trailing zero bits in abs(n) using gmpy."""
     if n: return MPZ(n).scan1()
     else: return 0
예제 #19
0
파일: gammazeta.py 프로젝트: xinjie0831/AMC
def mpf_bernoulli(n, prec, rnd=None):
    """Computation of Bernoulli numbers (numerically)"""
    if n < 2:
        if n < 0:
            raise ValueError("Bernoulli numbers only defined for n >= 0")
        if n == 0:
            return fone
        if n == 1:
            return mpf_neg(fhalf)
    # For odd n > 1, the Bernoulli numbers are zero
    if n & 1:
        return fzero
    # If precision is extremely high, we can save time by computing
    # the Bernoulli number at a lower precision that is sufficient to
    # obtain the exact fraction, round to the exact fraction, and
    # convert the fraction back to an mpf value at the original precision
    if prec > BERNOULLI_PREC_CUTOFF and prec > bernoulli_size(n) * 1.1 + 1000:
        p, q = bernfrac(n)
        return from_rational(p, q, prec, rnd or round_floor)
    if n > MAX_BERNOULLI_CACHE:
        return mpf_bernoulli_huge(n, prec, rnd)
    wp = prec + 30
    # Reuse nearby precisions
    wp += 32 - (prec & 31)
    cached = bernoulli_cache.get(wp)
    if cached:
        numbers, state = cached
        if n in numbers:
            if not rnd:
                return numbers[n]
            return mpf_pos(numbers[n], prec, rnd)
        m, bin, bin1 = state
        if n - m > 10:
            return mpf_bernoulli_huge(n, prec, rnd)
    else:
        if n > 10:
            return mpf_bernoulli_huge(n, prec, rnd)
        numbers = {0: fone}
        m, bin, bin1 = state = [2, MPZ(10), MPZ_ONE]
        bernoulli_cache[wp] = (numbers, state)
    while m <= n:
        #print m
        case = m % 6
        # Accurately estimate size of B_m so we can use
        # fixed point math without using too much precision
        szbm = bernoulli_size(m)
        s = 0
        sexp = max(0, szbm) - wp
        if m < 6:
            a = MPZ_ZERO
        else:
            a = bin1
        for j in xrange(1, m // 6 + 1):
            usign, uman, uexp, ubc = u = numbers[m - 6 * j]
            if usign:
                uman = -uman
            s += lshift(a * uman, uexp - sexp)
            # Update inner binomial coefficient
            j6 = 6 * j
            a *= ((m - 5 - j6) * (m - 4 - j6) * (m - 3 - j6) * (m - 2 - j6) *
                  (m - 1 - j6) * (m - j6))
            a //= ((4 + j6) * (5 + j6) * (6 + j6) * (7 + j6) * (8 + j6) *
                   (9 + j6))
        if case == 0: b = mpf_rdiv_int(m + 3, f3, wp)
        if case == 2: b = mpf_rdiv_int(m + 3, f3, wp)
        if case == 4: b = mpf_rdiv_int(-m - 3, f6, wp)
        s = from_man_exp(s, sexp, wp)
        b = mpf_div(mpf_sub(b, s, wp), from_int(bin), wp)
        numbers[m] = b
        m += 2
        # Update outer binomial coefficient
        bin = bin * ((m + 2) * (m + 3)) // (m * (m - 1))
        if m > 6:
            bin1 = bin1 * ((2 + m) * (3 + m)) // ((m - 7) * (m - 6))
        state[:] = [m, bin, bin1]
예제 #20
0
series contains only rational terms. This makes binary splitting very
efficient.

The recurrence formulas for the binary splitting were taken from
ftp://ftp.gmplib.org/pub/src/gmp-chudnovsky.c

Previously, Machin's formula was used at low precision and the AGM iteration
was used at high precision. However, the Chudnovsky series is essentially as
fast as the Machin formula at low precision and in practice about 3x faster
than the AGM at high precision (despite theoretically having a worse
asymptotic complexity), so there is no reason not to use it in all cases.

"""

# Constants in Chudnovsky's series
CHUD_A = MPZ(13591409)
CHUD_B = MPZ(545140134)
CHUD_C = MPZ(640320)
CHUD_D = MPZ(12)


def bs_chudnovsky(a, b, level, verbose):
    """
    Computes the sum from a to b of the series in the Chudnovsky
    formula. Returns g, p, q where p/q is the sum as an exact
    fraction and g is a temporary value used to save work
    for recursive calls.
    """
    if b - a == 1:
        g = MPZ((6 * b - 5) * (2 * b - 1) * (6 * b - 1))
        p = b**3 * CHUD_C**3 // 24
예제 #21
0
파일: libintmath.py 프로젝트: jarmoza/twic2
def bin_to_radix(x, xbits, base, bdigits):
    """Changes radix of a fixed-point number; i.e., converts
    x * 2**xbits to floor(x * 10**bdigits)."""
    return x * (MPZ(base)**bdigits) >> xbits
예제 #22
0
파일: libintmath.py 프로젝트: jarmoza/twic2
def sage_trailing(n):
    return MPZ(n).trailing_zero_bits()
예제 #23
0
파일: libintmath.py 프로젝트: jarmoza/twic2
def gmpy_bitcount(n):
    """Calculate bit size of the nonnegative integer n."""
    if n: return MPZ(n).numdigits(2)
    else: return 0
예제 #24
0
def from_pickable(x):
    sign, man, exp, bc = x
    return (sign, MPZ(man, 16), exp, bc)
예제 #25
0
def isqrt_python(x):
    """Integer square root with correct (floor) rounding."""
    return sqrtrem_python(x)[0]


def sqrt_fixed(x, prec):
    return isqrt_fast(x << prec)


sqrt_fixed2 = sqrt_fixed

if BACKEND == 'gmpy':
    isqrt_small = isqrt_fast = isqrt = gmpy.sqrt
    sqrtrem = gmpy.sqrtrem
elif BACKEND == 'sage':
    isqrt_small = isqrt_fast = isqrt = lambda n: MPZ(n).isqrt()
    sqrtrem = lambda n: MPZ(n).sqrtrem()
else:
    isqrt_small = isqrt_small_python
    isqrt_fast = isqrt_fast_python
    isqrt = isqrt_python
    sqrtrem = sqrtrem_python


def ifib(n, _cache={}):
    """Computes the nth Fibonacci number as an integer, for
    integer n."""
    if n < 0:
        return (-1)**(-n + 1) * ifib(-n)
    if n in _cache:
        return _cache[n]