def _eval_expand_trig(self, **hints): arg = self.args[0] x = None if arg.is_Add: from sympy import symmetric_poly n = len(arg.args) CX = [] for x in arg.args: cx = cot(x, evaluate=False)._eval_expand_trig() CX.append(cx) Yg = numbered_symbols("Y") Y = [Yg.next() for i in xrange(n)] p = [0, 0] for i in xrange(n, -1, -1): p[(n - i) % 2] += symmetric_poly(i, Y) * (-1) ** (((n - i) % 4) // 2) return (p[0] / p[1]).subs(zip(Y, CX)) else: coeff, terms = arg.as_coeff_Mul(rational=True) if coeff.is_Integer and coeff > 1: I = S.ImaginaryUnit z = C.Symbol("dummy", real=True) P = ((z + I) ** coeff).expand() return (C.re(P) / C.im(P)).subs([(z, cot(terms))]) return cot(arg)
def solve_ODE_first_order(eq, f): """ solves many kinds of first order odes, different methods are used depending on the form of the given equation. Now the linear and Bernoulli cases are implemented. """ from sympy.integrals.integrals import integrate x = f.args[0] f = f.func #linear case: a(x)*f'(x)+b(x)*f(x)+c(x) = 0 a = Wild('a', exclude=[f(x)]) b = Wild('b', exclude=[f(x)]) c = Wild('c', exclude=[f(x)]) r = eq.match(a*diff(f(x),x) + b*f(x) + c) if r: t = C.exp(integrate(r[b]/r[a], x)) tt = integrate(t*(-r[c]/r[a]), x) return (tt + Symbol("C1"))/t #Bernoulli case: a(x)*f'(x)+b(x)*f(x)+c(x)*f(x)^n = 0 n = Wild('n', exclude=[f(x)]) r = eq.match(a*diff(f(x),x) + b*f(x) + c*f(x)**n) if r: t = C.exp((1-r[n])*integrate(r[b]/r[a],x)) tt = (r[n]-1)*integrate(t*r[c]/r[a],x) return ((tt + Symbol("C1"))/t)**(1/(1-r[n])) #other cases of first order odes will be implemented here raise NotImplementedError("solve_ODE_first_order: Cannot solve " + str(eq))
def _eval_expand_complex(self, deep=True, **hints): re, im = self.args[0].as_real_imag() if deep: re = re.expand(deep, **hints) im = im.expand(deep, **hints) cos, sin = C.cos(im), C.sin(im) return exp(re) * cos + S.ImaginaryUnit * exp(re) * sin
def _eval_expand_trig(self, **hints): from sympy import expand_mul arg = self.args[0] x = None if arg.is_Add: # TODO, implement more if deep stuff here # TODO: Do this more efficiently for more than two terms x, y = arg.as_two_terms() sx = sin(x, evaluate=False)._eval_expand_trig() sy = sin(y, evaluate=False)._eval_expand_trig() cx = cos(x, evaluate=False)._eval_expand_trig() cy = cos(y, evaluate=False)._eval_expand_trig() return sx*cy + sy*cx else: n, x = arg.as_coeff_Mul(rational=True) if n.is_Integer: # n will be positive because of .eval # canonicalization # See http://mathworld.wolfram.com/Multiple-AngleFormulas.html if n.is_odd: return (-1)**((n - 1)/2)*C.chebyshevt(n, sin(x)) else: return expand_mul((-1)**(n/2 - 1)*cos(x)*C.chebyshevu(n - 1, sin(x)), deep=False) pi_coeff = _pi_coeff(arg) if pi_coeff is not None: if pi_coeff.is_Rational: return self.rewrite(sqrt) return sin(arg)
def vertices(self): points = [] c, r, n = self v = 2*S.Pi/n for k in xrange(0, n): points.append( Point(c[0] + r*C.cos(k*v), c[1] + r*C.sin(k*v)) ) return points
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.NegativeInfinity elif arg is S.Zero: return S.Zero elif arg is S.One: return C.log(2 ** S.Half + 1) elif arg is S.NegativeOne: return C.log(2 ** S.Half - 1) elif arg.is_negative: return -cls(-arg) else: i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.asin(i_coeff) else: coeff, terms = arg.as_coeff_terms() if coeff.is_negative: return -cls(-arg)
def _eval_expand_trig(self, **hints): arg = self.args[0] x = None if arg.is_Add: from sympy import symmetric_poly n = len(arg.args) TX = [] for x in arg.args: tx = tan(x, evaluate=False)._eval_expand_trig() TX.append(tx) Yg = numbered_symbols('Y') Y = [ Yg.next() for i in xrange(n) ] p = [0,0] for i in xrange(n+1): p[1-i%2] += symmetric_poly(i,Y)*(-1)**((i%4)//2) return (p[0]/p[1]).subs(zip(Y,TX)) else: coeff, terms = arg.as_coeff_Mul(rational=True) if coeff.is_Integer and coeff > 1: I = S.ImaginaryUnit z = C.Symbol('dummy',real=True) P = ((1+I*z)**coeff).expand() return (C.im(P)/C.re(P)).subs([(z,tan(terms))]) return tan(arg)
def monomial_count(V, N): r""" Computes the number of monomials. The number of monomials is given by the following formula: .. math:: \frac{(\#V + N)!}{\#V! N!} where `N` is a total degree and `V` is a set of variables. **Examples** >>> from sympy import monomials, monomial_count >>> from sympy.abc import x, y >>> monomial_count(2, 2) 6 >>> M = monomials([x, y], 2) >>> sorted(M) [1, x, y, x**2, y**2, x*y] >>> len(M) 6 """ return C.factorial(V + N) / C.factorial(V) / C.factorial(N)
def _eval_expand_complex(self, *args): if self.args[0].is_real: return self re, im = self.args[0].as_real_imag() denom = sin(re)**2 + C.sinh(im)**2 return (sin(re)*cos(re) - \ S.ImaginaryUnit*C.sinh(im)*C.cosh(im))/denom
def _eval_rewrite_as_polynomial(self, n, m, x): k = C.Dummy("k") kern = ( C.factorial(2 * n - 2 * k) / (2 ** n * C.factorial(n - k) * C.factorial(k) * C.factorial(n - 2 * k - m)) * (-1) ** k * x ** (n - m - 2 * k) ) return (1 - x ** 2) ** (m / 2) * C.Sum(kern, (k, 0, C.floor((n - m) * S.Half)))
def _eval_expand_func(self, **hints): n, m, theta, phi = self.args rv = ( sqrt((2 * n + 1) / (4 * pi) * C.factorial(n - m) / C.factorial(n + m)) * C.exp(I * m * phi) * assoc_legendre(n, m, C.cos(theta)) ) # We can do this because of the range of theta return rv.subs(sqrt(-cos(theta) ** 2 + 1), sin(theta))
def solve_ODE_second_order(eq, f): """ solves many kinds of second order odes, different methods are used depending on the form of the given equation. So far the constants coefficients case and a special case are implemented. """ x = f.args[0] f = f.func #constant coefficients case: af''(x)+bf'(x)+cf(x)=0 a = Wild('a', exclude=[x]) b = Wild('b', exclude=[x]) c = Wild('c', exclude=[x]) r = eq.match(a*f(x).diff(x,x) + c*f(x)) if r: return Symbol("C1")*C.sin(sqrt(r[c]/r[a])*x)+Symbol("C2")*C.cos(sqrt(r[c]/r[a])*x) r = eq.match(a*f(x).diff(x,x) + b*diff(f(x),x) + c*f(x)) if r: r1 = solve(r[a]*x**2 + r[b]*x + r[c], x) if r1[0].is_real: if len(r1) == 1: return (Symbol("C1") + Symbol("C2")*x)*exp(r1[0]*x) else: return Symbol("C1")*exp(r1[0]*x) + Symbol("C2")*exp(r1[1]*x) else: r2 = abs((r1[0] - r1[1])/(2*S.ImaginaryUnit)) return (Symbol("C2")*C.cos(r2*x) + Symbol("C1")*C.sin(r2*x))*exp((r1[0] + r1[1])*x/2) #other cases of the second order odes will be implemented here #special equations, that we know how to solve a = Wild('a') t = x*exp(f(x)) tt = a*t.diff(x, x)/t r = eq.match(tt.expand()) if r: return -solve_ODE_1(f(x), x) t = x*exp(-f(x)) tt = a*t.diff(x, x)/t r = eq.match(tt.expand()) if r: #check, that we've rewritten the equation correctly: #assert ( r[a]*t.diff(x,2)/t ) == eq.subs(f, t) return solve_ODE_1(f(x), x) neq = eq*exp(f(x))/exp(-f(x)) r = neq.match(tt.expand()) if r: #check, that we've rewritten the equation correctly: #assert ( t.diff(x,2)*r[a]/t ).expand() == eq return solve_ODE_1(f(x), x) raise NotImplementedError("solve_ODE_second_order: cannot solve " + str(eq))
def eval(cls, r, k): r, k = map(sympify, (r, k)) if k.is_Number: if k is S.Zero: return S.One elif k.is_Integer: if k.is_negative: return S.Zero else: if r.is_Integer and r.is_nonnegative: r, k = int(r), int(k) if k > r: return S.Zero elif k > r // 2: k = r - k M, result = int(sqrt(r)), 1 for prime in sieve.primerange(2, r+1): if prime > r - k: result *= prime elif prime > r // 2: continue elif prime > M: if r % prime < k % prime: result *= prime else: R, K = r, k exp = a = 0 while R > 0: a = int((R % prime) < (K % prime + a)) R, K = R // prime, K // prime exp = a + exp if exp > 0: result *= prime**exp return C.Integer(result) else: result = r - k + 1 for i in xrange(2, k+1): result *= r-k+i result /= i return result if k.is_integer: if k.is_negative: return S.Zero else: return C.gamma(r+1)/(C.gamma(r-k+1)*C.gamma(k+1))
def _eval_rewrite_as_polynomial(self, n, a, b, x): # TODO: Make sure n \in N k = C.Dummy("k") kern = ( C.RisingFactorial(-n, k) * C.RisingFactorial(a + b + n + 1, k) * C.RisingFactorial(a + k + 1, n - k) / C.factorial(k) * ((1 - x) / 2) ** k ) return 1 / C.factorial(n) * C.Sum(kern, (k, 0, n))
def as_real_imag(self, deep=True, **hints): if self.args[0].is_real: if deep: hints['complex'] = False return (self.expand(deep, **hints), S.Zero) else: return (self, S.Zero) if deep: re, im = self.args[0].expand(deep, **hints).as_real_imag() else: re, im = self.args[0].as_real_imag() return (cos(re)*C.cosh(im), -sin(re)*C.sinh(im))
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 (-1)**((n+1)//2) * 2**(n+1) * B/F * x**n
def as_real_imag(self, deep=True, **hints): if self.args[0].is_real: if deep: return (self.expand(deep, **hints), S.Zero) else: return (self, S.Zero) if deep: re, im = self.args[0].expand(deep, **hints).as_real_imag() else: re, im = self.args[0].as_real_imag() denom = sinh(re) ** 2 + C.sin(im) ** 2 return (sinh(re) * cosh(re) / denom, -C.sin(im) * C.cos(im) / denom)
def _eval_expand_complex(self, deep=True, **hints): if deep: abs = C.abs(self.args[0].expand(deep, **hints)) arg = C.arg(self.args[0].expand(deep, **hints)) else: abs = C.abs(self.args[0]) arg = C.arg(self.args[0]) if hints['log']: # Expand the log hints['complex'] = False return log(abs).expand(deep, **hints) + S.ImaginaryUnit * arg else: return log(abs) + S.ImaginaryUnit * arg
def taylor_term(n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = sympify(x) a, b = ((n-1)//2), 2**(n+1) B = C.bernoulli(n+1) F = C.factorial(n+1) return (-1)**a * b*(b-1) * B/F * x**n
def _eval_expand_complex(self, deep=True, **hints): if self.args[0].is_real: if deep: hints['complex'] = False return self.expand(deep, **hints) else: return self if deep: re, im = self.args[0].expand(deep, **hints).as_real_imag() else: re, im = self.args[0].as_real_imag() return sin(re)*C.cosh(im) + S.ImaginaryUnit*cos(re)*C.sinh(im)
def _eval_expand_complex(self, deep=True, **hints): if self.args[0].is_real: if deep: return self.expand(deep, **hints) else: return self if deep: re, im = self.args[0].expand(deep, **hints).as_real_imag() else: re, im = self.args[0].as_real_imag() denom = sinh(re)**2 + C.sin(im)**2 return (sinh(re)*cosh(re) - \ S.ImaginaryUnit*C.sin(im)*C.cos(im))/denom
def eval(cls, n, m, theta, phi): n, m, theta, phi = [sympify(x) for x in (n, m, theta, phi)] # Handle negative index m and arguments theta, phi if m.could_extract_minus_sign(): m = -m return S.NegativeOne**m * C.exp(-2*I*m*phi) * Ynm(n, m, theta, phi) if theta.could_extract_minus_sign(): theta = -theta return Ynm(n, m, theta, phi) if phi.could_extract_minus_sign(): phi = -phi return C.exp(-2*I*m*phi) * Ynm(n, m, theta, phi)
def as_real_imag(self, deep=True, **hints): other = [] coeff = S(1) for a in self.args: if a.is_real: coeff *= a else: other.append(a) m = Mul(*other) if hints.get('ignore') == m: return None else: return (coeff*C.re(m), coeff*C.im(m))
def eval(cls, n, m, x): if n.is_integer and n >= 0 and m.is_integer and abs(m) <= n: assoc = cls.calc(int(n), abs(int(m))) if m < 0: assoc *= (-1)**(-m) * (C.factorial(n + m)/C.factorial(n - m)) return assoc.subs(_x, x) if n.is_negative: raise ValueError("%s : 1st index must be nonnegative integer (got %r)" % (cls, n)) if abs(m) > n: raise ValueError("%s : abs('2nd index') must be <= '1st index' (got %r, %r)" % (cls, n, m))
def eval(cls, arg): if arg.is_integer: return arg if arg.is_imaginary or (S.ImaginaryUnit*arg).is_real: i = C.im(arg) if not i.has(S.ImaginaryUnit): return cls(i)*S.ImaginaryUnit return cls(arg, evaluate=False) v = cls._eval_number(arg) if v is not None: return v # Integral, numerical, symbolic part ipart = npart = spart = S.Zero # Extract integral (or complex integral) terms terms = Add.make_args(arg) for t in terms: if t.is_integer or (t.is_imaginary and C.im(t).is_integer): ipart += t elif t.has(C.Symbol): spart += t else: npart += t if not (npart or spart): return ipart # Evaluate npart numerically if independent of spart if npart and ( not spart or npart.is_real and (spart.is_imaginary or (S.ImaginaryUnit*spart).is_real) or npart.is_imaginary and spart.is_real): try: re, im = get_integer_part( npart, cls._dir, {}, return_ints=True) ipart += C.Integer(re) + C.Integer(im)*S.ImaginaryUnit npart = S.Zero except (PrecisionExhausted, NotImplementedError): pass spart += npart if not spart: return ipart elif spart.is_imaginary or (S.ImaginaryUnit*spart).is_real: return ipart + cls(C.im(spart), evaluate=False)*S.ImaginaryUnit else: return ipart + cls(spart, evaluate=False)
def eval(cls, n, m, x): if m.could_extract_minus_sign(): # P^{-m}_n ---> F * P^m_n return S.NegativeOne**(-m) * (C.factorial(m + n)/C.factorial(n - m)) * assoc_legendre(n, -m, x) if m == 0: # P^0_n ---> L_n return legendre(n, x) if x == 0: return 2**m*sqrt(S.Pi) / (C.gamma((1 - m - n)/2)*C.gamma(1 - (m - n)/2)) if n.is_Number and m.is_Number and n.is_integer and m.is_integer: if n.is_negative: raise ValueError("%s : 1st index must be nonnegative integer (got %r)" % (cls, n)) if abs(m) > n: raise ValueError("%s : abs('2nd index') must be <= '1st index' (got %r, %r)" % (cls, n, m)) return cls._eval_at_order(int(n), abs(int(m))).subs(_x, x)
def as_real_imag(self, deep=True, **hints): # TODO: Handle deep and hints n, m, theta, phi = self.args re = (sqrt((2*n + 1)/(4*pi) * C.factorial(n - m)/C.factorial(n + m)) * C.cos(m*phi) * assoc_legendre(n, m, C.cos(theta))) im = (sqrt((2*n + 1)/(4*pi) * C.factorial(n - m)/C.factorial(n + m)) * C.sin(m*phi) * assoc_legendre(n, m, C.cos(theta))) return (re, im)
def canonize(cls, arg): if arg.is_integer: return arg if arg.is_imaginary: return cls(C.im(arg))*S.ImaginaryUnit v = cls._eval_number(arg) if v is not None: return v # Integral, numerical, symbolic part ipart = npart = spart = S.Zero # Extract integral (or complex integral) terms if arg.is_Add: terms = arg.args else: terms = [arg] for t in terms: if t.is_integer or (t.is_imaginary and C.im(t).is_integer): ipart += t elif t.atoms(C.Symbol): spart += t else: npart += t if not (npart or spart): return ipart # Evaluate npart numerically if independent of spart orthogonal = (npart.is_real and spart.is_imaginary) or \ (npart.is_imaginary and spart.is_real) if npart and ((not spart) or orthogonal): try: re, im = get_integer_part(npart, cls._dir, {}, return_ints=True) ipart += C.Integer(re) + C.Integer(im)*S.ImaginaryUnit npart = S.Zero except (PrecisionExhausted, NotImplementedError): pass spart = npart + spart if not spart: return ipart elif spart.is_imaginary: return ipart + cls(C.im(spart),evaluate=False)*S.ImaginaryUnit else: return ipart + cls(spart, evaluate=False)
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Infinity elif arg is S.Zero: return S.One elif arg.is_negative: return cls(-arg) else: i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return C.cos(i_coeff) else: coeff, terms = arg.as_coeff_terms() if coeff.is_negative: return cls(-arg) if arg.func == asinh: return sqrt(1 + arg.args[0] ** 2) if arg.func == acosh: return arg.args[0] if arg.func == atanh: return 1 / sqrt(1 - arg.args[0] ** 2)
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.NegativeInfinity elif arg is S.Zero: return S.Zero elif arg.is_negative: return -cls(-arg) else: i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.sin(i_coeff) else: coeff, terms = arg.as_coeff_terms() if coeff.is_negative: return -cls(-arg) if arg.func == asinh: return arg.args[0] if arg.func == acosh: x = arg.args[0] return sqrt(x - 1) * sqrt(x + 1) if arg.func == atanh: x = arg.args[0] return x / sqrt(1 - x ** 2)
def plot_interval(self, parameter_name='t'): t = C.Symbol(parameter_name, real=True) return [t, 0, 1]
def _eval_rewrite_as_polynomial(self, n, x): k = C.Dummy("k") kern = C.binomial(n, 2 * k) * (x**2 - 1)**k * x**(n - 2 * k) return C.Sum(kern, (k, 0, C.floor(n / 2)))
def _eval_rewrite_as_polynomial(self, n, x): k = C.Dummy("k") kern = S.NegativeOne**k * C.factorial(n - k) * (2 * x)**(n - 2 * k) / ( C.factorial(k) * C.factorial(n - 2 * k)) return C.Sum(kern, (k, 0, C.floor(n / 2)))
def _eval_expand_complex(self, *args): if self.args[0].is_real: return self re, im = self.args[0].as_real_imag() return sinh(re) * C.cos(im) + cosh(re) * C.sin(im) * S.ImaginaryUnit
""" This module mainly implements special orthogonal polynomials. See also functions.combinatorial.numbers which contains some combinatorial polynomials. """ from sympy.core.basic import S, C from sympy.core import Rational from sympy.core.function import Function from sympy.utilities.memoization import recurrence_memo, assoc_recurrence_memo _x = C.Symbol('x', dummy=True) class PolynomialSequence(Function): """Polynomial sequence with 1 index n >= 0 """ nargs = 2 @classmethod def eval(cls, n, x): if n.is_integer and n >= 0: return cls.calc(int(n)).subs(_x, x) if n.is_negative: raise ValueError("%s index must be nonnegative integer (got %r)" % (cls, n))
from sympy.core.basic import C from sympy.core.singleton import S from sympy.core import Rational from sympy.core.function import Function from sympy.functions.combinatorial.factorials import factorial from sympy.polys.orthopolys import ( chebyshevt_poly, chebyshevu_poly, laguerre_poly, hermite_poly, legendre_poly, ) _x = C.Dummy('x') class PolynomialSequence(Function): """Polynomial sequence with one index and n >= 0. """ nargs = 2 @classmethod def eval(cls, n, x): if n.is_integer and n >= 0: return cls._ortho_poly(int(n), _x).subs(_x, x) if n.is_negative: raise ValueError("%s index must be nonnegative integer (got %r)" % (cls, n)) #---------------------------------------------------------------------------- # Chebyshev polynomials of first and second kind
def eval(cls, n, k): if not 0 <= k < n: raise ValueError("must have 0 <= k < n") return C.cos(S.Pi*(k+1)/(n+1))
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN if arg is S.Zero: return S.ComplexInfinity if arg.could_extract_minus_sign(): return -cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return -S.ImaginaryUnit * C.coth(i_coeff) pi_coeff = _pi_coeff(arg, 2) if pi_coeff is not None: if pi_coeff.is_integer: return S.ComplexInfinity if not pi_coeff.is_Rational: narg = pi_coeff*S.Pi if narg != arg: return cls(narg) return None cst_table = { 2 : S.Zero, 3 : 1 / sqrt(3), 4 : S.One, 6 : sqrt(3) } try: result = cst_table[pi_coeff.q] if (2*pi_coeff.p // pi_coeff.q) % 4 in (1, 3): return -result else: return result except KeyError: if pi_coeff.p > pi_coeff.q: p, q = pi_coeff.p % pi_coeff.q, pi_coeff.q if 2 * p > q: return -cls(Rational(q - p, q)*S.Pi) return cls(Rational(p, q)*S.Pi) if arg.is_Add: x, m = _peeloff_pi(arg) if m: if (m*2/S.Pi) % 2 == 0: return cot(x) else: return -tan(x) if arg.func is acot: return arg.args[0] if arg.func is atan: x = arg.args[0] return 1 / x if arg.func is asin: x = arg.args[0] return sqrt(1 - x**2) / x if arg.func is acos: x = arg.args[0] return x / sqrt(1 - x**2)
def _eval_rewrite_as_log(self, x): return S.ImaginaryUnit/2 * \ (C.log((S(1) - S.ImaginaryUnit * x)/(S(1) + S.ImaginaryUnit * x)))
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.Zero elif arg is S.Infinity or arg is S.NegativeInfinity: return if arg.could_extract_minus_sign(): return -cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.sinh(i_coeff) pi_coeff = _pi_coeff(arg) if pi_coeff is not None: if pi_coeff.is_integer: return S.Zero if not pi_coeff.is_Rational: narg = pi_coeff * S.Pi if narg != arg: return cls(narg) return None # http://code.google.com/p/sympy/issues/detail?id=2949 # transform a sine to a cosine, to avoid redundant code if pi_coeff.is_Rational: x = pi_coeff % 2 if x > 1: return -cls((x % 1) * S.Pi) if 2 * x > 1: return cls((1 - x) * S.Pi) narg = ((pi_coeff + C.Rational(3, 2)) % 2) * S.Pi result = cos(narg) if not isinstance(result, cos): return result if pi_coeff * S.Pi != arg: return cls(pi_coeff * S.Pi) return None if arg.is_Add: x, m = _peeloff_pi(arg) if m: return sin(m) * cos(x) + cos(m) * sin(x) if arg.func is asin: return arg.args[0] if arg.func is atan: x = arg.args[0] return x / sqrt(1 + x**2) if arg.func is atan2: y, x = arg.args return y / sqrt(x**2 + y**2) if arg.func is acos: x = arg.args[0] return sqrt(1 - x**2) if arg.func is acot: x = arg.args[0] return 1 / (sqrt(1 + 1 / x**2) * x)
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.One elif arg is S.Infinity or arg is S.NegativeInfinity: # In this cases, it is unclear if we should # return S.NaN or leave un-evaluated. One # useful test case is how "limit(sin(x)/x,x,oo)" # is handled. # See test_sin_cos_with_infinity() an # Test for issue 209 # http://code.google.com/p/sympy/issues/detail?id=2097 # For now, we return un-evaluated. return if arg.could_extract_minus_sign(): return cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return C.cosh(i_coeff) pi_coeff = _pi_coeff(arg) if pi_coeff is not None: if pi_coeff.is_integer: return (S.NegativeOne)**pi_coeff if not pi_coeff.is_Rational: narg = pi_coeff * S.Pi if narg != arg: return cls(narg) return None # cosine formula ##################### # http://code.google.com/p/sympy/issues/detail?id=2949 # explicit calculations are preformed for # cos(k pi / 8), cos(k pi /10), and cos(k pi / 12) # Some other exact values like cos(k pi/15) can be # calculated using a partial-fraction decomposition # by calling cos( X ).rewrite(sqrt) cst_table_some = { 3: S.Half, 5: (sqrt(5) + 1) / 4, } if pi_coeff.is_Rational: q = pi_coeff.q p = pi_coeff.p % (2 * q) if p > q: narg = (pi_coeff - 1) * S.Pi return -cls(narg) if 2 * p > q: narg = (1 - pi_coeff) * S.Pi return -cls(narg) # If nested sqrt's are worse than un-evaluation # you can require q in (1, 2, 3, 4, 6) # q <= 12 returns expressions with 2 or fewer nestings. if q > 12: return None if q in cst_table_some: cts = cst_table_some[pi_coeff.q] return C.chebyshevt(pi_coeff.p, cts).expand() if 0 == q % 2: narg = (pi_coeff * 2) * S.Pi nval = cls(narg) if None == nval: return None x = (2 * pi_coeff + 1) / 2 sign_cos = (-1)**((-1 if x < 0 else 1) * int(abs(x))) return sign_cos * sqrt((1 + nval) / 2) return None if arg.is_Add: x, m = _peeloff_pi(arg) if m: return cos(m) * cos(x) - sin(m) * sin(x) if arg.func is acos: return arg.args[0] if arg.func is atan: x = arg.args[0] return 1 / sqrt(1 + x**2) if arg.func is atan2: y, x = arg.args return x / sqrt(x**2 + y**2) if arg.func is asin: x = arg.args[0] return sqrt(1 - x**2) if arg.func is acot: x = arg.args[0] return 1 / sqrt(1 + 1 / x**2)
def _pi_coeff(arg, cycles=1): """ When arg is a Number times pi (e.g. 3*pi/2) then return the Number normalized to be in the range [0, 2], else None. When an even multiple of pi is encountered, if it is multiplying something with known parity then the multiple is returned as 0 otherwise as 2. Examples: >>> from sympy.functions.elementary.trigonometric import _pi_coeff as coeff >>> from sympy import pi >>> from sympy.abc import x, y >>> coeff(3*x*pi) 3*x >>> coeff(11*pi/7) 11/7 >>> coeff(-11*pi/7) 3/7 >>> coeff(4*pi) 0 >>> coeff(5*pi) 1 >>> coeff(5.0*pi) 1 >>> coeff(5.5*pi) 3/2 >>> coeff(2 + pi) """ arg = sympify(arg) if arg is S.Pi: return S.One elif not arg: return S.Zero elif arg.is_Mul: cx = arg.coeff(S.Pi) if cx: c, x = cx.as_coeff_Mul() # pi is not included as coeff if c.is_Float: # recast exact binary fractions to Rationals f = abs(c) % 1 if f != 0: p = -round(log(f, 2).evalf()) m = 2**p cm = c * m i = int(cm) if i == cm: c = C.Rational(i, m) cx = c * x else: c = C.Rational(int(c)) cx = c * x if x.is_integer: c2 = c % 2 if c2 == 1: return x elif not c2: if x.is_even is not None: # known parity return S.Zero return 2 * x else: return c2 * x return cx
def arbitrary_point(self, parameter_name='t'): """Returns a symbolic point that is on this line segment.""" t = C.Symbol(parameter_name, real=True) x = simplify(self.p1[0] + t * (self.p2[0] - self.p1[0])) y = simplify(self.p1[1] + t * (self.p2[1] - self.p1[1])) return Point(x, y)
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN if arg is S.Zero: return S.ComplexInfinity if arg.could_extract_minus_sign(): return -cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return -S.ImaginaryUnit * C.coth(i_coeff) pi_coeff = _pi_coeff(arg, 2) if pi_coeff is not None: if pi_coeff.is_integer: return S.ComplexInfinity if not pi_coeff.is_Rational: narg = pi_coeff * S.Pi if narg != arg: return cls(narg) return None if pi_coeff.is_Rational: narg = (((pi_coeff + S.Half) % 1) - S.Half) * S.Pi # see cos() to specify which expressions should be # expanded automatically in terms of radicals cresult, sresult = cos(narg), cos(narg - S.Pi / 2) if not isinstance(cresult, cos) \ and not isinstance(sresult, cos): if sresult == 0: return S.ComplexInfinity return cresult / sresult if narg != arg: return cls(narg) if arg.is_Add: x, m = _peeloff_pi(arg) if m: cotm = cot(m) if cotm == 0: return -tan(x) cotx = cot(x) if cotm is S.ComplexInfinity: return cotx if cotm.is_Rational: return (cotm * cotx - 1) / (cotm + cotx) return None if arg.func is acot: return arg.args[0] if arg.func is atan: x = arg.args[0] return 1 / x if arg.func is atan2: y, x = arg.args return x / y if arg.func is asin: x = arg.args[0] return sqrt(1 - x**2) / x if arg.func is acos: x = arg.args[0] return x / sqrt(1 - x**2)
def plot_interval(self, parameter_name='t'): """Returns the plot interval for the default geometric plot of line""" t = C.Symbol(parameter_name, real=True) return [t, -5, 5]
def _eval_rewrite_as_polynomial(self, n, x): k = C.Dummy("k") kern = (-1)**k * C.binomial(n, k)**2 * ((1 + x) / 2)**(n - k) * ( (1 - x) / 2)**k return C.Sum(kern, (k, 0, n))
def _eval_rewrite_as_polynomial(self, n, a, x): k = C.Dummy("k") kern = ((-1)**k * C.RisingFactorial(a, n - k) * (2 * x)**(n - 2 * k) / (C.factorial(k) * C.factorial(n - 2 * k))) return C.Sum(kern, (k, 0, C.floor(n / 2)))
def eval(cls, n, k): if not ((0 <= k) and (k < n)): raise ValueError("must have 0 <= k < n, " "got k = %s and n = %s" % (k, n)) return C.cos(S.Pi * (k + 1) / (n + 1))
def _eval_rewrite_as_polynomial(self, n, x): # TODO: Should make sure n is in N_0 k = C.Dummy("k") kern = C.RisingFactorial( -n, k) / (C.gamma(k + alpha + 1) * C.factorial(k)) * x**k return C.gamma(n + alpha + 1) / C.factorial(n) * C.Sum(kern, (k, 0, n))
def _eval_rewrite_as_log(self, x): return S.Pi/2 + S.ImaginaryUnit * C.log(S.ImaginaryUnit * x + sqrt(1 - x**2))
def eval(cls, n, a, b, x): # Simplify to other polynomials # P^{a, a}_n(x) if a == b: if a == -S.Half: return C.RisingFactorial( S.Half, n) / C.factorial(n) * chebyshevt(n, x) elif a == S.Zero: return legendre(n, x) elif a == S.Half: return C.RisingFactorial( 3 * S.Half, n) / C.factorial(n + 1) * chebyshevu(n, x) else: return C.RisingFactorial(a + 1, n) / C.RisingFactorial( 2 * a + 1, n) * gegenbauer(n, a + S.Half, x) elif b == -a: # P^{a, -a}_n(x) return C.gamma(n + a + 1) / C.gamma(n + 1) * (1 + x)**(a / 2) / ( 1 - x)**(a / 2) * assoc_legendre(n, -a, x) elif a == -b: # P^{-b, b}_n(x) return C.gamma(n - b + 1) / C.gamma(n + 1) * (1 - x)**(b / 2) / ( 1 + x)**(b / 2) * assoc_legendre(n, b, x) if not n.is_Number: # Symbolic result P^{a,b}_n(x) # P^{a,b}_n(-x) ---> (-1)**n * P^{b,a}_n(-x) if x.could_extract_minus_sign(): return S.NegativeOne**n * jacobi(n, b, a, -x) # We can evaluate for some special values of x if x == S.Zero: return (2**(-n) * C.gamma(a + n + 1) / (C.gamma(a + 1) * C.factorial(n)) * C.hyper([-b - n, -n], [a + 1], -1)) if x == S.One: return C.RisingFactorial(a + 1, n) / C.factorial(n) elif x == S.Infinity: if n.is_positive: # TODO: Make sure a+b+2*n \notin Z return C.RisingFactorial(a + b + n + 1, n) * S.Infinity else: # n is a given fixed integer, evaluate into polynomial return jacobi_poly(n, a, b, x)
def _eval_rewrite_as_log(self, x): return S.ImaginaryUnit/2 * \ (C.log((x - S.ImaginaryUnit)/(x + S.ImaginaryUnit)))
def _eval_rewrite_as_polynomial(self, n, x): k = C.Dummy("k") kern = (-1)**k / (C.factorial(k) * C.factorial(n - 2 * k)) * (2 * x)**(n - 2 * k) return C.factorial(n) * C.Sum(kern, (k, 0, C.floor(n / 2)))
def _eval_integral(self, f, x, meijerg=None, risch=None, manual=None, conds='piecewise'): """ Calculate the anti-derivative to the function f(x). The following algorithms are applied (roughly in this order): 1. Simple heuristics (based on pattern matching and integral table): - most frequently used functions (e.g. polynomials, products of trig functions) 2. Integration of rational functions: - A complete algorithm for integrating rational functions is implemented (the Lazard-Rioboo-Trager algorithm). The algorithm also uses the partial fraction decomposition algorithm implemented in apart() as a preprocessor to make this process faster. Note that the integral of a rational function is always elementary, but in general, it may include a RootSum. 3. Full Risch algorithm: - The Risch algorithm is a complete decision procedure for integrating elementary functions, which means that given any elementary function, it will either compute an elementary antiderivative, or else prove that none exists. Currently, part of transcendental case is implemented, meaning elementary integrals containing exponentials, logarithms, and (soon!) trigonometric functions can be computed. The algebraic case, e.g., functions containing roots, is much more difficult and is not implemented yet. - If the routine fails (because the integrand is not elementary, or because a case is not implemented yet), it continues on to the next algorithms below. If the routine proves that the integrals is nonelementary, it still moves on to the algorithms below, because we might be able to find a closed-form solution in terms of special functions. If risch=True, however, it will stop here. 4. The Meijer G-Function algorithm: - This algorithm works by first rewriting the integrand in terms of very general Meijer G-Function (meijerg in SymPy), integrating it, and then rewriting the result back, if possible. This algorithm is particularly powerful for definite integrals (which is actually part of a different method of Integral), since it can compute closed-form solutions of definite integrals even when no closed-form indefinite integral exists. But it also is capable of computing many indefinite integrals as well. - Another advantage of this method is that it can use some results about the Meijer G-Function to give a result in terms of a Piecewise expression, which allows to express conditionally convergent integrals. - Setting meijerg=True will cause integrate() to use only this method. 5. The "manual integration" algorithm: - This algorithm tries to mimic how a person would find an antiderivative by hand, for example by looking for a substitution or applying integration by parts. This algorithm does not handle as many integrands but can return results in a more familiar form. - Sometimes this algorithm can evaluate parts of an integral; in this case integrate() will try to evaluate the rest of the integrand using the other methods here. - Setting manual=True will cause integrate() to use only this method. 6. The Heuristic Risch algorithm: - This is a heuristic version of the Risch algorithm, meaning that it is not deterministic. This is tried as a last resort because it can be very slow. It is still used because not enough of the full Risch algorithm is implemented, so that there are still some integrals that can only be computed using this method. The goal is to implement enough of the Risch and Meijer G methods so that this can be deleted. """ from sympy.integrals.risch import risch_integrate if risch: try: return risch_integrate(f, x, conds=conds) except NotImplementedError: return None if manual: try: result = manualintegrate(f, x) if result is not None and result.func != Integral: return result except (ValueError, PolynomialError): pass # if it is a poly(x) then let the polynomial integrate itself (fast) # # It is important to make this check first, otherwise the other code # will return a sympy expression instead of a Polynomial. # # see Polynomial for details. if isinstance(f, Poly) and not meijerg: return f.integrate(x) # Piecewise antiderivatives need to call special integrate. if f.func is Piecewise: return f._eval_integral(x) # let's cut it short if `f` does not depend on `x` if not f.has(x): return f * x # try to convert to poly(x) and then integrate if successful (fast) poly = f.as_poly(x) if poly is not None and not meijerg: return poly.integrate().as_expr() if risch is not False: try: result, i = risch_integrate(f, x, separate_integral=True, conds=conds) except NotImplementedError: pass else: if i: # There was a nonelementary integral. Try integrating it. return result + i.doit(risch=False) else: return result # since Integral(f=g1+g2+...) == Integral(g1) + Integral(g2) + ... # we are going to handle Add terms separately, # if `f` is not Add -- we only have one term # Note that in general, this is a bad idea, because Integral(g1) + # Integral(g2) might not be computable, even if Integral(g1 + g2) is. # For example, Integral(x**x + x**x*log(x)). But many heuristics only # work term-wise. So we compute this step last, after trying # risch_integrate. We also try risch_integrate again in this loop, # because maybe the integral is a sum of an elementary part and a # nonelementary part (like erf(x) + exp(x)). risch_integrate() is # quite fast, so this is acceptable. parts = [] args = Add.make_args(f) for g in args: coeff, g = g.as_independent(x) # g(x) = const if g is S.One and not meijerg: parts.append(coeff * x) continue # g(x) = expr + O(x**n) order_term = g.getO() if order_term is not None: h = self._eval_integral(g.removeO(), x) if h is not None: h_order_expr = self._eval_integral(order_term.expr, x) if h_order_expr is not None: h_order_term = order_term.func(h_order_expr, *order_term.variables) parts.append(coeff * (h + h_order_term)) continue # NOTE: if there is O(x**n) and we fail to integrate then there is # no point in trying other methods because they will fail anyway. return None # c # g(x) = (a*x+b) if g.is_Pow and not g.exp.has(x) and not meijerg: a = Wild('a', exclude=[x]) b = Wild('b', exclude=[x]) M = g.base.match(a * x + b) if M is not None: if g.exp == -1: h = C.log(g.base) elif conds != 'piecewise': h = g.base**(g.exp + 1) / (g.exp + 1) else: h1 = C.log(g.base) h2 = g.base**(g.exp + 1) / (g.exp + 1) h = Piecewise((h1, Eq(g.exp, -1)), (h2, True)) parts.append(coeff * h / M[a]) continue # poly(x) # g(x) = ------- # poly(x) if g.is_rational_function(x) and not meijerg: parts.append(coeff * ratint(g, x)) continue if not meijerg: # g(x) = Mul(trig) h = trigintegrate(g, x, conds=conds) if h is not None: parts.append(coeff * h) continue # g(x) has at least a DiracDelta term h = deltaintegrate(g, x) if h is not None: parts.append(coeff * h) continue # Try risch again. if risch is not False: try: h, i = risch_integrate(g, x, separate_integral=True, conds=conds) except NotImplementedError: h = None else: if i: h = h + i.doit(risch=False) parts.append(coeff * h) continue # fall back to heurisch try: if conds == 'piecewise': h = heurisch_wrapper(g, x, hints=[]) else: h = heurisch(g, x, hints=[]) except PolynomialError: # XXX: this exception means there is a bug in the # implementation of heuristic Risch integration # algorithm. h = None else: h = None if meijerg is not False and h is None: # rewrite using G functions try: h = meijerint_indefinite(g, x) except NotImplementedError: from sympy.integrals.meijerint import _debug _debug('NotImplementedError from meijerint_definite') res = None if h is not None: parts.append(coeff * h) continue if h is None and manual is not False: try: result = manualintegrate(g, x) if result is not None and not isinstance(result, Integral): if result.has(Integral): # try to have other algorithms do the integrals # manualintegrate can't handle result = result.func(*[ arg.doit( manual=False) if arg.has(Integral) else arg for arg in result.args ]).expand(multinomial=False, log=False, power_exp=False, power_base=False) if not result.has(Integral): parts.append(coeff * result) continue except (ValueError, PolynomialError): # can't handle some SymPy expressions pass # if we failed maybe it was because we had # a product that could have been expanded, # so let's try an expansion of the whole # thing before giving up; we don't try this # at the outset because there are things # that cannot be solved unless they are # NOT expanded e.g., x**x*(1+log(x)). There # should probably be a checker somewhere in this # routine to look for such cases and try to do # collection on the expressions if they are already # in an expanded form if not h and len(args) == 1: f = f.expand(mul=True, deep=False) if f.is_Add: # Note: risch will be identical on the expanded # expression, but maybe it will be able to pick out parts, # like x*(exp(x) + erf(x)). return self._eval_integral(f, x, meijerg=meijerg, risch=risch, conds=conds) if h is not None: parts.append(coeff * h) else: return None return Add(*parts)
def _eval_rewrite_as_polynomial(self, n, x): # TODO: Should make sure n is in N_0 k = C.Dummy("k") kern = C.RisingFactorial(-n, k) / C.factorial(k)**2 * x**k return C.Sum(kern, (k, 0, n))
def sqrt(arg): # arg = sympify(arg) is handled by Pow return C.Pow(arg, S.Half)
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.Zero elif arg is S.Infinity: return if arg.could_extract_minus_sign(): return -cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.sinh(i_coeff) pi_coeff = _pi_coeff(arg) if pi_coeff is not None: if pi_coeff.is_integer: return S.Zero if not pi_coeff.is_Rational: narg = pi_coeff*S.Pi if narg != arg: return cls(narg) return None cst_table_some = { 2 : S.One, 3 : S.Half*sqrt(3), 4 : S.Half*sqrt(2), 6 : S.Half, } cst_table_more = { (1, 5) : sqrt((5 - sqrt(5)) / 8), (2, 5) : sqrt((5 + sqrt(5)) / 8) } p = pi_coeff.p q = pi_coeff.q Q, P = p // q, p % q try: result = cst_table_some[q] except KeyError: if abs(P) > q // 2: P = q - P try: result = cst_table_more[(P, q)] except KeyError: if P != p: result = cls(C.Rational(P, q)*S.Pi) else: return None if Q % 2 == 1: return -result else: return result if arg.is_Add: x, m = _peeloff_pi(arg) if m: return sin(m)*cos(x)+cos(m)*sin(x) if arg.func is asin: return arg.args[0] if arg.func is atan: x = arg.args[0] return x / sqrt(1 + x**2) if arg.func is acos: x = arg.args[0] return sqrt(1 - x**2) if arg.func is acot: x = arg.args[0]; return 1 / (sqrt(1 + 1 / x**2) * x)
def _eval_rewrite_as_sqrt(self, arg): _EXPAND_INTS = False def migcdex(x): # recursive calcuation of gcd and linear combination # for a sequence of integers. # Given (x1, x2, x3) # Returns (y1, y1, y3, g) # such that g is the gcd and x1*y1+x2*y2+x3*y3 - g = 0 # Note, that this is only one such linear combination. if len(x) == 1: return (1, x[0]) if len(x) == 2: return igcdex(x[0], x[-1]) g = migcdex(x[1:]) u, v, h = igcdex(x[0], g[-1]) return tuple([u] + [v * i for i in g[0:-1]] + [h]) def ipartfrac(r, factors=None): if isinstance(r, int): return r assert isinstance(r, C.Rational) n = r.q if 2 > r.q * r.q: return r.q if None == factors: a = [n / x**y for x, y in factorint(r.q).iteritems()] else: a = [n / x for x in factors] if len(a) == 1: return [r] h = migcdex(a) ans = [r.p * C.Rational(i * j, r.q) for i, j in zip(h[:-1], a)] assert r == sum(ans) return ans pi_coeff = _pi_coeff(arg) if pi_coeff is None: return None assert not pi_coeff.is_integer, "should have been simplified already" if not pi_coeff.is_Rational: return None cst_table_some = { 3: S.Half, 5: (sqrt(5) + 1) / 4, 17: sqrt((15 + sqrt(17)) / 32 + sqrt(2) * (sqrt(17 - sqrt(17)) + sqrt( sqrt(2) * (-8 * sqrt(17 + sqrt(17)) - (1 - sqrt(17)) * sqrt(17 - sqrt(17))) + 6 * sqrt(17) + 34)) / 32) # 65537 and 257 are the only other known Fermat primes # Please add if you would like them } def fermatCoords(n): assert isinstance(n, int) assert n > 0 if n == 1 or 0 == n % 2: return False primes = dict([(p, 0) for p in cst_table_some]) assert 1 not in primes for p_i in primes: while 0 == n % p_i: n = n / p_i primes[p_i] += 1 if 1 != n: return False if max(primes.values()) > 1: return False return tuple([p for p in primes if primes[p] == 1]) if pi_coeff.q in cst_table_some: return C.chebyshevt(pi_coeff.p, cst_table_some[pi_coeff.q]).expand() if 0 == pi_coeff.q % 2: # recursively remove powers of 2 narg = (pi_coeff * 2) * S.Pi nval = cos(narg) if None == nval: return None nval = nval.rewrite(sqrt) if not _EXPAND_INTS: if (isinstance(nval, cos) or isinstance(-nval, cos)): return None x = (2 * pi_coeff + 1) / 2 sign_cos = (-1)**((-1 if x < 0 else 1) * int(abs(x))) return sign_cos * sqrt((1 + nval) / 2) FC = fermatCoords(pi_coeff.q) if FC: decomp = ipartfrac(pi_coeff, FC) X = [(x[1], x[0] * S.Pi) for x in zip(decomp, numbered_symbols('z'))] pcls = cos(sum([x[0] for x in X]))._eval_expand_trig().subs(X) return pcls.rewrite(sqrt) if _EXPAND_INTS: decomp = ipartfrac(pi_coeff) X = [(x[1], x[0] * S.Pi) for x in zip(decomp, numbered_symbols('z'))] pcls = cos(sum([x[0] for x in X]))._eval_expand_trig().subs(X) return pcls return None
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.One elif arg is S.Infinity: return if arg.could_extract_minus_sign(): return cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return C.cosh(i_coeff) pi_coeff = _pi_coeff(arg) if pi_coeff is not None: if not pi_coeff.is_Rational: if pi_coeff.is_integer: even = pi_coeff.is_even if even: return S.One elif even is False: return S.NegativeOne narg = pi_coeff*S.Pi if narg != arg: return cls(narg) return None cst_table_some = { 1 : S.One, 2 : S.Zero, 3 : S.Half, 4 : S.Half*sqrt(2), 6 : S.Half*sqrt(3), } cst_table_more = { (1, 5) : (sqrt(5) + 1)/4, (2, 5) : (sqrt(5) - 1)/4 } p = pi_coeff.p q = pi_coeff.q Q, P = 2*p // q, p % q try: result = cst_table_some[q] except KeyError: if abs(P) > q // 2: P = q - P try: result = cst_table_more[(P, q)] except KeyError: if P != p: result = cls(C.Rational(P, q)*S.Pi) else: return None if Q % 4 in (1, 2): return -result else: return result if arg.is_Add: x, m = _peeloff_pi(arg) if m: return cos(m)*cos(x)-sin(m)*sin(x) if arg.func is acos: return arg.args[0] if arg.func is atan: x = arg.args[0] return 1 / sqrt(1 + x**2) if arg.func is asin: x = arg.args[0] return sqrt(1 - x ** 2) if arg.func is acot: x = arg.args[0] return 1 / sqrt(1 + 1 / x**2)
def fdiff(self, argindex=1): if argindex == 1: return 2 * C.exp(-self.args[0]**2) / sqrt(S.Pi) else: raise ArgumentIndexError(self, argindex)