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)
def evalf_trig(v, prec, options): """ This function handles sin and cos of real arguments. TODO: should also handle tan and complex arguments. """ if v.func is C.cos: func = mpf_cos elif v.func is C.sin: func = mpf_sin else: raise NotImplementedError arg = v.args[0] # 20 extra bits is possibly overkill. It does make the need # to restart very unlikely xprec = prec + 20 re, im, re_accuracy, im_accuracy = evalf(arg, xprec, options) if im: raise NotImplementedError if not re: if v.func is C.cos: return fone, None, prec, None elif v.func is C.sin: return None, None, None, None else: raise NotImplementedError # For trigonometric functions, we are interested in the # fixed-point (absolute) accuracy of the argument. xsize = fastlog(re) # Magnitude <= 1.0. OK to compute directly, because there is no # danger of hitting the first root of cos (with sin, magnitude # <= 2.0 would actually be ok) if xsize < 1: return func(re, prec, round_nearest), None, prec, None # Very large if xsize >= 10: xprec = prec + xsize re, im, re_accuracy, im_accuracy = evalf(arg, xprec, options) # Need to repeat in case the argument is very close to a # multiple of pi (or pi/2), hitting close to a root while 1: y = func(re, prec, round_nearest) ysize = fastlog(y) gap = -ysize accuracy = (xprec - xsize) - gap if accuracy < prec: if options.get('verbose'): print "SIN/COS", accuracy, "wanted", prec, "gap", gap print to_str(y,10) if xprec > options.get('maxprec', DEFAULT_MAXPREC): return y, None, accuracy, None xprec += gap re, im, re_accuracy, im_accuracy = evalf(arg, xprec, options) continue else: return y, None, prec, None
def _print_Real(self, expr): prec = expr._prec if prec < 5: dps = 0 else: dps = prec_to_dps(expr._prec) return mlib.to_str(expr._mpf_, dps, strip_zeros=False)
def _print_Real(self, expr): prec = expr._prec if prec < 5: dps = 0 else: dps = prec_to_dps(expr._prec) if self._settings["full_prec"] == True: strip = False elif self._settings["full_prec"] == False: strip = True elif self._settings["full_prec"] == "auto": strip = self._print_level > 1 return mlib.to_str(expr._mpf_, dps, strip_zeros=strip)
def evalf(x, prec, options): try: r = evalf_table[x.func](x, prec, options) except KeyError: #r = finalize_complex(x._eval_evalf(prec)._mpf_, fzero, prec) try: # Fall back to ordinary evalf if possible if 'subs' in options: x = x.subs(options['subs']) r = x._eval_evalf(prec)._mpf_, None, prec, None except AttributeError: raise NotImplementedError if options.get("verbose"): print "### input", x print "### output", to_str(r[0] or fzero, 50) #print "### raw", r[0], r[2] print if options.get("chop"): r = chop_parts(r, prec) if options.get("strict"): check_target(x, r, prec) return r
def _print_Real(self, expr): # Based off of that in StrPrinter dps = prec_to_dps(expr._prec) str_real = mlib.to_str(expr._mpf_, dps, strip_zeros=True) # Must always have a mul symbol (as 2.5 10^{20} just looks odd) seperator = r" \times " if self._settings["mul_symbol"] is not None: seperator = self._settings["mul_symbol_latex"] if "e" in str_real: (mant, exp) = str_real.split("e") if exp[0] == "+": exp = exp[1:] return r"%s%s10^{%s}" % (mant, seperator, exp) elif str_real == "+inf": return r"\infty" elif str_real == "-inf": return r"- \intfy" else: return str_real
def _print_Real(self, expr): dps = prec_to_dps(expr._prec) r = mlib.to_str(expr._mpf_, repr_dps(expr._prec)) return "%s('%s', prec=%i)" % (expr.__class__.__name__, r, dps)