"""A module providing information about the necessity of brackets""" # 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, "BitwiseXor": 37, "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. # Do not use this with printers other than StrPrinter 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"], "MatPow": PRECEDENCE["Pow"], "MatrixSolve": PRECEDENCE["Mul"], "Mod": PRECEDENCE["Mul"], "TensAdd": PRECEDENCE["Add"], # As soon as `TensMul` is a subclass of `Mul`, remove this: "TensMul": PRECEDENCE["Mul"], "HadamardProduct": PRECEDENCE["Mul"], "HadamardPower": PRECEDENCE["Pow"], "KroneckerProduct": 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 def precedence_Mul(item): if item.could_extract_minus_sign(): return PRECEDENCE["Add"] return PRECEDENCE["Mul"] def precedence_Rational(item): if item.p < 0: return PRECEDENCE["Add"] return PRECEDENCE["Mul"] def precedence_Integer(item): if item.p < 0: return PRECEDENCE["Add"] return PRECEDENCE["Atom"] def precedence_Float(item): if item < 0: return PRECEDENCE["Add"] return PRECEDENCE["Atom"] 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"] def precedence_FracElement(item): if item.denom == 1: return precedence_PolyElement(item.numer) else: return PRECEDENCE["Mul"] def precedence_UnevaluatedExpr(item): return precedence(item.args[0]) - 0.5 PRECEDENCE_FUNCTIONS = { "Integer": precedence_Integer, "Mul": precedence_Mul, "Rational": precedence_Rational, "Float": precedence_Float, "PolyElement": precedence_PolyElement, "FracElement": precedence_FracElement, "UnevaluatedExpr": precedence_UnevaluatedExpr, } def precedence(item): """Returns the precedence of a given object. This is the precedence for StrPrinter. """ 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"] PRECEDENCE_TRADITIONAL = PRECEDENCE.copy() PRECEDENCE_TRADITIONAL['Integral'] = PRECEDENCE["Mul"] PRECEDENCE_TRADITIONAL['Sum'] = PRECEDENCE["Mul"] PRECEDENCE_TRADITIONAL['Product'] = PRECEDENCE["Mul"] PRECEDENCE_TRADITIONAL['Limit'] = PRECEDENCE["Mul"] PRECEDENCE_TRADITIONAL['Derivative'] = PRECEDENCE["Mul"] PRECEDENCE_TRADITIONAL['TensorProduct'] = PRECEDENCE["Mul"] PRECEDENCE_TRADITIONAL['Transpose'] = PRECEDENCE["Pow"] PRECEDENCE_TRADITIONAL['Adjoint'] = PRECEDENCE["Pow"] PRECEDENCE_TRADITIONAL['Dot'] = PRECEDENCE["Mul"] - 1 PRECEDENCE_TRADITIONAL['Cross'] = PRECEDENCE["Mul"] - 1 PRECEDENCE_TRADITIONAL['Gradient'] = PRECEDENCE["Mul"] - 1 PRECEDENCE_TRADITIONAL['Divergence'] = PRECEDENCE["Mul"] - 1 PRECEDENCE_TRADITIONAL['Curl'] = PRECEDENCE["Mul"] - 1 PRECEDENCE_TRADITIONAL['Laplacian'] = PRECEDENCE["Mul"] - 1 PRECEDENCE_TRADITIONAL['Union'] = PRECEDENCE['Xor'] PRECEDENCE_TRADITIONAL['Intersection'] = PRECEDENCE['Xor'] PRECEDENCE_TRADITIONAL['Complement'] = PRECEDENCE['Xor'] PRECEDENCE_TRADITIONAL['SymmetricDifference'] = PRECEDENCE['Xor'] PRECEDENCE_TRADITIONAL['ProductSet'] = PRECEDENCE['Xor'] 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 sympy.core.expr import UnevaluatedExpr if isinstance(item, UnevaluatedExpr): return precedence_traditional(item.args[0]) n = item.__class__.__name__ if n in PRECEDENCE_TRADITIONAL: return PRECEDENCE_TRADITIONAL[n] return precedence(item)