Source code for modelparameters.sympy.printing.precedence

"""A module providing information about the necessity of brackets"""

from __future__ import print_function, division

from ..core.function import _coeff_isneg

# Default precedence values for some basic types
PRECEDENCE = {
    "Lambda": 1,
    "Xor": 10,
    "Or": 20,
    "And": 30,
    "Relational": 35,
    "Add": 40,
    "Mul": 50,
    "Pow": 60,
    "Func": 70,
    "Not": 100,
    "Atom": 1000,
    "BitwiseOr": 36,
    "BitwiseAnd": 38
}

# A dictionary assigning precedence values to certain classes. These values are
# treated like they were inherited, so not every single class has to be named
# here.
PRECEDENCE_VALUES = {
    "Equivalent": PRECEDENCE["Xor"],
    "Xor": PRECEDENCE["Xor"],
    "Implies": PRECEDENCE["Xor"],
    "Or": PRECEDENCE["Or"],
    "And": PRECEDENCE["And"],
    "Add": PRECEDENCE["Add"],
    "Pow": PRECEDENCE["Pow"],
    "Relational": PRECEDENCE["Relational"],
    "Sub": PRECEDENCE["Add"],
    "Not": PRECEDENCE["Not"],
    "Function" : PRECEDENCE["Func"],
    "NegativeInfinity": PRECEDENCE["Add"],
    "MatAdd": PRECEDENCE["Add"],
    "MatMul": PRECEDENCE["Mul"],
    "MatPow": PRECEDENCE["Pow"],
    "HadamardProduct": PRECEDENCE["Mul"],
    "Equality": PRECEDENCE["Mul"],
    "Unequality": PRECEDENCE["Mul"],
}

# Sometimes it's not enough to assign a fixed precedence value to a
# class. Then a function can be inserted in this dictionary that takes
# an instance of this class as argument and returns the appropriate
# precedence value.

# Precedence functions


[docs]def precedence_Mul(item): if _coeff_isneg(item): return PRECEDENCE["Add"] return PRECEDENCE["Mul"]
[docs]def precedence_Rational(item): if item.p < 0: return PRECEDENCE["Add"] return PRECEDENCE["Mul"]
[docs]def precedence_Integer(item): if item.p < 0: return PRECEDENCE["Add"] return PRECEDENCE["Atom"]
[docs]def precedence_Float(item): if item < 0: return PRECEDENCE["Add"] return PRECEDENCE["Atom"]
[docs]def precedence_PolyElement(item): if item.is_generator: return PRECEDENCE["Atom"] elif item.is_ground: return precedence(item.coeff(1)) elif item.is_term: return PRECEDENCE["Mul"] else: return PRECEDENCE["Add"]
[docs]def precedence_FracElement(item): if item.denom == 1: return precedence_PolyElement(item.numer) else: return PRECEDENCE["Mul"]
[docs]def precedence_UnevaluatedExpr(item): return precedence(item.args[0])
PRECEDENCE_FUNCTIONS = { "Integer": precedence_Integer, "Mul": precedence_Mul, "Rational": precedence_Rational, "Float": precedence_Float, "PolyElement": precedence_PolyElement, "FracElement": precedence_FracElement, "UnevaluatedExpr": precedence_UnevaluatedExpr, }
[docs]def precedence(item): """ Returns the precedence of a given object. """ if hasattr(item, "precedence"): return item.precedence try: mro = item.__class__.__mro__ except AttributeError: return PRECEDENCE["Atom"] for i in mro: n = i.__name__ if n in PRECEDENCE_FUNCTIONS: return PRECEDENCE_FUNCTIONS[n](item) elif n in PRECEDENCE_VALUES: return PRECEDENCE_VALUES[n] return PRECEDENCE["Atom"]
[docs]def precedence_traditional(item): """ Returns the precedence of a given object according to the traditional rules of mathematics. This is the precedence for the LaTeX and pretty printer. """ # Integral, Sum, Product, Limit have the precedence of Mul in LaTeX, # the precedence of Atom for other printers: from .. import Integral, Sum, Product, Limit, Derivative from ..core.expr import UnevaluatedExpr if isinstance(item, (Integral, Sum, Product, Limit, Derivative)): return PRECEDENCE["Mul"] elif isinstance(item, UnevaluatedExpr): return precedence_traditional(item.args[0]) else: return precedence(item)