def _eval_factor(self, **hints): summand = self.function.factor(**hints) keep_inside = [] pull_outside = [] if summand.is_Mul and summand.is_commutative: for i in summand.args: if not i.atoms(C.Symbol).intersection(self.variables): pull_outside.append(i) else: keep_inside.append(i) return C.Mul(*pull_outside) * self.func(C.Mul(*keep_inside), *self.limits) return self
def _eval_factor(self, **hints): if 1 == len(self.limits): summand = self.function.factor(**hints) if summand.is_Mul: out = sift(summand.args, lambda w: w.is_commutative \ and not w.has(*self.variables)) return C.Mul(*out[True])*self.func(C.Mul(*out[False]), \ *self.limits) else: summand = self.func(self.function, self.limits[0:-1]).factor() if not summand.has(self.variables[-1]): return self.func(1, [self.limits[-1]]).doit() * summand elif isinstance(summand, C.Mul): return self.func(summand, self.limits[-1]).factor() return self
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 _eval_as_leading_term(self, x): arg = self.args[0] if arg.is_Add: return C.Mul(*[exp(f).as_leading_term(x) for f in arg.args]) arg = self.args[0].as_leading_term(x) if C.Order(1,x).contains(arg): return S.One return exp(arg)
def eval(cls, arg): if arg is S.NaN: return S.NaN if arg is S.Zero: return S.Zero if arg.is_positive: return S.One if arg.is_negative: return S.NegativeOne if arg.is_Mul: coeff, terms = arg.as_coeff_terms() if coeff is not S.One: return cls(coeff) * cls(C.Mul(*terms))
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(cls, arg): if arg is S.NaN: return S.NaN if arg.is_zero: return arg if arg.is_positive: return arg if arg.is_negative: return -arg coeff, terms = arg.as_coeff_terms() if coeff is not S.One: return cls(coeff) * cls(C.Mul(*terms)) if arg.is_real is False: return sqrt((arg * arg.conjugate()).expand()) if arg.is_Pow: base, exponent = arg.as_base_exp() if exponent.is_even and base.is_real: return arg return
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(cls, arg): if arg is S.NaN: return S.NaN if arg is S.Zero: return S.Zero if arg.is_positive: return S.One if arg.is_negative: return S.NegativeOne if arg.is_Function: if arg.func is sign: return arg if arg.is_Mul: c, args = arg.as_coeff_terms() unk = [] is_neg = c.is_negative for ai in args: if ai.is_negative == None: unk.append(ai) elif ai.is_negative: is_neg = not is_neg if c is S.One and len(unk) == len(args): return None return iff(is_neg, S.NegativeOne, S.One) * cls(C.Mul(*unk))
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(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))]))
def as_base_exp(self): return S.Exp1, C.Mul(*self.args)