(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.
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.
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 .
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):
        term = expr.subs(n, 0)
        term = (MPZ(term.p) << prec) // term.q
        s = term
        k = 1
        while abs(term) > 5:
            term *= MPZ(func1(k - 1))
            term //= MPZ(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
        term = expr.subs(n, 0)
        term = (MPZ(term.p) << prec2) // term.q

        def summand(k, _term=[term]):
            if k:
                k = int(k)
                _term[0] *= MPZ(func1(k - 1))
                _term[0] //= MPZ(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 ) : 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 ) : term = expr . subs ( n , 0 ) term = ( MPZ ( term . p ) << prec ) // term . q s = term k = 1 while abs ( term ) > 5 : term *= MPZ ( func1 ( k - 1 ) ) term //= MPZ ( 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 term = expr . subs ( n , 0 ) term = ( MPZ ( term . p ) << prec2 ) // term . q def summand ( k , _term = [ term ] ) : if k : k = int ( k ) _term [ 0 ] *= MPZ ( func1 ( k - 1 ) ) _term [ 0 ] //= MPZ ( 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_