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 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)
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)