Ejemplo n.º 1
0
    def _get_general_solution(self, *, simplify: bool = True):
        x = self.ode_problem.sym
        (C1,)  = self.ode_problem.get_numbered_constants(num=1)
        gensol = Eq(self.ly, (((C1 + Integral((self.cx/self.ax)*exp(Integral(self.bx/self.ax, x)),x))
                * exp(-Integral(self.bx/self.ax, x)))))

        return [gensol]
Ejemplo n.º 2
0
def test_Integral():
    assert mcode(Integral(sin(sin(x)), x)) == "Hold[Integrate[Sin[Sin[x]], x]]"
    assert mcode(Integral(exp(-x**2 - y**2),
                          (x, -oo, oo),
                          (y, -oo, oo))) == \
        "Hold[Integrate[Exp[-x^2 - y^2], {x, -Infinity, Infinity}, " \
        "{y, -Infinity, Infinity}]]"
Ejemplo n.º 3
0
 def _get_general_solution(self, *, simplify: bool = True):
     P, Q = self.wilds_match()
     fx = self.ode_problem.func
     x = self.ode_problem.sym
     (C1,)  = self.ode_problem.get_numbered_constants(num=1)
     gensol = Eq(fx, (((C1 + Integral(Q*exp(Integral(P, x)),x))
         * exp(-Integral(P, x)))))
     return [gensol]
Ejemplo n.º 4
0
    def _get_general_solution(self, *, simplify: bool = True):
        d, e, k = self.wilds_match()
        fx = self.ode_problem.func
        x = self.ode_problem.sym
        C1, C2 = self.ode_problem.get_numbered_constants(num=2)
        int = Integral(exp(Integral(self.g, self.y)), (self.y, None, fx))
        gen_sol = Eq(int + C1 * Integral(exp(-Integral(self.h, x)), x) + C2, 0)

        return [gen_sol]
Ejemplo n.º 5
0
 def _get_general_solution(self, *, simplify: bool = True):
     fx = self.ode_problem.func
     x = self.ode_problem.sym
     (C1, ) = self.ode_problem.get_numbered_constants(num=1)
     int = Integral(self.m2['coeff'] * self.m2[self.y] / self.m1[self.y],
                    (self.y, None, fx))
     gen_sol = Eq(
         int,
         Integral(-self.m1['coeff'] * self.m1[x] / self.m2[x], x) + C1)
     return [gen_sol]
Ejemplo n.º 6
0
 def _get_general_solution(self, *, simplify: bool = True):
     g = self.wilds_match()[0]
     fx = self.ode_problem.func
     x = self.ode_problem.sym
     u = Dummy('u')
     g = g.subs(fx, u)
     C1, C2 = self.ode_problem.get_numbered_constants(num=2)
     inside = -2 * Integral(g, u) + C1
     lhs = Integral(1 / sqrt(inside), (u, fx))
     return [Eq(lhs, C2 + x), Eq(lhs, C2 - x)]
Ejemplo n.º 7
0
 def _get_general_solution(self, *, simplify: bool = True):
     P, Q, n = self.wilds_match()
     fx = self.ode_problem.func
     x = self.ode_problem.sym
     (C1, ) = self.ode_problem.get_numbered_constants(num=1)
     if n == 1:
         gensol = Eq(log(fx), ((C1 + Integral((-P + Q), x))))
     else:
         gensol = Eq(fx**(1 - n), ((C1 - (n - 1) * Integral(
             Q * exp(-n * Integral(P, x)) * exp(Integral(P, x)), x)) *
                                   exp(-(1 - n) * Integral(P, x))))
     return [gensol]
Ejemplo n.º 8
0
Archivo: single.py Proyecto: tnzl/sympy
    def _get_general_solution(self, *, simplify: bool = True):
        m, n = self.wilds_match()
        fx = self.ode_problem.func
        x = self.ode_problem.sym
        (C1,) = self.ode_problem.get_numbered_constants(num=1)
        y = Dummy('y')

        m = m.subs(fx, y)
        n = n.subs(fx, y)

        gen_sol = Eq(Subs(Integral(m, x)
                          + Integral(n - Integral(m, x).diff(y), y), y, fx), C1)
        return gen_sol
Ejemplo n.º 9
0
Archivo: single.py Proyecto: tnzl/sympy
    def _verify(self, fx) -> bool:
        P, Q = self.wilds()
        x = self.ode_problem.sym
        y = Dummy('y')

        m, n = self.wilds_match()

        try:
            if simplify(m) != 0:
                m = m.subs(fx,y)
                n = n.subs(fx,y)
                numerator= simplify(m.diff(y)-n.diff(x))
                # The following few conditions try to convert a non-exact
                # differential equation into an exact one.
                # References :
                #1. Differential equations with applications
                # and historical notes - George E. Simmons
                #2. https://math.okstate.edu/people/binegar/2233-S99/2233-l12.pdf
                if numerator:
                    # If (dP/dy - dQ/dx) / Q = f(x)
                    # then exp(integral(f(x))*equation becomes exact
                    factor = simplify(numerator/n)
                    variables = factor.free_symbols
                    if len(variables) == 1 and x == variables.pop():
                        factor = exp(Integral(factor).doit())
                        m *= factor
                        n *= factor
                        self._wilds_match[P] = m.subs(y, fx)
                        self._wilds_match[Q] = n.subs(y, fx)
                        return True
                    else:
                        # If (dP/dy - dQ/dx) / -P = f(y)
                        # then exp(integral(f(y))*equation becomes exact
                        factor = simplify(-numerator / m)
                        variables = factor.free_symbols
                        if len(variables) == 1 and y == variables.pop():
                            factor = exp(Integral(factor).doit())
                            m *= factor
                            n *= factor
                            self._wilds_match[P] = m.subs(y, fx)
                            self._wilds_match[Q] = n.subs(y, fx)
                            return True
                else:
                    return True
        except NotImplementedError:
            # Differentiating the coefficients might fail because of things
            # like f(2*x).diff(x).  See issue 4624 and issue 4719.
            pass

        return False
Ejemplo n.º 10
0
    def __init__(self):
        if Parser.__instance is not None:
            raise Exception("Invalid initialistion of Parser.")
        Parser.__instance = self
        self.__transformations = standard_transformations \
            + (function_exponentiation, convert_xor, convert_equals_signs)

        self.__global_dict = {}
        exec_('from sympy.core import *', self.__global_dict)
        exec_('from sympy.functions import *', self.__global_dict)
        exec_('from sympy.integrals import *', self.__global_dict)
        exclusions = ['sympify', 'SympifyError', 'Subs', 'evalf', 'evaluate']
        for e in exclusions:
            self.__global_dict.pop(e)

        e, pi = sy.symbols('e pi')

        def func_check(name):
            return lambda e : isinstance(e, sy.Function) \
                and getattr(e, 'name', None) == name

        self.__default_subs = [(e, np.exp(1)), (pi, np.pi)]
        self.__default_repl = [
            (func_check('der'), lambda e: Derivative(*e.args)),
            (func_check('int'), lambda e: Integral(*e.args))
        ]
        self.__default_trans = [(lambda x: isinstance(x,
                                                      (Derivative, Integral)),
                                 lambda e: e.doit())]
        self.__invalid_atoms = (Derivative, Integral)
Ejemplo n.º 11
0
def _solve_variation_of_parameters(eq,
                                   func,
                                   roots,
                                   homogen_sol,
                                   order,
                                   match_obj,
                                   simplify_flag=True):
    r"""
    Helper function for the method of variation of parameters and nonhomogeneous euler eq.

    See the
    :py:meth:`~sympy.solvers.ode.single.NthLinearConstantCoeffVariationOfParameters`
    docstring for more information on this method.

    The parameter are ``match_obj`` should be a dictionary that has the following
    keys:

    ``list``
    A list of solutions to the homogeneous equation.

    ``sol``
    The general solution.

    """
    f = func.func
    x = func.args[0]
    r = match_obj
    psol = 0
    wr = wronskian(roots, x)

    if simplify_flag:
        wr = simplify(wr)  # We need much better simplification for
        # some ODEs. See issue 4662, for example.
        # To reduce commonly occurring sin(x)**2 + cos(x)**2 to 1
        wr = trigsimp(wr, deep=True, recursive=True)
    if not wr:
        # The wronskian will be 0 iff the solutions are not linearly
        # independent.
        raise NotImplementedError(
            "Cannot find " + str(order) +
            " solutions to the homogeneous equation necessary to apply " +
            "variation of parameters to " + str(eq) + " (Wronskian == 0)")
    if len(roots) != order:
        raise NotImplementedError(
            "Cannot find " + str(order) +
            " solutions to the homogeneous equation necessary to apply " +
            "variation of parameters to " + str(eq) +
            " (number of terms != order)")
    negoneterm = (-1)**(order)
    for i in roots:
        psol += negoneterm * Integral(
            wronskian([sol for sol in roots if sol != i], x) * r[-1] / wr,
            x) * i / r[order]
        negoneterm *= -1

    if simplify_flag:
        psol = simplify(psol)
        psol = trigsimp(psol, deep=True)
    return Eq(f(x), homogen_sol.rhs + psol)
Ejemplo n.º 12
0
def get_sol_2F1_hypergeometric(eq, func, match_object):
    x = func.args[0]
    from sympy.simplify.hyperexpand import hyperexpand
    from sympy.polys.polytools import factor
    C0, C1 = get_numbered_constants(eq, num=2)
    a = match_object['a']
    b = match_object['b']
    c = match_object['c']
    A = match_object['A']

    sol = None

    if c.is_integer == False:
        sol = C0 * hyper([a, b], [c], x) + C1 * hyper([a - c + 1, b - c + 1],
                                                      [2 - c], x) * x**(1 - c)
    elif c == 1:
        y2 = Integral(
            exp(Integral((-(a + b + 1) * x + c) / (x**2 - x), x)) /
            (hyperexpand(hyper([a, b], [c], x))**2), x) * hyper([a, b], [c], x)
        sol = C0 * hyper([a, b], [c], x) + C1 * y2
    elif (c - a - b).is_integer == False:
        sol = C0 * hyper([a, b], [1 + a + b - c], 1 - x) + C1 * hyper(
            [c - a, c - b], [1 + c - a - b], 1 - x) * (1 - x)**(c - a - b)

    if sol:
        # applying transformation in the solution
        subs = match_object['mobius']
        dtdx = simplify(1 / (subs.diff(x)))
        _B = ((a + b + 1) * x - c).subs(x, subs) * dtdx
        _B = factor(_B + ((x**2 - x).subs(x, subs)) * (dtdx.diff(x) * dtdx))
        _A = factor((x**2 - x).subs(x, subs) * (dtdx**2))
        e = exp(logcombine(Integral(cancel(_B / (2 * _A)), x), force=True))
        sol = sol.subs(x, match_object['mobius'])
        sol = sol.subs(x, x**match_object['k'])
        e = e.subs(x, x**match_object['k'])

        if not A.is_zero:
            e1 = Integral(A / 2, x)
            e1 = exp(logcombine(e1, force=True))
            sol = cancel((e / e1) * x**((-match_object['k'] + 1) / 2)) * sol
            sol = Eq(func, sol)
            return sol

        sol = cancel((e) * x**((-match_object['k'] + 1) / 2)) * sol
        sol = Eq(func, sol)
    return sol
Ejemplo n.º 13
0
    def _sympy_(self, f, x, a, b):
        """
        Convert this integral to the equivalent SymPy object

        The resulting SymPy integral can be evaluated using ``doit()``.

        EXAMPLES::

            sage: integral(x, x, 0, 1, hold=True)._sympy_()
            Integral(x, (x, 0, 1))
            sage: _.doit()
            1/2
        """
        from sympy.integrals import Integral
        return Integral(f, (x, a, b))
Ejemplo n.º 14
0
    def _verify(self, fx) -> bool:
        P, Q = self.wilds()
        x = self.ode_problem.sym
        y = Dummy('y')

        m, n = self.wilds_match()

        m = m.subs(fx, y)
        n = n.subs(fx, y)
        numerator = cancel(m.diff(y) - n.diff(x))

        if numerator.is_zero:
            # Is exact
            return True
        else:
            # The following few conditions try to convert a non-exact
            # differential equation into an exact one.
            # References:
            # 1. Differential equations with applications
            # and historical notes - George E. Simmons
            # 2. https://math.okstate.edu/people/binegar/2233-S99/2233-l12.pdf

            factor_n = cancel(numerator / n)
            factor_m = cancel(-numerator / m)
            if y not in factor_n.free_symbols:
                # If (dP/dy - dQ/dx) / Q = f(x)
                # then exp(integral(f(x))*equation becomes exact
                factor = factor_n
                integration_variable = x
            elif x not in factor_m.free_symbols:
                # If (dP/dy - dQ/dx) / -P = f(y)
                # then exp(integral(f(y))*equation becomes exact
                factor = factor_m
                integration_variable = y
            else:
                # Couldn't convert to exact
                return False

            factor = exp(Integral(factor, integration_variable))
            m *= factor
            n *= factor
            self._wilds_match[P] = m.subs(y, fx)
            self._wilds_match[Q] = n.subs(y, fx)
            return True
Ejemplo n.º 15
0
    def _get_general_solution(self, *, simplify: bool = True):
        P, Q = self.wilds_match()
        fx = self.ode_problem.func
        x = self.ode_problem.sym
        (C1, ) = self.ode_problem.get_numbered_constants(num=1)
        if self.fxx is None or self.gx is None or self.kx is None:
            gensol = Eq(fx, (((C1 + Integral(Q * exp(Integral(P, x)), x)) *
                              exp(-Integral(P, x)))))
        else:
            gensol = Eq(self.substituting, (((C1 + Integral(
                (self.gx / self.fxx) * exp(Integral(self.kx / self.fxx, x)),
                x)) * exp(-Integral(self.kx / self.fxx, x)))))

        return [gensol]
Ejemplo n.º 16
0
        return  components[:self.dim]


class VectorMagnitude(Basic):
    def __init__(self, arg): 
        self._args = Tuple(arg)

    def decompose(self):
        comps = self.args[0].components()
        return sqrt(sum([x*x for x in comps]))

 


if __name__ == '__main__':
    from sympy import Function, exp
    from sympy.functions import Abs
    from sympy.integrals import Integral
    v1 = Vector('v1',dim=2)
    v2 = Vector('v2',dim=2)
    i = Symbol('i',integer=True)
    a = Symbol('a')
    print v1,type(v1)
    #e = 2*Integral(Abs(v1-v2),(v1,0.2))
    V = Function('V')
    #V2 = V(i)
    e = Integral(exp(-a*V(v1)),v1)
    
    print e,e.subs(V(v1),V(Abs(v1)))

Ejemplo n.º 17
0
from sympy import *
from sympy import sin, sqrt
from sympy.abc import x, n
from sympy.integrals import Integral

x = Symbol('x')

# example 1: finding the indefinite integral for function: x**2+8 = x**4 + 7*x**(3 + 8)
# reminder: Indefinite integral is an integral with no lower or upper limit specified.
integralex = Integral((x**2) + 8, x)
print(integralex.doit())  # x**3/3 + 8*x

# example 2: integrating the same function above (x**2+8), but we will perform a definite integral with
# respect to a lower limit of 2 and an upper limit of 4.
x = Symbol('x')

integralex = Integral(
    (x**2) + 8, (x, 2, 4)
)  # the second argument reads as: wrt x variable, with lower limit 2, and upper limit 4
print(integralex.doit())
Ejemplo n.º 18
0
 def inverse(self):
     # don't use integrate here because fx has been replaced by _t
     # in the equation; integrals will not be correct while solve
     # is at work.
     return lambda expr: Integral(expr, var) + Dummy('C')
Ejemplo n.º 19
0
 def _as_integral(self, f, t, s):
     from sympy import Integral, exp
     return Integral(f * exp(-s * t), (t, 0, oo))
Ejemplo n.º 20
0
 def _as_integral(self, F, s, x):
     from sympy import Integral, I, oo
     c = self.__class__._c
     return Integral(F * x**(-s), (s, c - I * oo, c + I * oo))
Ejemplo n.º 21
0
 def _as_integral(self, f, x, s):
     from sympy import Integral
     return Integral(f * x**(s - 1), (x, 0, oo))
Ejemplo n.º 22
0
 def _as_integral(self, f, x, k):
     from sympy import Integral, exp, I
     a = self.__class__._a
     b = self.__class__._b
     return Integral(a * f * exp(b * I * x * k), (x, -oo, oo))
Ejemplo n.º 23
0
 def _as_integral(self, F, s, t):
     from sympy import I, Integral, exp
     c = self.__class__._c
     return Integral(exp(s * t) * F, (s, c - I * oo, c + I * oo))
Ejemplo n.º 24
0
    def euler_maclaurin(self, m=0, n=0, eps=0, eval_integral=True):
        """
        Return an Euler-Maclaurin approximation of self, where m is the
        number of leading terms to sum directly and n is the number of
        terms in the tail.

        With m = n = 0, this is simply the corresponding integral
        plus a first-order endpoint correction.

        Returns (s, e) where s is the Euler-Maclaurin approximation
        and e is the estimated error (taken to be the magnitude of
        the first omitted term in the tail):

            >>> from sympy.abc import k, a, b
            >>> from sympy import Sum
            >>> Sum(1/k, (k, 2, 5)).doit().evalf()
            1.28333333333333
            >>> s, e = Sum(1/k, (k, 2, 5)).euler_maclaurin()
            >>> s
            -log(2) + 7/20 + log(5)
            >>> from sympy import sstr
            >>> print(sstr((s.evalf(), e.evalf()), full_prec=True))
            (1.26629073187415, 0.0175000000000000)

        The endpoints may be symbolic:

            >>> s, e = Sum(1/k, (k, a, b)).euler_maclaurin()
            >>> s
            -log(a) + log(b) + 1/(2*b) + 1/(2*a)
            >>> e
            Abs(1/(12*b**2) - 1/(12*a**2))

        If the function is a polynomial of degree at most 2n+1, the
        Euler-Maclaurin formula becomes exact (and e = 0 is returned):

            >>> Sum(k, (k, 2, b)).euler_maclaurin()
            (b**2/2 + b/2 - 1, 0)
            >>> Sum(k, (k, 2, b)).doit()
            b**2/2 + b/2 - 1

        With a nonzero eps specified, the summation is ended
        as soon as the remainder term is less than the epsilon.
        """
        from sympy.functions import bernoulli, factorial
        from sympy.integrals import Integral

        m = int(m)
        n = int(n)
        f = self.function
        if len(self.limits) != 1:
            raise ValueError("More than 1 limit")
        i, a, b = self.limits[0]
        if (a > b) == True:
            if a - b == 1:
                return S.Zero, S.Zero
            a, b = b + 1, a - 1
            f = -f
        s = S.Zero
        if m:
            if b.is_Integer and a.is_Integer:
                m = min(m, b - a + 1)
            if not eps or f.is_polynomial(i):
                for k in range(m):
                    s += f.subs(i, a + k)
            else:
                term = f.subs(i, a)
                if term:
                    test = abs(term.evalf(3)) < eps
                    if test == True:
                        return s, abs(term)
                    elif not (test == False):
                        # a symbolic Relational class, can't go further
                        return term, S.Zero
                s += term
                for k in range(1, m):
                    term = f.subs(i, a + k)
                    if abs(term.evalf(3)) < eps and term != 0:
                        return s, abs(term)
                    s += term
            if b - a + 1 == m:
                return s, S.Zero
            a += m
        x = Dummy('x')
        I = Integral(f.subs(i, x), (x, a, b))
        if eval_integral:
            I = I.doit()
        s += I

        def fpoint(expr):
            if b is S.Infinity:
                return expr.subs(i, a), 0
            return expr.subs(i, a), expr.subs(i, b)

        fa, fb = fpoint(f)
        iterm = (fa + fb) / 2
        g = f.diff(i)
        for k in range(1, n + 2):
            ga, gb = fpoint(g)
            term = bernoulli(2 * k) / factorial(2 * k) * (gb - ga)
            if (eps and term and abs(term.evalf(3)) < eps) or (k > n):
                break
            s += term
            g = g.diff(i, 2, simplify=False)
        return s + iterm, abs(term)
def approximate(func, from_val, to_val, degree):
    """
    Approximate given continuous function over real numbers, using a polynomial of given degree, with inner product
    defined as <f, g> = INTEGRATE f(x) * g(x) dx from a to b.
    :param func: Function to approximate represented in a string, with variable as 'x'.
    :param from_val: a as a string.
    :param to_val: b as a string.
    :param degree: Highest degree of result polynomial, as an integer.
    :return: Approximated polynomial function in string format.
    """
    print('------ Started Calculating Approximation ------')
    print()
    print('f(x) = {0}'.format(func))
    print()
    start_time = time.time()
    orth_basis = orthonormal_basis(_get_float_value(from_val),
                                   _get_float_value(to_val), degree)
    print('Orthonormal basis:')
    for idx, ele in enumerate(orth_basis):
        print('e{0} = {1}'.format(idx + 1, ele))
    print()
    x = sp.Symbol('x')
    res = 0
    func_str = '({0})'.format(func)
    for idx, e_j in enumerate(orth_basis):
        start_time_e_j = time.time()
        if idx is 0:
            print('Calculating projection on span(e{0}) --- '.format(idx + 1),
                  end='')
        else:
            print(
                'Calculating projection on span(e1,...,e{0}) --- '.format(idx +
                                                                          1),
                end='')
        e_j_str = '({0})'.format(
            e_j.standard_coeff_rep(show_mul_op=True, double_stars=True))
        product_str = '{0} * {1}'.format(func_str, e_j_str)
        func_product = parse_expr(product_str)
        tmp = Integral(func_product,
                       (x, from_val, to_val)).as_sum(100,
                                                     method="midpoint").n()
        tmp *= parse_expr(e_j_str)
        res += tmp
        end_time_e_j = time.time()
        print('%.2fs' % (end_time_e_j - start_time_e_j))
        # Print the current result
        tmp_res = str(res)
        tmp_res = tmp_res.replace('**', '^')
        tmp_res = tmp_res.replace('*', '')
        tmp_res = Polynomial(tmp_res)
        print()
        print('    f{0}(x) = {1}'.format(idx + 1, tmp_res))
        print()
    end_time = time.time()
    print()
    print("Duration: %.2fs" % (end_time - start_time))
    print()
    print('------ Finished Calculating Approximation ------')
    res = str(res)
    res = res.replace('**', '^')
    res = res.replace('*', '')
    res = Polynomial(res)
    return res
Ejemplo n.º 26
0
    def euler_maclaurin(self, m=0, n=0, eps=0, eval_integral=True):
        """
        Return an Euler-Maclaurin approximation of self, where m is the
        number of leading terms to sum directly and n is the number of
        terms in the tail.

        With m = n = 0, this is simply the corresponding integral
        plus a first-order endpoint correction.

        Returns (s, e) where s is the Euler-Maclaurin approximation
        and e is the estimated error (taken to be the magnitude of
        the first omitted term in the tail):

            >>> from sympy.abc import k, a, b
            >>> from sympy import Sum
            >>> Sum(1/k, (k, 2, 5)).doit().evalf()
            1.28333333333333
            >>> s, e = Sum(1/k, (k, 2, 5)).euler_maclaurin()
            >>> s
            -log(2) + 7/20 + log(5)
            >>> from sympy import sstr
            >>> print(sstr((s.evalf(), e.evalf()), full_prec=True))
            (1.26629073187415, 0.0175000000000000)

        The endpoints may be symbolic:

            >>> s, e = Sum(1/k, (k, a, b)).euler_maclaurin()
            >>> s
            -log(a) + log(b) + 1/(2*b) + 1/(2*a)
            >>> e
            Abs(1/(12*b**2) - 1/(12*a**2))

        If the function is a polynomial of degree at most 2n+1, the
        Euler-Maclaurin formula becomes exact (and e = 0 is returned):

            >>> Sum(k, (k, 2, b)).euler_maclaurin()
            (b**2/2 + b/2 - 1, 0)
            >>> Sum(k, (k, 2, b)).doit()
            b**2/2 + b/2 - 1

        With a nonzero eps specified, the summation is ended
        as soon as the remainder term is less than the epsilon.
        """
        from sympy.functions import bernoulli, factorial
        from sympy.integrals import Integral

        m = int(m)
        n = int(n)
        f = self.function
        if len(self.limits) != 1:
            raise ValueError("More than 1 limit")
        i, a, b = self.limits[0]
        if (a > b) == True:
            if a - b == 1:
                return S.Zero,S.Zero
            a, b = b + 1, a - 1
            f = -f
        s = S.Zero
        if m:
            if b.is_Integer and a.is_Integer:
                m = min(m, b - a + 1)
            if not eps or f.is_polynomial(i):
                for k in range(m):
                    s += f.subs(i, a + k)
            else:
                term = f.subs(i, a)
                if term:
                    test = abs(term.evalf(3)) < eps
                    if test == True:
                        return s, abs(term)
                    elif not (test == False):
                        # a symbolic Relational class, can't go further
                        return term, S.Zero
                s += term
                for k in range(1, m):
                    term = f.subs(i, a + k)
                    if abs(term.evalf(3)) < eps and term != 0:
                        return s, abs(term)
                    s += term
            if b - a + 1 == m:
                return s, S.Zero
            a += m
        x = Dummy('x')
        I = Integral(f.subs(i, x), (x, a, b))
        if eval_integral:
            I = I.doit()
        s += I

        def fpoint(expr):
            if b is S.Infinity:
                return expr.subs(i, a), 0
            return expr.subs(i, a), expr.subs(i, b)
        fa, fb = fpoint(f)
        iterm = (fa + fb)/2
        g = f.diff(i)
        for k in range(1, n + 2):
            ga, gb = fpoint(g)
            term = bernoulli(2*k)/factorial(2*k)*(gb - ga)
            if (eps and term and abs(term.evalf(3)) < eps) or (k > n):
                break
            s += term
            g = g.diff(i, 2, simplify=False)
        return s + iterm, abs(term)