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 fraction(p, q): """Given Python integers p, q, return a lazy mpf with value p/q. The value is updated with the precision. >>> mp.dps = 15 >>> a = fraction(1,100) >>> b = mpf(1)/100 >>> print a; print b 0.01 0.01 >>> mp.dps = 30 >>> print a; print b 0.01 0.0100000000000000002081668171172 >>> mp.dps = 15 """ return constant(lambda prec, rnd: from_rational(p, q, prec, rnd), '%s/%s' % (p, q))
def fraction(p, q): """ Given Python integers `(p, q)`, returns a lazy ``mpf`` representing the fraction `p/q`. The value is updated with the precision. >>> mp.dps = 15 >>> a = fraction(1,100) >>> b = mpf(1)/100 >>> print a; print b 0.01 0.01 >>> mp.dps = 30 >>> print a; print b # a will be accurate 0.01 0.0100000000000000002081668171172 >>> mp.dps = 15 """ return constant(lambda prec, rnd: from_rational(p, q, prec, rnd), '%s/%s' % (p, q))
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_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 _mpmath_(self, prec, rounding): # XXX return mp.make_mpf(from_rational(self[0], self[1], prec, rounding))
def mpf_cos_sin(x, prec, rnd=round_fast, which=0, pi=False): """ which: 0 -- return cos(x), sin(x) 1 -- return cos(x) 2 -- return sin(x) 3 -- return tan(x) if pi=True, compute for pi*x """ sign, man, exp, bc = x if not man: if exp: c, s = fnan, fnan else: c, s = fone, fzero if which == 0: return c, s if which == 1: return c if which == 2: return s if which == 3: return s mag = bc + exp wp = prec + 10 # Extremely small? if mag < 0: if mag < -wp: if pi: x = mpf_mul(x, mpf_pi(wp)) c = mpf_perturb(fone, 1, prec, rnd) s = mpf_perturb(x, 1 - sign, prec, rnd) if which == 0: return c, s if which == 1: return c if which == 2: return s if which == 3: return mpf_perturb(x, sign, prec, rnd) if pi: if exp >= -1: if exp == -1: c = fzero s = (fone, fnone)[bool(man & 2) ^ sign] elif exp == 0: c, s = (fnone, fzero) else: c, s = (fone, fzero) if which == 0: return c, s if which == 1: return c if which == 2: return s if which == 3: return mpf_div(s, c, prec, rnd) # Subtract nearest half-integer (= mod by pi/2) n = ((man >> (-exp - 2)) + 1) >> 1 man = man - (n << (-exp - 1)) mag2 = bitcount(man) + exp wp = prec + 10 - mag2 offset = exp + wp if offset >= 0: t = man << offset else: t = man >> (-offset) t = (t * pi_fixed(wp)) >> wp else: t, n, wp = mod_pi2(man, exp, mag, wp) c, s = cos_sin_basecase(t, wp) m = n & 3 if m == 1: c, s = -s, c elif m == 2: c, s = -c, -s elif m == 3: c, s = s, -c if sign: s = -s if which == 0: c = from_man_exp(c, -wp, prec, rnd) s = from_man_exp(s, -wp, prec, rnd) return c, s if which == 1: return from_man_exp(c, -wp, prec, rnd) if which == 2: return from_man_exp(s, -wp, prec, rnd) if which == 3: return from_rational(s, c, prec, rnd)
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, None return mpf_gamma_int(n, prec, rnd), None 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 = ((-MPZ_ONE) << (wp+wp)) // to_fixed(x, wp) m = n t = r*m s = MPZ_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(ifac(n-1)), prec, rnd) else: raise NotImplementedError if have_imag: M = from_int(-ifac(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 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]
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