예제 #1
0
    def eval(cls, arg):
        if arg.is_Number:
            if arg is S.NaN:
                return S.NaN
            elif arg is S.Infinity:
                return S.Infinity
            elif arg.is_Integer:
                if arg.is_positive:
                    return C.Factorial(arg - 1)
                else:
                    return S.ComplexInfinity
            elif arg.is_Rational:
                if arg.q == 2:
                    n = abs(arg.p) // arg.q

                    if arg.is_positive:
                        k, coeff = n, S.One
                    else:
                        n = k = n + 1

                        if n & 1 == 0:
                            coeff = S.One
                        else:
                            coeff = S.NegativeOne

                    for i in range(3, 2 * k, 2):
                        coeff *= i

                    if arg.is_positive:
                        return coeff * sqrt(S.Pi) / 2**n
                    else:
                        return 2**n * sqrt(S.Pi) / coeff
예제 #2
0
    def _eval_expand_func(self, deep=True, **hints):
        if deep:
            hints['func'] = False
            n = self.args[0].expand(deep, **hints)
            z = self.args[1].expand(deep, **hints)
        else:
            n, z = self.args[0], self.args[1].expand(deep, func=True)

        if n.is_Integer and n.is_nonnegative:
            if z.is_Add:
                coeff, factors = z.as_coeff_factors()

                if coeff.is_Integer:
                    tail = Add(*[z + i for i in xrange(0, int(coeff))])
                    return polygamma(
                        n, z - coeff) + (-1)**n * C.Factorial(n) * tail
            elif z.is_Mul:
                coeff, terms = z.as_coeff_terms()

                if coeff.is_Integer and coeff.is_positive:
                    tail = [
                        polygamma(n, z + i // coeff)
                        for i in xrange(0, int(coeff))
                    ]

                    if n is S.Zero:
                        return log(coeff) + Add(*tail) / coeff**(n + 1)
                    else:
                        return Add(*tail) / coeff**(n + 1)

        return polygamma(n, z)
예제 #3
0
    def _eval_expand_func(self, deep=True, **hints):
        if deep:
            hints['func'] = False
            n = self.args[0].expand(deep, **hints)
            z = self.args[1].expand(deep, **hints)
        else:
            n, z = self.args[0], self.args[1].expand(deep, func=True)

        if n.is_Integer and n.is_nonnegative:
            if z.is_Add:
                coeff = z.args[0]
                if coeff.is_Integer:
                    e = -(n + 1)
                    if coeff > 0:
                        tail = Add(*[C.Pow(z - i, e)  for i in xrange(1, int(coeff) + 1)])
                    else:
                        tail = -Add(*[C.Pow(z + i, e)  for i in xrange(0, int(-coeff))])
                    return polygamma(n, z - coeff) + (-1)**n*C.Factorial(n)*tail

            elif z.is_Mul:
                coeff, z = z.as_two_terms()
                if coeff.is_Integer and coeff.is_positive:
                    tail = [ polygamma(n, z + C.Rational(i, coeff)) for i in xrange(0, int(coeff)) ]
                    if n == 0:
                        return Add(*tail)/coeff + log(coeff)
                    else:
                        return Add(*tail)/coeff**(n+1)

        return polygamma(n, z)
예제 #4
0
    def eval(cls, n, z):
        n, z = map(sympify, (n, z))

        if n.is_integer:
            if n.is_negative:
                return loggamma(z)
            else:
                if z.is_Number:
                    if z is S.NaN:
                        return S.NaN
                    elif z is S.Infinity:
                        if n.is_Number:
                            if n is S.Zero:
                                return S.Infinity
                            else:
                                return S.Zero
                    elif z.is_Integer:
                        if z.is_nonpositive:
                            return S.ComplexInfinity
                        else:
                            if n is S.Zero:
                                return -S.EulerGamma + C.harmonic(z - 1, 1)
                            elif n.is_odd:
                                return (-1)**(n + 1) * C.Factorial(n) * zeta(
                                    n + 1, z)
예제 #5
0
    def eval(cls, z, a=S.One):
        z, a = map(sympify, (z, a))

        if a.is_Number:
            if a is S.NaN:
                return S.NaN
            elif a is S.Zero:
                return cls(z)

        if z.is_Number:
            if z is S.NaN:
                return S.NaN
            elif z is S.Infinity:
                return S.One
            elif z is S.Zero:
                if a.is_negative:
                    return S.Half - a - 1
                else:
                    return S.Half - a
            elif z is S.One:
                return S.ComplexInfinity
            elif z.is_Integer:
                if a.is_Integer:
                    if z.is_negative:
                        zeta = (-1)**z * C.bernoulli(-z+1)/(-z+1)
                    elif z.is_even:
                        B, F = C.bernoulli(z), C.Factorial(z)
                        zeta = 2**(z-1) * abs(B) * pi**z / F
                    else:
                        return

                    if a.is_negative:
                        return zeta + C.harmonic(abs(a), z)
                    else:
                        return zeta - C.harmonic(a-1, z)
예제 #6
0
 def taylor_term(n, x, *previous_terms):
     if n < 0: return S.Zero
     if n == 0: return S.One
     x = sympify(x)
     if previous_terms:
         p = previous_terms[-1]
         if p is not None:
             return p * x / n
     return x**n / C.Factorial()(n)
예제 #7
0
    def taylor_term(n, x, *previous_terms):
        if n < 0 or n % 2 == 0:
            return S.Zero
        else:
            x = sympify(x)

            if len(previous_terms) > 2:
                p = previous_terms[-2]
                return p * x**2 / (n*(n-1))
            else:
                return x**(n) / C.Factorial(n)
예제 #8
0
    def taylor_term(n, x, *previous_terms):
        if n < 0 or n % 2 == 0:
            return S.Zero
        else:
            x = sympify(x)

            k = (n - 1) // 2

            if len(previous_terms) > 2:
                return -previous_terms[-2] * x**2 * (n - 2) / (n * k)
            else:
                return 2 * (-1)**k * x**n / (n * C.Factorial(k) * sqrt(S.Pi))
예제 #9
0
    def taylor_term(n, x, *previous_terms):
        if n == 0:
            return 1 / sympify(x)
        elif n < 0 or n % 2 == 0:
            return S.Zero
        else:
            x = sympify(x)

            B = C.bernoulli(n+1)
            F = C.Factorial(n+1)

            return 2**(n+1) * B/F * x**n
예제 #10
0
 def taylor_term(n, x, *previous_terms):
     if n < 0 or n % 2 == 0:
         return S.Zero
     else:
         x = sympify(x)
         if len(previous_terms) >= 2 and n > 2:
             p = previous_terms[-2]
             return -p * (n-2)**2/(n*(n-1)) * x**2
         else:
             k = (n - 1) // 2
             R = C.RisingFactorial(S.Half, k)
             F = C.Factorial(k)
             return (-1)**k * R / F * x**n / n
예제 #11
0
 def _eval_rewrite_as_zeta(self, n, z):
     return (-1)**(n + 1) * C.Factorial(n) * zeta(n + 1, z - 1)
예제 #12
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):

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

        The endpoints may be symbolic:

            >>> k, a, b = symbols('kab')
            >>> s, e = Sum(1/k, (k, a, b)).euler_maclaurin()
            >>> s
            -log(a) + log(b) + 1/(2*a) + 1/(2*b)
            >>> 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()
            (-1 + b/2 + b**2/2, 0)
            >>> Sum(k, (k, 2, b)).doit()
            -1 + b/2 + b**2/2

        With a nonzero eps specified, the summation is ended
        as soon as the remainder term is less than the epsilon.
        """
        m = int(m)
        n = int(n)
        f = self.function
        assert len(self.limits) == 1
        i, a, b = self.limits[0]
        s = S.Zero
        if m:
            for k in range(m):
                term = f.subs(i, a + k)
                if (eps and term and abs(term.evalf(3)) < eps):
                    return s, abs(term)
                s += term
            a += m
        x = Symbol('x', dummy=True)
        I = C.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 xrange(1, n + 2):
            ga, gb = fpoint(g)
            term = C.bernoulli(2 * k) / C.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)
        return s + iterm, abs(term)