def eval(cls, arg): if arg is S.NaN: return S.NaN elif arg.is_real: return arg else: if not arg.is_Add: arg = [arg] included, reverted, excluded = [], [], [] if isinstance(arg, Basic): arg = arg.args for term in arg: coeff = term.as_coefficient(S.ImaginaryUnit) if coeff is not None: if not coeff.is_real: reverted.append(coeff) elif not term.has(S.ImaginaryUnit) and term.is_real: excluded.append(term) else: included.append(term) if len(arg[:]) != len(included): a, b, c = map(lambda xs: C.Add(*xs), [included, reverted, excluded]) return cls(a) - im(b) + c
def _eval_expand_basic(self, **hints): summand = self.function.expand(**hints) if summand.is_Add and summand.is_commutative: return C.Add(*[self.func(i, *self.limits) for i in summand.args]) elif summand != self.function: return self.func(summand, *self.limits) return self
def eval(cls, arg): if arg is S.NaN: return S.NaN elif arg.is_real: return arg elif arg.is_Function and arg.func == conjugate: return re(arg.args[0]) else: included, reverted, excluded = [], [], [] arg = make_list(arg, C.Add) for term in arg: coeff = term.as_coefficient(S.ImaginaryUnit) if coeff is not None: if not coeff.is_real: reverted.append(coeff) elif not term.has(S.ImaginaryUnit) and term.is_real: excluded.append(term) else: included.append(term) if len(arg) != len(included): a, b, c = map(lambda xs: C.Add(*xs), [included, reverted, excluded]) return cls(a) - im(b) + c
def _eval_subs(self, old, new): if self==old: return new arg = self.args[0] o = old if old.is_Pow: # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2) old = exp(old.exp * log(old.base)) if old.func is exp: # exp(a*expr) .subs( exp(b*expr), y ) -> y ** (a/b) a, expr_terms = self.args[0].as_coeff_terms() b, expr_terms_= old .args[0].as_coeff_terms() if expr_terms == expr_terms_: return new ** (a/b) if arg.is_Add: # exp(2*x+a).subs(exp(3*x),y) -> y**(2/3) * exp(a) # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2)) oarg = old.args[0] new_l = [] old_al = [] coeff2,terms2 = oarg.as_coeff_terms() for a in arg.args: a = a._eval_subs(old, new) coeff1,terms1 = a.as_coeff_terms() if terms1==terms2: new_l.append(new**(coeff1/coeff2)) else: old_al.append(a._eval_subs(old, new)) if new_l: new_l.append(self.func(C.Add(*old_al))) r = C.Mul(*new_l) return r old = o return Function._eval_subs(self, old, new)
def _taylor(self, x, x0, n): l = [] g = None for i in xrange(n): g = self.taylor_term(i, self.args[0], g) g = g.nseries(x, x0, n) l.append(g) return C.Add(*l) + C.Order(x**n, x)
def _eval_expand_trig(self, *args): arg = self.args[0].expand() x = None if arg.is_Add: x = arg.args[0] y = C.Add(*arg.args[1:]) return (cos(x) * cos(y) - sin(y) * sin(x)).expand(trig=True) else: coeff, terms = arg.as_coeff_terms() if not (coeff is S.One) and coeff.is_Integer and terms: x = C.Mul(*terms) return C.chebyshevt(coeff, cos(x)) return cos(arg)
def _eval_expand_trig(self, *args): arg = self.args[0].expand() x = None if arg.is_Add: x = arg.args[0] y = C.Add(*arg.args[1:]) else: coeff, terms = arg.as_coeff_terms() if not (coeff is S.One) and coeff.is_Integer and terms: x = C.Mul(*terms) y = (coeff - 1) * x if x is not None: return (sin(x) * cos(y) + sin(y) * cos(x)).expand(trig=True) return sin(arg)
def _eval_expand_trig(self, deep=True, **hints): if deep: arg = self.args[0].expand() else: arg = self.args[0] x = None if arg.is_Add: # TODO, implement more if deep stuff here x = arg.args[0] y = C.Add(*arg.args[1:]) return (cos(x) * cos(y) - sin(y) * sin(x)).expand(trig=True) else: coeff, terms = arg.as_coeff_terms() if not (coeff is S.One) and coeff.is_Integer and terms: x = C.Mul(*terms) return C.chebyshevt(coeff, cos(x)) return cos(arg)
def _eval_expand_trig(self, deep=True, **hints): if deep: arg = self.args[0].expand(deep, **hints) else: arg = self.args[0] x = None if arg.is_Add: # TODO, implement more if deep stuff here x = arg.args[0] y = C.Add(*arg.args[1:]) else: coeff, terms = arg.as_coeff_terms() if not (coeff is S.One) and coeff.is_Integer and terms: x = C.Mul(*terms) y = (coeff - 1) * x if x is not None: return (sin(x) * cos(y) + sin(y) * cos(x)).expand(trig=True) return sin(arg)
def eval_sum_direct(expr, limits): (i, a, b) = limits dif = b - a return C.Add(*[expr.subs(i, a + j) for j in xrange(dif + 1)])
def __new__(cls, expr, *symbols, **assumptions): expr = sympify(expr).expand() if expr is S.NaN: return S.NaN if symbols: symbols = map(sympify, symbols) else: symbols = list(expr.atoms(C.Symbol)) symbols.sort(Basic.compare) if expr.is_Order: new_symbols = list(expr.symbols) for s in symbols: if s not in new_symbols: new_symbols.append(s) if len(new_symbols) == len(expr.symbols): return expr symbols = new_symbols elif symbols: symbol_map = {} new_symbols = [] for s in symbols: if isinstance(s, C.Symbol): new_symbols.append(s) continue z = C.Symbol('z', dummy=True) x1, s1 = s.solve4linearsymbol(z) expr = expr.subs(x1, s1) symbol_map[z] = s new_symbols.append(z) if symbol_map: r = Order(expr, *new_symbols, **assumptions) expr = r.expr.subs(symbol_map) symbols = [] for s in r.symbols: if symbol_map.has_key(s): symbols.append(symbol_map[s]) else: symbols.append(s) else: if expr.is_Add: lst = expr.extract_leading_order(*symbols) expr = C.Add(*[f.expr for (e, f) in lst]) else: expr = expr.as_leading_term(*symbols) coeff, terms = expr.as_coeff_terms() if coeff is S.Zero: return coeff expr = C.Mul(*[t for t in terms if t.has(*symbols)]) elif expr is not S.Zero: expr = S.One if expr is S.Zero: return expr # create Order instance: obj = Basic.__new__(cls, expr, *symbols, **assumptions) return obj
def _eval_nseries(self, x, x0, n): from sympy import powsimp arg = self.args[0] k, l = Wild("k"), Wild("l") r = arg.match(k*x**l) if r is not None: k, l = r[k], r[l] if l != 0 and not l.has(x) and not k.has(x): r = log(k) + l*log(x) return r order = C.Order(x**n, x) arg = self.args[0] x = order.symbols[0] ln = C.log use_lt = not C.Order(1,x).contains(arg) if not use_lt: arg0 = arg.limit(x, 0) use_lt = (arg0 is S.Zero) if use_lt: # singularity, #example: self = log(sin(x)) # arg = (arg / lt) * lt lt = arg.as_leading_term(x) # arg = sin(x); lt = x a = powsimp((arg/lt).expand(), deep=True, combine='exp') # a = sin(x)/x # the idea is to recursively call ln(a).series(), but one needs to # make sure that ln(sin(x)/x) doesn't get "simplified" to # -log(x)+ln(sin(x)) and an infinite recursion occurs, see also the # issue 252. obj = ln(lt) + ln(a)._eval_nseries(x, x0, n) else: # arg -> arg0 + (arg - arg0) -> arg0 * (1 + (arg/arg0 - 1)) z = (arg/arg0 - 1) x = order.symbols[0] ln = C.log o = C.Order(z, x) if o is S.Zero: return ln(1+z)+ ln(arg0) if o.expr.is_number: e = ln(order.expr*x)/ln(x) else: e = ln(order.expr)/ln(o.expr) n = e.limit(x,0) + 1 if n.is_unbounded: # requested accuracy gives infinite series, # order is probably nonpolynomial e.g. O(exp(-1/x), x). return ln(1+z)+ ln(arg0) try: n = int(n) except TypeError: #well, the n is something more complicated (like 1+log(2)) n = int(n.evalf()) + 1 assert n>=0,`n` l = [] g = None for i in xrange(n+2): g = ln.taylor_term(i, z, g) g = g.nseries(x, x0, n) l.append(g) obj = C.Add(*l) + ln(arg0) obj2 = expand_log(powsimp(obj, deep=True, combine='exp')) if obj2 != obj: r = obj2.nseries(x, x0, n) else: r = obj if r == self: return self return r + order
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.One: return S.Exp1 elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Zero elif arg.func is log: return arg.args[0] elif arg.is_Mul: coeff = arg.as_coefficient(S.Pi*S.ImaginaryUnit) if coeff is not None: if (2*coeff).is_integer: if coeff.is_even: return S.One elif coeff.is_odd: return S.NegativeOne elif (coeff + S.Half).is_even: return -S.ImaginaryUnit elif (coeff + S.Half).is_odd: return S.ImaginaryUnit I = S.ImaginaryUnit oo = S.Infinity a = Wild("a", exclude=[I, oo]) r = arg.match(I*a*oo) if r and r[a] != 0: return S.NaN if arg.is_Add: args = arg.args[:] else: args = [arg] included, excluded = [], [] for arg in args: coeff, terms = arg.as_coeff_terms() if coeff is S.Infinity: excluded.append(coeff**C.Mul(*terms)) else: coeffs, log_term = [coeff], None for term in terms: if term.func is log: if log_term is None: log_term = term.args[0] else: log_term = None break elif term.is_comparable: coeffs.append(term) else: log_term = None break if log_term is not None: excluded.append(log_term**C.Mul(*coeffs)) else: included.append(arg) if excluded: return C.Mul(*(excluded+[cls(C.Add(*included))]))