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
def _as_mpf_val(self, prec): return mlib.from_man_exp(mpmath.gammazeta.catalan_fixed(prec+10), -prec-10)
def _as_mpf_val(self, prec): return mlib.from_man_exp(phi_fixed(prec+10), -prec-10)
def summand(k, _term=[term]): if k: k = int(k) _term[0] *= MP_BASE(func1(k-1)) _term[0] //= MP_BASE(func2(k-1)) return make_mpf(from_man_exp(_term[0], -prec2))
def hypsum(expr, n, start, prec): """ Sum a rapidly convergent infinite hypergeometric series with given general term, e.g. e = hypsum(1/factorial(n), n). The quotient between successive terms must be a quotient of integer polynomials. """ from sympy import hypersimp, lambdify if start: expr = expr.subs(n, n+start) hs = hypersimp(expr, n) if hs is None: raise NotImplementedError("a hypergeometric series is required") num, den = hs.as_numer_denom() func1 = lambdify(n, num) func2 = lambdify(n, den) h, g, p = check_convergence(num, den, n) if h < 0: raise ValueError("Sum diverges like (n!)^%i" % (-h)) # Direct summation if geometric or faster if h > 0 or (h == 0 and abs(g) > 1): one = MP_BASE(1) << prec term = expr.subs(n, 0) term = (MP_BASE(term.p) << prec) // term.q s = term k = 1 while abs(term) > 5: term *= MP_BASE(func1(k-1)) term //= MP_BASE(func2(k-1)) s += term k += 1 return from_man_exp(s, -prec) else: alt = g < 0 if abs(g) < 1: raise ValueError("Sum diverges like (%i)^n" % abs(1/g)) if p < 1 or (p == 1 and not alt): raise ValueError("Sum diverges like n^%i" % (-p)) # We have polynomial convergence: use Richardson extrapolation # Need to use at least quad precision because a lot of cancellation # might occur in the extrapolation process prec2 = 4*prec one = MP_BASE(1) << prec2 term = expr.subs(n, 0) term = (MP_BASE(term.p) << prec2) // term.q def summand(k, _term=[term]): if k: k = int(k) _term[0] *= MP_BASE(func1(k-1)) _term[0] //= MP_BASE(func2(k-1)) return make_mpf(from_man_exp(_term[0], -prec2)) orig = mp.prec try: mp.prec = prec v = nsum(summand, [0, mpmath_inf], method='richardson') finally: mp.prec = orig return v._mpf_
def hypsum(expr, n, start, prec): """ Sum a rapidly convergent infinite hypergeometric series with given general term, e.g. e = hypsum(1/factorial(n), n). The quotient between successive terms must be a quotient of integer polynomials. """ from sympy import hypersimp, lambdify if start: expr = expr.subs(n, n + start) hs = hypersimp(expr, n) if hs is None: raise NotImplementedError("a hypergeometric series is required") num, den = hs.as_numer_denom() func1 = lambdify(n, num) func2 = lambdify(n, den) h, g, p = check_convergence(num, den, n) if h < 0: raise ValueError("Sum diverges like (n!)^%i" % (-h)) # Direct summation if geometric or faster if h > 0 or (h == 0 and abs(g) > 1): one = MP_BASE(1) << prec term = expr.subs(n, 0) term = (MP_BASE(term.p) << prec) // term.q s = term k = 1 while abs(term) > 5: term *= MP_BASE(func1(k - 1)) term //= MP_BASE(func2(k - 1)) s += term k += 1 return from_man_exp(s, -prec) else: alt = g < 0 if abs(g) < 1: raise ValueError("Sum diverges like (%i)^n" % abs(1 / g)) if p < 1 or (p == 1 and not alt): raise ValueError("Sum diverges like n^%i" % (-p)) # We have polynomial convergence: # Use Shanks extrapolation for alternating series, # Richardson extrapolation for nonalternating series if alt: # XXX: better parameters for Shanks transformation # This tends to get bad somewhere > 50 digits N = 5 + int(prec * 0.36) M = 2 + N // 3 NTERMS = M + N + 2 else: N = 3 + int(prec * 0.15) M = 2 * N NTERMS = M + N + 2 # Need to use at least double precision because a lot of cancellation # might occur in the extrapolation process prec2 = 2 * prec one = MP_BASE(1) << prec2 term = expr.subs(n, 0) term = (MP_BASE(term.p) << prec2) // term.q s = term table = [make_mpf(from_man_exp(s, -prec2))] for k in xrange(1, NTERMS): term *= MP_BASE(func1(k - 1)) term //= MP_BASE(func2(k - 1)) s += term table.append(make_mpf(from_man_exp(s, -prec2))) k += 1 orig = mp.prec try: mp.prec = prec if alt: v = shanks_extrapolation(table, N, M) else: v = richardson_extrapolation(table, N, M) finally: mp.prec = orig return v._mpf_
def hypsum(expr, n, start, prec): """ Sum a rapidly convergent infinite hypergeometric series with given general term, e.g. e = hypsum(1/factorial(n), n). The quotient between successive terms must be a quotient of integer polynomials. """ from sympy import hypersimp, lambdify if start: expr = expr.subs(n, n+start) hs = hypersimp(expr, n) if hs is None: raise NotImplementedError("a hypergeometric series is required") num, den = hs.as_numer_denom() func1 = lambdify(n, num) func2 = lambdify(n, den) h, g, p = check_convergence(num, den, n) if h < 0: raise ValueError("Sum diverges like (n!)^%i" % (-h)) # Direct summation if geometric or faster if h > 0 or (h == 0 and abs(g) > 1): one = MP_BASE(1) << prec term = expr.subs(n, 0) term = (MP_BASE(term.p) << prec) // term.q s = term k = 1 while abs(term) > 5: term *= MP_BASE(func1(k-1)) term //= MP_BASE(func2(k-1)) s += term k += 1 return from_man_exp(s, -prec) else: alt = g < 0 if abs(g) < 1: raise ValueError("Sum diverges like (%i)^n" % abs(1/g)) if p < 1 or (p == 1 and not alt): raise ValueError("Sum diverges like n^%i" % (-p)) # We have polynomial convergence: # Use Shanks extrapolation for alternating series, # Richardson extrapolation for nonalternating series if alt: # XXX: better parameters for Shanks transformation # This tends to get bad somewhere > 50 digits N = 5 + int(prec*0.36) M = 2 + N//3 NTERMS = M + N + 2 else: N = 3 + int(prec*0.15) M = 2*N NTERMS = M + N + 2 # Need to use at least double precision because a lot of cancellation # might occur in the extrapolation process prec2 = 2*prec one = MP_BASE(1) << prec2 term = expr.subs(n, 0) term = (MP_BASE(term.p) << prec2) // term.q s = term table = [make_mpf(from_man_exp(s, -prec2))] for k in xrange(1, NTERMS): term *= MP_BASE(func1(k-1)) term //= MP_BASE(func2(k-1)) s += term table.append(make_mpf(from_man_exp(s, -prec2))) k += 1 orig = mp.prec try: mp.prec = prec if alt: v = shanks_extrapolation(table, N, M) else: v = richardson_extrapolation(table, N, M) finally: mp.prec = orig return v._mpf_