def twinprime_fixed(prec): def I(n): return sum( moebius(d) << (n // d) for d in xrange(1, n + 1) if not n % d) // n wp = 2 * prec + 30 res = fone primes = [from_rational(1, p, wp) for p in [2, 3, 5, 7]] ppowers = [mpf_mul(p, p, wp) for p in primes] n = 2 while 1: a = mpf_zeta_int(n, wp) for i in range(4): a = mpf_mul(a, mpf_sub(fone, ppowers[i]), wp) ppowers[i] = mpf_mul(ppowers[i], primes[i], wp) a = mpf_pow_int(a, -I(n), wp) if mpf_pos(a, prec + 10, 'n') == fone: break #from libmpf import to_str #print n, to_str(mpf_sub(fone, a), 6) res = mpf_mul(res, a, wp) n += 1 res = mpf_mul(res, from_int(3 * 15 * 35), wp) res = mpf_div(res, from_int(4 * 16 * 36), wp) return to_fixed(res, prec)
def mpf_gamma_int(n, prec, rounding=round_fast): if n < 1000: return from_int(ifac(n-1), prec, rounding) # XXX: choose the cutoff less arbitrarily size = int(n*math.log(n,2)) if prec > size/20.0: return from_int(ifac(n-1), prec, rounding) return mpf_gamma(from_int(n), prec, rounding)
def mpf_gamma_int(n, prec, rounding=round_fast): if n < 1000: return from_int(int_fac(n - 1), prec, rounding) # XXX: choose the cutoff less arbitrarily size = int(n * math.log(n, 2)) if prec > size / 20.0: return from_int(int_fac(n - 1), prec, rounding) return mpf_gamma(from_int(n), prec, rounding)
def mpc_psi(m, z, prec, rnd=round_fast): """ Computation of the polygamma function of arbitrary integer order m >= 0, for a complex argument z. """ if m == 0: return mpc_psi0(z, prec, rnd) re, im = z wp = prec + 20 sign, man, exp, bc = re if not man: if re == finf and im == fzero: return (fzero, fzero) if re == fnan: return fnan # Recurrence w = to_int(re) n = int(0.4 * wp + 4 * m) s = mpc_zero if w < n: for k in xrange(w, n): t = mpc_pow_int(z, -m - 1, wp) s = mpc_add(s, t, wp) z = mpc_add_mpf(z, fone, wp) zm = mpc_pow_int(z, -m, wp) z2 = mpc_pow_int(z, -2, wp) # 1/m*(z+N)^m integral_term = mpc_div_mpf(zm, from_int(m), wp) s = mpc_add(s, integral_term, wp) # 1/2*(z+N)^(-(m+1)) s = mpc_add(s, mpc_mul_mpf(mpc_div(zm, z, wp), fhalf, wp), wp) a = m + 1 b = 2 k = 1 # Important: we want to sum up to the *relative* error, # not the absolute error, because psi^(m)(z) might be tiny magn = mpc_abs(s, 10) magn = magn[2] + magn[3] eps = mpf_shift(fone, magn - wp + 2) while 1: zm = mpc_mul(zm, z2, wp) bern = mpf_bernoulli(2 * k, wp) scal = mpf_mul_int(bern, a, wp) scal = mpf_div(scal, from_int(b), wp) term = mpc_mul_mpf(zm, scal, wp) s = mpc_add(s, term, wp) szterm = mpc_abs(term, 10) if k > 2 and mpf_le(szterm, eps): break #print k, to_str(szterm, 10), to_str(eps, 10) a *= (m + 2 * k) * (m + 2 * k + 1) b *= (2 * k + 1) * (2 * k + 2) k += 1 # Scale and sign factor v = mpc_mul_mpf(s, mpf_gamma(from_int(m + 1), wp), prec, rnd) if not (m & 1): v = mpf_neg(v[0]), mpf_neg(v[1]) return v
def mpc_psi(m, z, prec, rnd=round_fast): """ Computation of the polygamma function of arbitrary integer order m >= 0, for a complex argument z. """ if m == 0: return mpc_psi0(z, prec, rnd) re, im = z wp = prec + 20 sign, man, exp, bc = re if not man: if re == finf and im == fzero: return (fzero, fzero) if re == fnan: return fnan # Recurrence w = to_int(re) n = int(0.4*wp + 4*m) s = mpc_zero if w < n: for k in xrange(w, n): t = mpc_pow_int(z, -m-1, wp) s = mpc_add(s, t, wp) z = mpc_add_mpf(z, fone, wp) zm = mpc_pow_int(z, -m, wp) z2 = mpc_pow_int(z, -2, wp) # 1/m*(z+N)^m integral_term = mpc_div_mpf(zm, from_int(m), wp) s = mpc_add(s, integral_term, wp) # 1/2*(z+N)^(-(m+1)) s = mpc_add(s, mpc_mul_mpf(mpc_div(zm, z, wp), fhalf, wp), wp) a = m + 1 b = 2 k = 1 # Important: we want to sum up to the *relative* error, # not the absolute error, because psi^(m)(z) might be tiny magn = mpc_abs(s, 10) magn = magn[2]+magn[3] eps = mpf_shift(fone, magn-wp+2) while 1: zm = mpc_mul(zm, z2, wp) bern = mpf_bernoulli(2*k, wp) scal = mpf_mul_int(bern, a, wp) scal = mpf_div(scal, from_int(b), wp) term = mpc_mul_mpf(zm, scal, wp) s = mpc_add(s, term, wp) szterm = mpc_abs(term, 10) if k > 2 and mpf_le(szterm, eps): break #print k, to_str(szterm, 10), to_str(eps, 10) a *= (m+2*k)*(m+2*k+1) b *= (2*k+1)*(2*k+2) k += 1 # Scale and sign factor v = mpc_mul_mpf(s, mpf_gamma(from_int(m+1), wp), prec, rnd) if not (m & 1): v = mpf_neg(v[0]), mpf_neg(v[1]) return v
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)
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)
def exp_newton(x, prec): extra = 10 r = mpf_exp(x, 60) start = 50 prevp = start for p in giant_steps(start, prec+extra, 4): h = mpf_sub(x, mpf_log(r, p), p) h2 = mpf_mul(h, h, p) h3 = mpf_mul(h2, h, p) h4 = mpf_mul(h2, h2, p) t = mpf_add(h, mpf_shift(h2, -1), p) t = mpf_add(t, mpf_div(h3, from_int(6, p), p), p) t = mpf_add(t, mpf_div(h4, from_int(24, p), p), p) t = mpf_mul(r, t, p) r = mpf_add(r, t, p) return r
def khinchin_fixed(prec): wp = int(prec + prec**0.5 + 15) s = MP_ZERO fac = from_int(4) t = ONE = MP_ONE << wp pi = mpf_pi(wp) pipow = twopi2 = mpf_shift(mpf_mul(pi, pi, wp), 2) n = 1 while 1: zeta2n = mpf_abs(mpf_bernoulli(2 * n, wp)) zeta2n = mpf_mul(zeta2n, pipow, wp) zeta2n = mpf_div(zeta2n, fac, wp) zeta2n = to_fixed(zeta2n, wp) term = (((zeta2n - ONE) * t) // n) >> wp if term < 100: break #if not n % 100: # print n, nstr(ln(term)) s += term t += ONE // (2 * n + 1) - ONE // (2 * n) n += 1 fac = mpf_mul_int(fac, (2 * n) * (2 * n - 1), wp) pipow = mpf_mul(pipow, twopi2, wp) s = (s << wp) // ln2_fixed(wp) K = mpf_exp(from_man_exp(s, -wp), wp) K = to_fixed(K, prec) return K
def khinchin_fixed(prec): wp = int(prec + prec**0.5 + 15) s = MPZ_ZERO fac = from_int(4) t = ONE = MPZ_ONE << wp pi = mpf_pi(wp) pipow = twopi2 = mpf_shift(mpf_mul(pi, pi, wp), 2) n = 1 while 1: zeta2n = mpf_abs(mpf_bernoulli(2*n, wp)) zeta2n = mpf_mul(zeta2n, pipow, wp) zeta2n = mpf_div(zeta2n, fac, wp) zeta2n = to_fixed(zeta2n, wp) term = (((zeta2n - ONE) * t) // n) >> wp if term < 100: break #if not n % 10: # print n, math.log(int(abs(term))) s += term t += ONE//(2*n+1) - ONE//(2*n) n += 1 fac = mpf_mul_int(fac, (2*n)*(2*n-1), wp) pipow = mpf_mul(pipow, twopi2, wp) s = (s << wp) // ln2_fixed(wp) K = mpf_exp(from_man_exp(s, -wp), wp) K = to_fixed(K, prec) return K
def __rsub__(s, t): prec, rounding = prec_rounding if type(t) in int_types: return make_mpf(mpf_sub(from_int(t), s._mpf_, prec, rounding)) t = mpf_convert_lhs(t) if t is NotImplemented: return t return t - s
def calc_spouge_coefficients(a, prec): wp = prec + int(a * 1.4) c = [0] * a # b = exp(a-1) b = mpf_exp(from_int(a - 1), wp) # e = exp(1) e = mpf_exp(fone, wp) # sqrt(2*pi) sq2pi = mpf_sqrt(mpf_shift(mpf_pi(wp), 1), wp) c[0] = to_fixed(sq2pi, prec) for k in xrange(1, a): # c[k] = ((-1)**(k-1) * (a-k)**k) * b / sqrt(a-k) term = mpf_mul_int(b, ((-1)**(k - 1) * (a - k)**k), wp) term = mpf_div(term, mpf_sqrt(from_int(a - k), wp), wp) c[k] = to_fixed(term, prec) # b = b / (e * k) b = mpf_div(b, mpf_mul(e, from_int(k), wp), wp) return c
def calc_spouge_coefficients(a, prec): wp = prec + int(a*1.4) c = [0] * a # b = exp(a-1) b = mpf_exp(from_int(a-1), wp) # e = exp(1) e = mpf_exp(fone, wp) # sqrt(2*pi) sq2pi = mpf_sqrt(mpf_shift(mpf_pi(wp), 1), wp) c[0] = to_fixed(sq2pi, prec) for k in xrange(1, a): # c[k] = ((-1)**(k-1) * (a-k)**k) * b / sqrt(a-k) term = mpf_mul_int(b, ((-1)**(k-1) * (a-k)**k), wp) term = mpf_div(term, mpf_sqrt(from_int(a-k), wp), wp) c[k] = to_fixed(term, prec) # b = b / (e * k) b = mpf_div(b, mpf_mul(e, from_int(k), wp), wp) return c
def mpf_gamma(x, prec, rounding=round_fast, p1=1): """ Computes the gamma function of a real floating-point argument. With p1=0, computes a factorial instead. """ sign, man, exp, bc = x if not man: if x == finf: return finf if x == fninf or x == fnan: return fnan # More precision is needed for enormous x. TODO: # use Stirling's formula + Euler-Maclaurin summation size = exp + bc if size > 5: size = int(size * math.log(size, 2)) wp = prec + max(0, size) + 15 if exp >= 0: if sign or (p1 and not man): raise ValueError("gamma function pole") # A direct factorial is fastest if exp + bc <= 10: return from_int(int_fac((man << exp) - p1), prec, rounding) reflect = sign or exp + bc < -1 if p1: # Should be done exactly! x = mpf_sub(x, fone, bc - exp + 2) # x < 0.25 if reflect: # gamma = pi / (sin(pi*x) * gamma(1-x)) wp += 15 pix = mpf_mul(x, mpf_pi(wp), wp) t = mpf_sin_pi(x, wp) g = mpf_gamma(mpf_sub(fone, x, wp), wp) return mpf_div(pix, mpf_mul(t, g, wp), prec, rounding) sprec, a, c = get_spouge_coefficients(wp) s = spouge_sum_real(x, sprec, a, c) # gamma = exp(log(x+a)*(x+0.5) - xpa) * s xpa = mpf_add(x, from_int(a), wp) logxpa = mpf_log(xpa, wp) xph = mpf_add(x, fhalf, wp) t = mpf_sub(mpf_mul(logxpa, xph, wp), xpa, wp) t = mpf_mul(mpf_exp(t, wp), s, prec, rounding) return t
def mpf_gamma(x, prec, rounding=round_fast, p1=1): """ Computes the gamma function of a real floating-point argument. With p1=0, computes a factorial instead. """ sign, man, exp, bc = x if not man: if x == finf: return finf if x == fninf or x == fnan: return fnan # More precision is needed for enormous x. TODO: # use Stirling's formula + Euler-Maclaurin summation size = exp + bc if size > 5: size = int(size * math.log(size,2)) wp = prec + max(0, size) + 15 if exp >= 0: if sign or (p1 and not man): raise ValueError("gamma function pole") # A direct factorial is fastest if exp + bc <= 10: return from_int(ifac((man<<exp)-p1), prec, rounding) reflect = sign or exp+bc < -1 if p1: # Should be done exactly! x = mpf_sub(x, fone) # x < 0.25 if reflect: # gamma = pi / (sin(pi*x) * gamma(1-x)) wp += 15 pix = mpf_mul(x, mpf_pi(wp), wp) t = mpf_sin_pi(x, wp) g = mpf_gamma(mpf_sub(fone, x), wp) return mpf_div(pix, mpf_mul(t, g, wp), prec, rounding) sprec, a, c = get_spouge_coefficients(wp) s = spouge_sum_real(x, sprec, a, c) # gamma = exp(log(x+a)*(x+0.5) - xpa) * s xpa = mpf_add(x, from_int(a), wp) logxpa = mpf_log(xpa, wp) xph = mpf_add(x, fhalf, wp) t = mpf_sub(mpf_mul(logxpa, xph, wp), xpa, wp) t = mpf_mul(mpf_exp(t, wp), s, prec, rounding) return t
def mpi_pow(s, t, prec): ta, tb = t if ta == tb and ta not in (finf, fninf): if ta == from_int(to_int(ta)): return mpi_pow_int(s, to_int(ta), prec) if ta == fhalf: return mpi_sqrt(s, prec) u = mpi_log(s, prec + 20) v = mpi_mul(u, t, prec + 20) return mpi_exp(v, prec)
def mpf_convert_arg(x, prec, rounding): if isinstance(x, int_types): return from_int(x) if isinstance(x, float): return from_float(x) if isinstance(x, basestring): return from_str(x, prec, rounding) if isinstance(x, constant): return x.func(prec, rounding) if hasattr(x, '_mpf_'): return x._mpf_ if hasattr(x, '_mpmath_'): t = convert_lossless(x._mpmath_(prec, rounding)) if isinstance(t, mpf): return t._mpf_ raise TypeError("cannot create mpf from " + repr(x))
def mpf_convert_rhs(x): if isinstance(x, int_types): return from_int(x) if isinstance(x, float): return from_float(x) if isinstance(x, complex_types): return mpc(x) if hasattr(x, '_mpf_'): return x._mpf_ if hasattr(x, '_mpmath_'): t = convert_lossless(x._mpmath_(*prec_rounding)) if isinstance(t, mpf): return t._mpf_ return t return NotImplemented
def mpc_gamma(x, prec, rounding=round_fast, p1=1): re, im = x if im == fzero: return mpf_gamma(re, prec, rounding, p1), fzero # More precision is needed for enormous x. sign, man, exp, bc = re isign, iman, iexp, ibc = im if re == fzero: size = iexp + ibc else: size = max(exp + bc, iexp + ibc) if size > 5: size = int(size * math.log(size, 2)) reflect = sign or (exp + bc < -1) wp = prec + max(0, size) + 25 # Near x = 0 pole (TODO: other poles) if p1: if size < -prec - 5: return mpc_add_mpf(mpc_div(mpc_one, x, 2*prec+10), \ mpf_neg(mpf_euler(2*prec+10)), prec, rounding) elif size < -5: wp += (-2 * size) if p1: # Should be done exactly! re_orig = re re = mpf_sub(re, fone, bc + abs(exp) + 2) x = re, im if reflect: # Reflection formula wp += 15 pi = mpf_pi(wp), fzero pix = mpc_mul(x, pi, wp) t = mpc_sin_pi(x, wp) u = mpc_sub(mpc_one, x, wp) g = mpc_gamma(u, wp) w = mpc_mul(t, g, wp) return mpc_div(pix, w, wp) # Extremely close to the real line? # XXX: reflection formula if iexp + ibc < -wp: a = mpf_gamma(re_orig, wp) b = mpf_psi0(re_orig, wp) gamma_diff = mpf_div(a, b, wp) return mpf_pos(a, prec, rounding), mpf_mul(gamma_diff, im, prec, rounding) sprec, a, c = get_spouge_coefficients(wp) s = spouge_sum_complex(re, im, sprec, a, c) # gamma = exp(log(x+a)*(x+0.5) - xpa) * s repa = mpf_add(re, from_int(a), wp) logxpa = mpc_log((repa, im), wp) reph = mpf_add(re, fhalf, wp) t = mpc_sub(mpc_mul(logxpa, (reph, im), wp), (repa, im), wp) t = mpc_mul(mpc_exp(t, wp), s, prec, rounding) return t
def mpf_convert_arg(x, prec, rounding): if isinstance(x, int_types): return from_int(x) if isinstance(x, float): return from_float(x) if isinstance(x, basestring): return from_str(x, prec, rounding) if isinstance(x, constant): return x.func(prec, rounding) if hasattr(x, '_mpf_'): return x._mpf_ if hasattr(x, '_mpmath_'): t = mpmathify(x._mpmath_(prec, rounding)) if isinstance(t, mpf): return t._mpf_ raise TypeError("cannot create mpf from " + repr(x))
def mpf_convert_rhs(x): if isinstance(x, int_types): return from_int(x) if isinstance(x, float): return from_float(x) if isinstance(x, complex_types): return mpc(x) if hasattr(x, '_mpf_'): return x._mpf_ if hasattr(x, '_mpmath_'): t = mpmathify(x._mpmath_(*prec_rounding)) if isinstance(t, mpf): return t._mpf_ return t return NotImplemented
def log_int_fixed(n, prec): if n in log_int_cache: value, vprec = log_int_cache[n] if vprec >= prec: return value >> (vprec - prec) extra = 30 vprec = prec + extra v = to_fixed(mpf_log(from_int(n), vprec+5), vprec) if n < MAX_LOG_INT_CACHE: log_int_cache[n] = (v, vprec) return v >> extra
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 # XXX: workaround bug in gmpy if abs(re) < 0.1: re = 0 if abs(im) < 0.1: im = 0 re = MP_BASE(re) im = MP_BASE(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
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 # XXX: workaround bug in gmpy if abs(re) < 0.1: re = 0 if abs(im) < 0.1: im = 0 re = MP_BASE(re) im = MP_BASE(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
def nthroot_fixed(y, n, prec, exp1): start = 50 try: y1 = rshift(y, prec - n*start) r = MP_BASE(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
def mpc_gamma(x, prec, rounding=round_fast, p1=1): re, im = x if im == fzero: return mpf_gamma(re, prec, rounding, p1), fzero # More precision is needed for enormous x. sign, man, exp, bc = re isign, iman, iexp, ibc = im if re == fzero: size = iexp+ibc else: size = max(exp+bc, iexp+ibc) if size > 5: size = int(size * math.log(size,2)) reflect = sign or (exp+bc < -1) wp = prec + max(0, size) + 25 # Near x = 0 pole (TODO: other poles) if p1: if size < -prec-5: return mpc_add_mpf(mpc_div(mpc_one, x, 2*prec+10), \ mpf_neg(mpf_euler(2*prec+10)), prec, rounding) elif size < -5: wp += (-2*size) if p1: # Should be done exactly! re_orig = re re = mpf_sub(re, fone, bc+abs(exp)+2) x = re, im if reflect: # Reflection formula wp += 15 pi = mpf_pi(wp), fzero pix = mpc_mul(x, pi, wp) t = mpc_sin_pi(x, wp) u = mpc_sub(mpc_one, x, wp) g = mpc_gamma(u, wp) w = mpc_mul(t, g, wp) return mpc_div(pix, w, wp) # Extremely close to the real line? # XXX: reflection formula if iexp+ibc < -wp: a = mpf_gamma(re_orig, wp) b = mpf_psi0(re_orig, wp) gamma_diff = mpf_div(a, b, wp) return mpf_pos(a, prec, rounding), mpf_mul(gamma_diff, im, prec, rounding) sprec, a, c = get_spouge_coefficients(wp) s = spouge_sum_complex(re, im, sprec, a, c) # gamma = exp(log(x+a)*(x+0.5) - xpa) * s repa = mpf_add(re, from_int(a), wp) logxpa = mpc_log((repa, im), wp) reph = mpf_add(re, fhalf, wp) t = mpc_sub(mpc_mul(logxpa, (reph, im), wp), (repa, im), wp) t = mpc_mul(mpc_exp(t, wp), s, prec, rounding) return t
def nthroot_fixed(y, n, prec, exp1): start = 50 try: y1 = rshift(y, prec - n*start) r = MP_BASE(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
def mpi_from_str_a_b(x, y, percent, prec): wp = prec + 20 xa = from_str(x, wp, round_floor) xb = from_str(x, wp, round_ceiling) #ya = from_str(y, wp, round_floor) y = from_str(y, wp, round_ceiling) assert mpf_ge(y, fzero) if percent: y = mpf_mul(MAX(mpf_abs(xa), mpf_abs(xb)), y, wp, round_ceiling) y = mpf_div(y, from_int(100), wp, round_ceiling) a = mpf_sub(xa, y, prec, round_floor) b = mpf_add(xb, y, prec, round_ceiling) return a, b
def glaisher_fixed(prec): wp = prec + 30 # Number of direct terms to sum before applying the Euler-Maclaurin # formula to the tail. TODO: choose more intelligently N = int(0.33 * prec + 5) ONE = MP_ONE << wp # Euler-Maclaurin, step 1: sum log(k)/k**2 for k from 2 to N-1 s = MP_ZERO for k in range(2, N): #print k, N s += log_int_fixed(k, wp) // k**2 logN = log_int_fixed(N, wp) #logN = to_fixed(mpf_log(from_int(N), wp+20), wp) # E-M step 2: integral of log(x)/x**2 from N to inf s += (ONE + logN) // N # E-M step 3: endpoint correction term f(N)/2 s += logN // (N**2 * 2) # E-M step 4: the series of derivatives pN = N**3 a = 1 b = -2 j = 3 fac = from_int(2) k = 1 while 1: # D(2*k-1) * B(2*k) / fac(2*k) [D(n) = nth derivative] D = ((a << wp) + b * logN) // pN D = from_man_exp(D, -wp) B = mpf_bernoulli(2 * k, wp) term = mpf_mul(B, D, wp) term = mpf_div(term, fac, wp) term = to_fixed(term, wp) if abs(term) < 100: break #if not k % 10: # print k, math.log(int(abs(term)), 10) s -= term # Advance derivative twice a, b, pN, j = b - a * j, -j * b, pN * N, j + 1 a, b, pN, j = b - a * j, -j * b, pN * N, j + 1 k += 1 fac = mpf_mul_int(fac, (2 * k) * (2 * k - 1), wp) # A = exp((6*s/pi**2 + log(2*pi) + euler)/12) pi = pi_fixed(wp) s *= 6 s = (s << wp) // (pi**2 >> wp) s += euler_fixed(wp) s += to_fixed(mpf_log(from_man_exp(2 * pi, -wp), wp), wp) s //= 12 A = mpf_exp(from_man_exp(s, -wp), wp) return to_fixed(A, prec)
def glaisher_fixed(prec): wp = prec + 30 # Number of direct terms to sum before applying the Euler-Maclaurin # formula to the tail. TODO: choose more intelligently N = int(0.33*prec + 5) ONE = MPZ_ONE << wp # Euler-Maclaurin, step 1: sum log(k)/k**2 for k from 2 to N-1 s = MPZ_ZERO for k in range(2, N): #print k, N s += log_int_fixed(k, wp) // k**2 logN = log_int_fixed(N, wp) #logN = to_fixed(mpf_log(from_int(N), wp+20), wp) # E-M step 2: integral of log(x)/x**2 from N to inf s += (ONE + logN) // N # E-M step 3: endpoint correction term f(N)/2 s += logN // (N**2 * 2) # E-M step 4: the series of derivatives pN = N**3 a = 1 b = -2 j = 3 fac = from_int(2) k = 1 while 1: # D(2*k-1) * B(2*k) / fac(2*k) [D(n) = nth derivative] D = ((a << wp) + b*logN) // pN D = from_man_exp(D, -wp) B = mpf_bernoulli(2*k, wp) term = mpf_mul(B, D, wp) term = mpf_div(term, fac, wp) term = to_fixed(term, wp) if abs(term) < 100: break #if not k % 10: # print k, math.log(int(abs(term)), 10) s -= term # Advance derivative twice a, b, pN, j = b-a*j, -j*b, pN*N, j+1 a, b, pN, j = b-a*j, -j*b, pN*N, j+1 k += 1 fac = mpf_mul_int(fac, (2*k)*(2*k-1), wp) # A = exp((6*s/pi**2 + log(2*pi) + euler)/12) pi = pi_fixed(wp) s *= 6 s = (s << wp) // (pi**2 >> wp) s += euler_fixed(wp) s += to_fixed(mpf_log(from_man_exp(2*pi, -wp), wp), wp) s //= 12 A = mpf_exp(from_man_exp(s, -wp), wp) return to_fixed(A, prec)
def mertens_fixed(prec): wp = prec + 20 m = 2 s = mpf_euler(wp) while 1: t = mpf_zeta_int(m, wp) if t == fone: break t = mpf_log(t, wp) t = mpf_mul_int(t, moebius(m), wp) t = mpf_div(t, from_int(m), wp) s = mpf_add(s, t) m += 1 return to_fixed(s, prec)
def twinprime_fixed(prec): def I(n): return sum(moebius(d)<<(n//d) for d in xrange(1,n+1) if not n%d)//n wp = 2*prec + 30 res = fone primes = [from_rational(1,p,wp) for p in [2,3,5,7]] ppowers = [mpf_mul(p,p,wp) for p in primes] n = 2 while 1: a = mpf_zeta_int(n, wp) for i in range(4): a = mpf_mul(a, mpf_sub(fone, ppowers[i]), wp) ppowers[i] = mpf_mul(ppowers[i], primes[i], wp) a = mpf_pow_int(a, -I(n), wp) if mpf_pos(a, prec+10, 'n') == fone: break #from libmpf import to_str #print n, to_str(mpf_sub(fone, a), 6) res = mpf_mul(res, a, wp) n += 1 res = mpf_mul(res, from_int(3*15*35), wp) res = mpf_div(res, from_int(4*16*36), wp) return to_fixed(res, prec)
def convert_lossless(x, strings=True): """Attempt to convert x to an mpf or mpc losslessly. If x is an mpf or mpc, return it unchanged. If x is an int, create an mpf with sufficient precision to represent it exactly. If x is a str, just convert it to an mpf with the current working precision (perhaps this should be done differently...)""" if isinstance(x, mpnumeric): return x if isinstance(x, int_types): return make_mpf(from_int(x)) if isinstance(x, float): return make_mpf(from_float(x)) if isinstance(x, complex): return mpc(x) if strings and isinstance(x, basestring): return make_mpf(from_str(x, *prec_rounding)) if hasattr(x, '_mpf_'): return make_mpf(x._mpf_) if hasattr(x, '_mpc_'): return make_mpc(x._mpc_) if hasattr(x, '_mpmath_'): return convert_lossless(x._mpmath_(*prec_rounding)) raise TypeError("cannot create mpf from " + repr(x))
def mpmathify(x, strings=True): """ Converts *x* to an ``mpf`` or ``mpc``. If *x* is of type ``mpf``, ``mpc``, ``int``, ``float``, ``complex``, the conversion will be performed losslessly. If *x* is a string, the result will be rounded to the present working precision. Strings representing fractions or complex numbers are permitted. >>> from sympy.mpmath import * >>> mp.dps = 15 >>> mpmathify(3.5) mpf('3.5') >>> mpmathify('2.1') mpf('2.1000000000000001') >>> mpmathify('3/4') mpf('0.75') >>> mpmathify('2+3j') mpc(real='2.0', imag='3.0') """ if isinstance(x, mpnumeric): return x if isinstance(x, int_types): return make_mpf(from_int(x)) if isinstance(x, float): return make_mpf(from_float(x)) if isinstance(x, complex): return mpc(x) if strings and isinstance(x, basestring): try: return make_mpf(from_str(x, *prec_rounding)) except Exception, e: if '/' in x: fract = x.split('/') assert len(fract) == 2 return mpmathify(fract[0]) / mpmathify(fract[1]) if 'j' in x.lower(): x = x.lower().replace(' ', '') match = get_complex.match(x) re = match.group('re') if not re: re = 0 im = match.group('im').rstrip('j') return mpc(mpmathify(re), mpmathify(im)) raise e
def log_int_fixed(n, prec, ln2=None): """ Fast computation of log(n), caching the value for small n, intended for zeta sums. """ if n in log_int_cache: value, vprec = log_int_cache[n] if vprec >= prec: return value >> (vprec - prec) wp = prec + 10 if wp <= LOG_TAYLOR_SHIFT: if ln2 is None: ln2 = ln2_fixed(wp) r = bitcount(n) x = n << (wp - r) v = log_taylor_cached(x, wp) + r * ln2 else: v = to_fixed(mpf_log(from_int(n), wp + 5), wp) if n < MAX_LOG_INT_CACHE: log_int_cache[n] = (v, wp) return v >> (wp - prec)
def mpc_nthroot(z, n, prec, rnd=round_fast): """ Complex n-th root. Use Newton method as in the real case when it is faster, otherwise use z**(1/n) """ a, b = z if a[0] == 0 and b == fzero: re = mpf_nthroot(a, n, prec, rnd) return (re, fzero) if n < 2: if n == 0: return mpc_one if n == 1: return mpc_pos((a, b), prec, rnd) if n == -1: return mpc_div(mpc_one, (a, b), prec, rnd) inverse = mpc_nthroot((a, b), -n, prec + 5, reciprocal_rnd[rnd]) return mpc_div(mpc_one, inverse, prec, rnd) if n <= 20: prec2 = int(1.2 * (prec + 10)) asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b pf = mpc_abs((a, b), prec) if pf[-2] + pf[-1] > -10 and pf[-2] + pf[-1] < prec: af = to_fixed(a, prec2) bf = to_fixed(b, prec2) re, im = mpc_nthroot_fixed(af, bf, n, prec2) extra = 10 re = from_man_exp(re, -prec2 - extra, prec2, rnd) im = from_man_exp(im, -prec2 - extra, prec2, rnd) return re, im fn = from_int(n) prec2 = prec + 10 + 10 nth = mpf_rdiv_int(1, fn, prec2) re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im
def mpc_nthroot(z, n, prec, rnd=round_fast): """ Complex n-th root. Use Newton method as in the real case when it is faster, otherwise use z**(1/n) """ a, b = z if a[0] == 0 and b == fzero: re = mpf_nthroot(a, n, prec, rnd) return (re, fzero) if n < 2: if n == 0: return mpc_one if n == 1: return mpc_pos((a, b), prec, rnd) if n == -1: return mpc_div(mpc_one, (a, b), prec, rnd) inverse = mpc_nthroot((a, b), -n, prec+5, reciprocal_rnd[rnd]) return mpc_div(mpc_one, inverse, prec, rnd) if n <= 20: prec2 = int(1.2 * (prec + 10)) asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b pf = mpc_abs((a,b), prec) if pf[-2] + pf[-1] > -10 and pf[-2] + pf[-1] < prec: af = to_fixed(a, prec2) bf = to_fixed(b, prec2) re, im = mpc_nthroot_fixed(af, bf, n, prec2) extra = 10 re = from_man_exp(re, -prec2-extra, prec2, rnd) im = from_man_exp(im, -prec2-extra, prec2, rnd) return re, im fn = from_int(n) prec2 = prec+10 + 10 nth = mpf_rdiv_int(1, fn, prec2) re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im
def bernfrac(n): """ Computes integers (p,q) such that p/q = B_n exactly, where B_n denotes the nth Bernoulli number. Use bernoulli(n) to get a floating-point approximation instead of the exact fraction (much faster for large n). """ n = int(n) if n < 3: return [(1, 1), (-1, 2), (1, 6)][n] if n & 1: return (0, 1) q = 1 for k in list_primes(n+1): if not (n % (k-1)): q *= k prec = bernoulli_size(n) + int(math.log(q,2)) + 20 b = mpf_bernoulli(n, prec) p = mpf_mul(b, from_int(q)) pint = to_int(p, round_nearest) return (pint, q)
def mpf_fibonacci(x, prec, rnd=round_fast): sign, man, exp, bc = x if not man: if x == fninf: return fnan return x # F(2^n) ~= 2^(2^n) size = abs(exp+bc) if exp >= 0: # Exact if size < 10 or size <= bitcount(prec): return from_int(ifib(to_int(x)), prec, rnd) # Use the modified Binet formula wp = prec + size + 20 a = mpf_phi(wp) b = mpf_add(mpf_shift(a, 1), fnone, wp) u = mpf_pow(a, x, wp) v = mpf_cos_pi(x, wp) v = mpf_div(v, u, wp) u = mpf_sub(u, v, wp) u = mpf_div(u, b, prec, rnd) return u
def bernfrac(n): """ Computes integers (p,q) such that p/q = B_n exactly, where B_n denotes the nth Bernoulli number. Use bernoulli(n) to get a floating-point approximation instead of the exact fraction (much faster for large n). """ n = int(n) if n < 3: return [(1, 1), (-1, 2), (1, 6)][n] if n & 1: return (0, 1) q = 1 for k in list_primes(n + 1): if not (n % (k - 1)): q *= k prec = bernoulli_size(n) + int(math.log(q, 2)) + 20 b = mpf_bernoulli(n, prec) p = mpf_mul(b, from_int(q)) pint = to_int(p, round_nearest) return (pint, q)
def mpf_nthroot(s, n, prec, rnd=round_fast): """nth-root of a positive number Use the Newton method when faster, otherwise use x**(1/n) """ sign, man, exp, bc = s if sign: raise ComplexResult("nth root of a negative number") if not man: if s == fnan: return fnan if s == fzero: if n > 0: return fzero if n == 0: return fone return finf # Infinity if not n: return fnan if n < 0: return fzero return finf flag_inverse = False if n < 2: if n == 0: return fone if n == 1: return mpf_pos(s, prec, rnd) if n == -1: return mpf_div(fone, s, prec, rnd) # n < 0 rnd = reciprocal_rnd[rnd] flag_inverse = True extra_inverse = 5 prec += extra_inverse n = -n if n > 20 and (n >= 20000 or prec < int(233 + 28.3 * n**0.62)): prec2 = prec + 10 fn = from_int(n) nth = mpf_rdiv_int(1, fn, prec2) r = mpf_pow(s, nth, prec2, rnd) s = normalize(r[0], r[1], r[2], r[3], prec, rnd) if flag_inverse: return mpf_div(fone, s, prec-extra_inverse, rnd) else: return s # Convert to a fixed-point number with prec2 bits. prec2 = prec + 2*n - (prec%n) # a few tests indicate that # for 10 < n < 10**4 a bit more precision is needed if n > 10: prec2 += prec2//10 prec2 = prec2 - prec2%n # Mantissa may have more bits than we need. Trim it down. shift = bc - prec2 # Adjust exponents to make prec2 and exp+shift multiples of n. sign1 = 0 es = exp+shift if es < 0: sign1 = 1 es = -es if sign1: shift += es%n else: shift -= es%n man = rshift(man, shift) extra = 10 exp1 = ((exp+shift-(n-1)*prec2)//n) - extra rnd_shift = 0 if flag_inverse: if rnd == 'u' or rnd == 'c': rnd_shift = 1 else: if rnd == 'd' or rnd == 'f': rnd_shift = 1 man = nthroot_fixed(man+rnd_shift, n, prec2, exp1) s = from_man_exp(man, exp1, prec, rnd) if flag_inverse: return mpf_div(fone, s, prec-extra_inverse, rnd) else: return s
def bernfrac(n): r""" Returns a tuple of integers `(p, q)` such that `p/q = B_n` exactly, where `B_n` denotes the `n`-th Bernoulli number. The fraction is always reduced to lowest terms. Note that for `n > 1` and `n` odd, `B_n = 0`, and `(0, 1)` is returned. **Examples** The first few Bernoulli numbers are exactly:: >>> from mpmath import * >>> for n in range(15): ... p, q = bernfrac(n) ... print n, "%s/%s" % (p, q) ... 0 1/1 1 -1/2 2 1/6 3 0/1 4 -1/30 5 0/1 6 1/42 7 0/1 8 -1/30 9 0/1 10 5/66 11 0/1 12 -691/2730 13 0/1 14 7/6 This function works for arbitrarily large `n`:: >>> p, q = bernfrac(10**4) >>> print q 2338224387510 >>> print len(str(p)) 27692 >>> mp.dps = 15 >>> print mpf(p) / q -9.04942396360948e+27677 >>> print bernoulli(10**4) -9.04942396360948e+27677 Note: :func:`bernoulli` computes a floating-point approximation directly, without computing the exact fraction first. This is much faster for large `n`. **Algorithm** :func:`bernfrac` works by computing the value of `B_n` numerically and then using the von Staudt-Clausen theorem [1] to reconstruct the exact fraction. For large `n`, this is significantly faster than computing `B_1, B_2, \ldots, B_2` recursively with exact arithmetic. The implementation has been tested for `n = 10^m` up to `m = 6`. In practice, :func:`bernfrac` appears to be about three times slower than the specialized program calcbn.exe [2] **References** 1. MathWorld, von Staudt-Clausen Theorem: http://mathworld.wolfram.com/vonStaudt-ClausenTheorem.html 2. The Bernoulli Number Page: http://www.bernoulli.org/ """ n = int(n) if n < 3: return [(1, 1), (-1, 2), (1, 6)][n] if n & 1: return (0, 1) q = 1 for k in list_primes(n + 1): if not (n % (k - 1)): q *= k prec = bernoulli_size(n) + int(math.log(q, 2)) + 20 b = mpf_bernoulli(n, prec) p = mpf_mul(b, from_int(q)) pint = to_int(p, round_nearest) return (pint, q)
[n/6] ___ \ / n + 3 \ S(n) = ) | | * B /___ \ n - 6*k / n-6*k k = 1 For isolated large Bernoulli numbers, we use the Riemann zeta function to calculate a numerical value for B_n. The von Staudt-Clausen theorem can then be used to optionally find the exact value of the numerator and denominator. """ bernoulli_cache = {} f3 = from_int(3) f6 = from_int(6) def bernoulli_size(n): """Accurately estimate the size of B_n (even n > 2 only)""" lgn = math.log(n, 2) return int(2.326 + 0.5 * lgn + n * (lgn - 4.094)) BERNOULLI_PREC_CUTOFF = bernoulli_size(MAX_BERNOULLI_CACHE) def mpf_bernoulli(n, prec, rnd=None): """Computation of Bernoulli numbers (numerically)""" if n < 2:
def mpf_exp(x, prec, rnd=round_fast): sign, man, exp, bc = x if not man: if not exp: return fone if x == fninf: return fzero return x mag = bc+exp # Fast handling e**n. TODO: the best cutoff depends on both the # size of n and the precision. if prec > 600 and exp >= 0: e = mpf_e(prec+10+int(1.45*mag)) return mpf_pow_int(e, (-1)**sign *(man<<exp), prec, rnd) if mag < -prec-10: return mpf_perturb(fone, sign, prec, rnd) # extra precision needs to be similar in magnitude to log_2(|x|) # for the modulo reduction, plus r for the error from squaring r times wp = prec + max(0, mag) if wp < 300: r = int(2*wp**0.4) if mag < 0: r = max(1, r + mag) wp += r + 20 t = to_fixed(x, wp) # abs(x) > 1? if mag > 1: lg2 = ln2_fixed(wp) n, t = divmod(t, lg2) else: n = 0 man = exp_series(t, wp, r) else: use_newton = False # put a bound on exp to avoid infinite recursion in exp_newton # TODO find a good bound if wp > LIM_EXP_SERIES2 and exp < 1000: if mag > 0: use_newton = True elif mag <= 0 and -mag <= ns_exp[-1]: i = bisect(ns_exp, -mag-1) if i < len(ns_exp): wp0 = precs_exp[i] if wp > wp0: use_newton = True if not use_newton: r = int(0.7 * wp**0.5) if mag < 0: r = max(1, r + mag) wp += r + 20 t = to_fixed(x, wp) if mag > 1: lg2 = ln2_fixed(wp) n, t = divmod(t, lg2) else: n = 0 man = exp_series2(t, wp, r) else: # if x is very small or very large use # exp(x + m) = exp(x) * e**m if mag > LIM_MAG: wp += mag*10 + 100 n = int(mag * math.log(2)) + 1 x = mpf_sub(x, from_int(n, wp), wp) elif mag <= 0: wp += -mag*10 + 100 if mag < 0: n = int(-mag * math.log(2)) + 1 x = mpf_add(x, from_int(n, wp), wp) res = exp_newton(x, wp) sign, man, exp, bc = res if mag < 0: t = mpf_pow_int(mpf_e(wp), n, wp) res = mpf_div(res, t, wp) sign, man, exp, bc = res if mag > LIM_MAG: t = mpf_pow_int(mpf_e(wp), n, wp) res = mpf_mul(res, t, wp) sign, man, exp, bc = res return normalize(sign, man, exp, bc, prec, rnd) bc = bitcount(man) return normalize(0, man, int(-wp+n), bc, prec, rnd)
def bernfrac(n): r""" Returns a tuple of integers `(p, q)` such that `p/q = B_n` exactly, where `B_n` denotes the `n`-th Bernoulli number. The fraction is always reduced to lowest terms. Note that for `n > 1` and `n` odd, `B_n = 0`, and `(0, 1)` is returned. **Examples** The first few Bernoulli numbers are exactly:: >>> from mpmath import * >>> for n in range(15): ... p, q = bernfrac(n) ... print n, "%s/%s" % (p, q) ... 0 1/1 1 -1/2 2 1/6 3 0/1 4 -1/30 5 0/1 6 1/42 7 0/1 8 -1/30 9 0/1 10 5/66 11 0/1 12 -691/2730 13 0/1 14 7/6 This function works for arbitrarily large `n`:: >>> p, q = bernfrac(10**4) >>> print q 2338224387510 >>> print len(str(p)) 27692 >>> mp.dps = 15 >>> print mpf(p) / q -9.04942396360948e+27677 >>> print bernoulli(10**4) -9.04942396360948e+27677 Note: :func:`bernoulli` computes a floating-point approximation directly, without computing the exact fraction first. This is much faster for large `n`. **Algorithm** :func:`bernfrac` works by computing the value of `B_n` numerically and then using the von Staudt-Clausen theorem [1] to reconstruct the exact fraction. For large `n`, this is significantly faster than computing `B_1, B_2, \ldots, B_2` recursively with exact arithmetic. The implementation has been tested for `n = 10^m` up to `m = 6`. In practice, :func:`bernfrac` appears to be about three times slower than the specialized program calcbn.exe [2] **References** 1. MathWorld, von Staudt-Clausen Theorem: http://mathworld.wolfram.com/vonStaudt-ClausenTheorem.html 2. The Bernoulli Number Page: http://www.bernoulli.org/ """ n = int(n) if n < 3: return [(1, 1), (-1, 2), (1, 6)][n] if n & 1: return (0, 1) q = 1 for k in list_primes(n+1): if not (n % (k-1)): q *= k prec = bernoulli_size(n) + int(math.log(q,2)) + 20 b = mpf_bernoulli(n, prec) p = mpf_mul(b, from_int(q)) pint = to_int(p, round_nearest) return (pint, q)
""" if a[0] == 0 and b == fzero: re = mpf_nthroot(a, n, prec, rnd) return (re, fzero) if n < 2: if n == 0: return mpc_one if n == 1: return mpc_pos((a, b), prec, rnd) if n == -1: return mpc_div(mpc_one, (a, b), prec, rnd) inverse = mpc_nthroot((a, b), -n, prec + 5, reciprocal_rnd[rnd]) return mpc_div(mpc_one, inverse, prec, rnd) if n > 20: fn = from_int(n) prec2 = prec + 10 nth = mpf_rdiv_int(1, fn, prec2) re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im prec2 = int(1.2 * (prec + 10)) asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b af = to_fixed(a, prec2) bf = to_fixed(b, prec2) re, im = mpc_nthroot_fixed(af, bf, n, prec2) extra = 10 re = from_man_exp(re, -prec2 - extra, prec2, rnd) im = from_man_exp(im, -prec2 - extra, prec2, rnd)
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] return numbers[n]
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, MP_BASE(10), MP_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 = MP_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]
[n/6] ___ \ / n + 3 \ S(n) = ) | | * B /___ \ n - 6*k / n-6*k k = 1 For isolated large Bernoulli numbers, we use the Riemann zeta function to calculate a numerical value for B_n. The von Staudt-Clausen theorem can then be used to optionally find the exact value of the numerator and denominator. """ bernoulli_cache = {} f3 = from_int(3) f6 = from_int(6) def bernoulli_size(n): """Accurately estimate the size of B_n (even n > 2 only)""" lgn = math.log(n,2) return int(2.326 + 0.5*lgn + n*(lgn - 4.094)) BERNOULLI_PREC_CUTOFF = bernoulli_size(MAX_BERNOULLI_CACHE) 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:
def mpf_expint(n, x, prec, rnd=round_fast, gamma=False): """ E_n(x), n an integer, x real With gamma=True, computes Gamma(n,x) (upper incomplete gamma function) Returns (real, None) if real, otherwise (real, imag) The imaginary part is an optional branch cut term """ sign, man, exp, bc = x if not man: if gamma: if x == fzero: # Actually gamma function pole if n <= 0: return finf return mpf_gamma_int(n, prec, rnd) if x == finf: return fzero, None # TODO: could return finite imaginary value at -inf return fnan, fnan else: if x == fzero: if n > 1: return from_rational(1, n - 1, prec, rnd), None else: return finf, None if x == finf: return fzero, None return fnan, fnan n_orig = n if gamma: n = 1 - n wp = prec + 20 xmag = exp + bc # Beware of near-poles if xmag < -10: raise NotImplementedError nmag = bitcount(abs(n)) have_imag = n > 0 and sign negx = mpf_neg(x) # Skip series if direct convergence if n == 0 or 2 * nmag - xmag < -wp: if gamma: v = mpf_exp(negx, wp) re = mpf_mul(v, mpf_pow_int(x, n_orig - 1, wp), prec, rnd) else: v = mpf_exp(negx, wp) re = mpf_div(v, x, prec, rnd) else: # Finite number of terms, or... can_use_asymptotic_series = -3 * wp < n <= 0 # ...large enough? if not can_use_asymptotic_series: xi = abs(to_int(x)) m = min(max(1, xi - n), 2 * wp) siz = -n * nmag + (m + n) * bitcount(abs(m + n)) - m * xmag - ( 144 * m // 100) tol = -wp - 10 can_use_asymptotic_series = siz < tol if can_use_asymptotic_series: r = ((-MP_ONE) << (wp + wp)) // to_fixed(x, wp) m = n t = r * m s = MP_ONE << wp while m and t: s += t m += 1 t = (m * r * t) >> wp v = mpf_exp(negx, wp) if gamma: # ~ exp(-x) * x^(n-1) * (1 + ...) v = mpf_mul(v, mpf_pow_int(x, n_orig - 1, wp), wp) else: # ~ exp(-x)/x * (1 + ...) v = mpf_div(v, x, wp) re = mpf_mul(v, from_man_exp(s, -wp), prec, rnd) elif n == 1: re = mpf_neg(mpf_ei(negx, prec, rnd)) elif n > 0 and n < 3 * wp: T1 = mpf_neg(mpf_ei(negx, wp)) if gamma: if n_orig & 1: T1 = mpf_neg(T1) else: T1 = mpf_mul(T1, mpf_pow_int(negx, n - 1, wp), wp) r = t = to_fixed(x, wp) facs = [1] * (n - 1) for k in range(1, n - 1): facs[k] = facs[k - 1] * k facs = facs[::-1] s = facs[0] << wp for k in range(1, n - 1): if k & 1: s -= facs[k] * t else: s += facs[k] * t t = (t * r) >> wp T2 = from_man_exp(s, -wp, wp) T2 = mpf_mul(T2, mpf_exp(negx, wp)) if gamma: T2 = mpf_mul(T2, mpf_pow_int(x, n_orig, wp), wp) R = mpf_add(T1, T2) re = mpf_div(R, from_int(int_fac(n - 1)), prec, rnd) else: raise NotImplementedError if have_imag: M = from_int(-int_fac(n - 1)) if gamma: im = mpf_div(mpf_pi(wp), M, prec, rnd) else: im = mpf_div( mpf_mul(mpf_pi(wp), mpf_pow_int(negx, n_orig - 1, wp), wp), M, prec, rnd) return re, im else: return re, None
def mpc_zeta(s, prec, rnd=round_fast, alt=0, force=False): re, im = s if im == fzero: return mpf_zeta(re, prec, rnd, alt), fzero # slow for large s if (not force) and mpf_gt(mpc_abs(s, 10), from_int(prec)): raise NotImplementedError wp = prec + 20 # Near pole r = mpc_sub(mpc_one, s, wp) asign, aman, aexp, abc = mpc_abs(r, 10) pole_dist = -2*(aexp+abc) if pole_dist > wp: if alt: q = mpf_ln2(wp) y = mpf_mul(q, mpf_euler(wp), wp) g = mpf_shift(mpf_mul(q, q, wp), -1) g = mpf_sub(y, g) z = mpc_mul_mpf(r, mpf_neg(g), wp) z = mpc_add_mpf(z, q, wp) return mpc_pos(z, prec, rnd) else: q = mpc_neg(mpc_div(mpc_one, r, wp)) q = mpc_add_mpf(q, mpf_euler(wp), wp) return mpc_pos(q, prec, rnd) else: wp += max(0, pole_dist) # Reflection formula. To be rigorous, we should reflect to the left of # re = 1/2 (see comments for mpf_zeta), but this leads to unnecessary # slowdown for interesting values of s if mpf_lt(re, fzero): # XXX: could use the separate refl. formula for Dirichlet eta if alt: q = mpc_sub(mpc_one, mpc_pow(mpc_two, mpc_sub(mpc_one, s, wp), wp), wp) return mpc_mul(mpc_zeta(s, wp), q, prec, rnd) # XXX: -1 should be done exactly y = mpc_sub(mpc_one, s, 10*wp) a = mpc_gamma(y, wp) b = mpc_zeta(y, wp) c = mpc_sin_pi(mpc_shift(s, -1), wp) rsign, rman, rexp, rbc = re isign, iman, iexp, ibc = im mag = max(rexp+rbc, iexp+ibc) wp2 = wp + mag pi = mpf_pi(wp+wp2) pi2 = (mpf_shift(pi, 1), fzero) d = mpc_div_mpf(mpc_pow(pi2, s, wp2), pi, wp2) return mpc_mul(a,mpc_mul(b,mpc_mul(c,d,wp),wp),prec,rnd) n = int(wp/2.54 + 5) n += int(0.9*abs(to_int(im))) d = borwein_coefficients(n) ref = to_fixed(re, wp) imf = to_fixed(im, wp) tre = MPZ_ZERO tim = MPZ_ZERO one = MPZ_ONE << wp one_2wp = MPZ_ONE << (2*wp) critical_line = re == fhalf for k in xrange(n): log = log_int_fixed(k+1, wp) # A square root is much cheaper than an exp if critical_line: w = one_2wp // sqrt_fixed((k+1) << wp, wp) else: w = to_fixed(mpf_exp(from_man_exp(-ref*log, -2*wp), wp), wp) if k & 1: w *= (d[n] - d[k]) else: w *= (d[k] - d[n]) wre, wim = mpf_cos_sin(from_man_exp(-imf * log, -2*wp), wp) tre += (w * to_fixed(wre, wp)) >> wp tim += (w * to_fixed(wim, wp)) >> wp tre //= (-d[n]) tim //= (-d[n]) tre = from_man_exp(tre, -wp, wp) tim = from_man_exp(tim, -wp, wp) if alt: return mpc_pos((tre, tim), prec, rnd) else: q = mpc_sub(mpc_one, mpc_pow(mpc_two, r, wp), wp) return mpc_div((tre, tim), q, prec, rnd)