Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    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
Пример #4
0
    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
Пример #5
0
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")
Пример #6
0
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")