Example #1
0
def npartitions(n, verbose=False):
    """
    Calculate the partition function P(n), i.e. the number of ways that
    n can be written as a sum of positive integers.

    P(n) is computed using the Hardy-Ramanujan-Rademacher formula,
    described e.g. at http://mathworld.wolfram.com/PartitionFunctionP.html

    The correctness of this implementation has been tested for 10**n
    up to n = 8.
    """
    n = int(n)
    if n < 0: return 0
    if n <= 5: return [1, 1, 2, 3, 5, 7][n]
    # Estimate number of bits in p(n). This formula could be tidied
    pbits = int((math.pi*(2*n/3.)**0.5-math.log(4*n))/math.log(10)+1)*\
        math.log(10,2)
    prec = p = int(pbits*1.1 + 100)
    s = fzero
    M = max(6, int(0.24*n**0.5+4))
    sq23pi = mpf_mul(mpf_sqrt(from_rational(2,3,p), p), mpf_pi(p), p)
    sqrt8 = mpf_sqrt(from_int(8), p)
    for q in xrange(1, M):
        a = A(n,q,p)
        d = D(n,q,p, sq23pi, sqrt8)
        s = mpf_add(s, mpf_mul(a, d), prec)
        if verbose:
            print "step", q, "of", M, to_str(a, 10), to_str(d, 10)
        # On average, the terms decrease rapidly in magnitude. Dynamically
        # reducing the precision greatly improves performance.
        p = bitcount(abs(to_int(d))) + 50
    np = to_int(mpf_add(s, fhalf, prec))
    return int(np)
Example #2
0
 def __add__(self, other):
     if (other is S.NaN) or (self is NaN):
         return S.NaN
     if isinstance(other, Number):
         rhs, prec = other._as_mpf_op(self._prec)
         return Real._new(mlib.mpf_add(self._mpf_, rhs, prec, rnd), prec)
     return Number.__add__(self, other)
Example #3
0
def evalf_log(expr, prec, options):
    arg = expr.args[0]
    workprec = prec+10
    xre, xim, xacc, _ = evalf(arg, workprec, options)

    if xim:
        # XXX: use get_abs etc instead
        re = evalf_log(C.log(C.abs(arg, evaluate=False), evaluate=False), prec, options)
        im = mpf_atan2(xim, xre or fzero, prec)
        return re[0], im, re[2], prec

    imaginary_term = (mpf_cmp(xre, fzero) < 0)

    re = mpf_log(mpf_abs(xre), prec, round_nearest)
    size = fastlog(re)
    if prec - size > workprec:
        # We actually need to compute 1+x accurately, not x
        arg = C.Add(S.NegativeOne,arg,evaluate=False)
        xre, xim, xre_acc, xim_acc = evalf_add(arg, prec, options)
        prec2 = workprec - fastlog(xre)
        re = mpf_log(mpf_add(xre, fone, prec2), prec, round_nearest)

    re_acc = prec

    if imaginary_term:
        return re, mpf_pi(prec), re_acc, prec
    else:
        return re, None, re_acc, None
Example #4
0
 def __add__(self, other):
     if (other is S.NaN) or (self is NaN):
         return S.NaN
     if isinstance(other, Number):
         rhs, prec = other._as_mpf_op(self._prec)
         return Real._new(mlib.mpf_add(self._mpf_, rhs, prec, rnd), prec)
     return Number.__add__(self, other)
Example #5
0
 def __add__(self, other):
     try:
         other = _sympify(other)
     except SympifyError:
         return NotImplemented
     if (other is S.NaN) or (self is NaN):
         return S.NaN
     if isinstance(other, Number):
         rhs, prec = other._as_mpf_op(self._prec)
         return Real._new(mlib.mpf_add(self._mpf_, rhs, prec, rnd), prec)
     return Number.__add__(self, other)
Example #6
0
 def __add__(self, other):
     try:
         other = _sympify(other)
     except SympifyError:
         return NotImplemented
     if (other is S.NaN) or (self is NaN):
         return S.NaN
     if isinstance(other, Number):
         rhs, prec = other._as_mpf_op(self._prec)
         return Real._new(mlib.mpf_add(self._mpf_, rhs, prec, rnd), prec)
     return Number.__add__(self, other)
Example #7
0
def A(n, j, prec):
    """Compute the inner sum in the HRR formula."""
    if j == 1:
        return fone
    s = fzero
    pi = pi_fixed(prec)
    for h in xrange(1, j):
        if igcd(h,j) != 1:
            continue
        # & with mask to compute fractional part of fixed-point number
        one = 1 << prec
        onemask = one - 1
        half = one >> 1
        g = 0
        if j >= 3:
            for k in xrange(1, j):
                t = h*k*one//j
                if t > 0: frac = t & onemask
                else:     frac = -((-t) & onemask)
                g += k*(frac - half)
        g = ((g - 2*h*n*one)*pi//j) >> prec
        s = mpf_add(s, mpf_cos(from_man_exp(g, -prec), prec), prec)
    return s