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
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)
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)
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)
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)
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)
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)
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))
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
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
def _eval_rewrite_as_zeta(self, n, z): return (-1)**(n + 1) * C.Factorial(n) * zeta(n + 1, z - 1)
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)