def __add__(self, other): if not isinstance(other, Rational): newother = Rational(other) else: newother = other try: t = traits.common_traits(self.Denominator, newother.Denominator) newden = t.lcm(self.Denominator, newother.Denominator) newnum = self.Numerator * newden/self.Denominator + \ newother.Numerator * newden/newother.Denominator gcd = t.gcd(newden, newnum) return primitives.quotient(newnum/gcd, newden/gcd) except traits.NoTraitsError: return primitives.Expression.__add__(self, other) except traits.NoCommonTraitsError: return primitives.Expression.__add__(self, other)
def __divmod__(self, other): if not isinstance(other, Polynomial): dm_list = [(exp, divmod(coeff, other)) for exp, coeff in self.Data] return ( Polynomial(self.Base, [(exp, quot) for (exp, (quot, rem)) in dm_list]), Polynomial(self.Base, [(exp, rem) for (exp, (quot, rem)) in dm_list]), ) if other.Base != self.Base: assert self.VarLess == other.VarLess if self.VarLess(self.Base, other.Base): dm_list = [(exp, divmod(coeff, other)) for exp, coeff in self.Data] return ( Polynomial(self.Base, [(exp, quot) for (exp, (quot, rem)) in dm_list]), Polynomial(self.Base, [(exp, rem) for (exp, (quot, rem)) in dm_list]), ) else: other_unit = Polynomial(other.Base, ((0, other.unit),), self.VarLess) quot, rem = divmod(other_unit, other) return quot * self, rem * self if other.degree == -1: raise DivisionByZeroError quot = Polynomial(self.Base, ()) rem = self other_lead_coeff = other.Data[-1][1] other_lead_exp = other.Data[-1][0] coeffs_are_field = isinstance(traits(self.Unit), FieldTraits) from pymbolic.primitives import quotient while rem.degree >= other.degree: if coeffs_are_field: coeff_factor = quotient(rem.Data[-1][1], other_lead_coeff) else: coeff_factor, lead_rem = divmod(rem.Data[-1][1], other_lead_coeff) if lead_rem: return quot, rem deg_diff = rem.Data[-1][0] - other_lead_exp this_fac = Polynomial(self.Base, ((deg_diff, coeff_factor),)) quot += this_fac rem -= this_fac * other return quot, rem
def __divmod__(self, other): if not isinstance(other, Polynomial): dm_list = [(exp, divmod(coeff, other)) for exp, coeff in self.Data] return Polynomial(self.Base, [(exp, quot) for (exp, (quot, rem)) in dm_list]),\ Polynomial(self.Base, [(exp, rem) for (exp, (quot, rem)) in dm_list]) if other.Base != self.Base: assert self.VarLess == other.VarLess if self.VarLess(self.Base, other.Base): dm_list = [(exp, divmod(coeff, other)) for exp, coeff in self.Data] return Polynomial(self.Base, [(exp, quot) for (exp, (quot, rem)) in dm_list]),\ Polynomial(self.Base, [(exp, rem) for (exp, (quot, rem)) in dm_list]) else: other_unit = Polynomial(other.Base, ((0, other.unit), ), self.VarLess) quot, rem = divmod(other_unit, other) return quot * self, rem * self if other.degree == -1: raise DivisionByZeroError quot = Polynomial(self.Base, ()) rem = self other_lead_coeff = other.Data[-1][1] other_lead_exp = other.Data[-1][0] coeffs_are_field = isinstance(traits(self.Unit), FieldTraits) from pymbolic.primitives import quotient while rem.degree >= other.degree: if coeffs_are_field: coeff_factor = quotient(rem.Data[-1][1], other_lead_coeff) else: coeff_factor, lead_rem = divmod(rem.Data[-1][1], other_lead_coeff) if lead_rem: return quot, rem deg_diff = rem.Data[-1][0] - other_lead_exp this_fac = Polynomial(self.Base, ((deg_diff, coeff_factor), )) quot += this_fac rem -= this_fac * other return quot, rem
def map_math_functions_by_name(i, func, pars): try: f = pymbolic.evaluate(func, {"math": math, "cmath": cmath}) except pymbolic.mapper.evaluator.UnknownVariableError: raise RuntimeError("No derivative of non-constant function "+str(func)) def make_f(name): return primitives.Lookup(primitives.Variable("math"), name) if f is math.sin and len(pars) == 1: return make_f("cos")(*pars) elif f is math.cos and len(pars) == 1: return -make_f("sin")(*pars) elif f is math.tan and len(pars) == 1: return make_f("tan")(*pars)**2+1 elif f is math.log and len(pars) == 1: return primitives.quotient(1, pars[0]) elif f is math.exp and len(pars) == 1: return make_f("exp")(*pars) else: raise RuntimeError("unrecognized function, cannot differentiate")
def map_math_functions_by_name(i, func, pars, allowed_nonsmoothness="none"): def make_f(name): return primitives.Lookup(primitives.Variable("math"), name) if func == make_f("sin") and len(pars) == 1: return make_f("cos")(*pars) elif func == make_f("cos") and len(pars) == 1: return -make_f("sin")(*pars) elif func == make_f("tan") and len(pars) == 1: return make_f("tan")(*pars)**2 + 1 elif func == make_f("log") and len(pars) == 1: return primitives.quotient(1, pars[0]) elif func == make_f("exp") and len(pars) == 1: return make_f("exp")(*pars) elif func == make_f("sinh") and len(pars) == 1: return make_f("cosh")(*pars) elif func == make_f("cosh") and len(pars) == 1: return make_f("sinh")(*pars) elif func == make_f("tanh") and len(pars) == 1: return 1 - make_f("tanh")(*pars)**2 elif func == make_f("expm1") and len(pars) == 1: return make_f("exp")(*pars) elif func == make_f("fabs") and len(pars) == 1: if allowed_nonsmoothness in ["continuous", "discontinuous"]: from pymbolic.functions import sign return sign(*pars) else: raise ValueError("fabs is not smooth" ", pass allowed_nonsmoothness='continuous' " "to return sign") elif func == make_f("copysign") and len(pars) == 2: if allowed_nonsmoothness == "discontinuous": return 0 else: raise ValueError("sign is discontinuous" ", pass allowed_nonsmoothness='discontinuous' " "to return 0") else: raise RuntimeError("unrecognized function, cannot differentiate")