1"""A module providing information about the necessity of brackets""" 2 3from sympy.core.function import _coeff_isneg 4 5# Default precedence values for some basic types 6PRECEDENCE = { 7 "Lambda": 1, 8 "Xor": 10, 9 "Or": 20, 10 "And": 30, 11 "Relational": 35, 12 "Add": 40, 13 "Mul": 50, 14 "Pow": 60, 15 "Func": 70, 16 "Not": 100, 17 "Atom": 1000, 18 "BitwiseOr": 36, 19 "BitwiseXor": 37, 20 "BitwiseAnd": 38 21} 22 23# A dictionary assigning precedence values to certain classes. These values are 24# treated like they were inherited, so not every single class has to be named 25# here. 26# Do not use this with printers other than StrPrinter 27PRECEDENCE_VALUES = { 28 "Equivalent": PRECEDENCE["Xor"], 29 "Xor": PRECEDENCE["Xor"], 30 "Implies": PRECEDENCE["Xor"], 31 "Or": PRECEDENCE["Or"], 32 "And": PRECEDENCE["And"], 33 "Add": PRECEDENCE["Add"], 34 "Pow": PRECEDENCE["Pow"], 35 "Relational": PRECEDENCE["Relational"], 36 "Sub": PRECEDENCE["Add"], 37 "Not": PRECEDENCE["Not"], 38 "Function" : PRECEDENCE["Func"], 39 "NegativeInfinity": PRECEDENCE["Add"], 40 "MatAdd": PRECEDENCE["Add"], 41 "MatPow": PRECEDENCE["Pow"], 42 "MatrixSolve": PRECEDENCE["Mul"], 43 "TensAdd": PRECEDENCE["Add"], 44 # As soon as `TensMul` is a subclass of `Mul`, remove this: 45 "TensMul": PRECEDENCE["Mul"], 46 "HadamardProduct": PRECEDENCE["Mul"], 47 "HadamardPower": PRECEDENCE["Pow"], 48 "KroneckerProduct": PRECEDENCE["Mul"], 49 "Equality": PRECEDENCE["Mul"], 50 "Unequality": PRECEDENCE["Mul"], 51} 52 53# Sometimes it's not enough to assign a fixed precedence value to a 54# class. Then a function can be inserted in this dictionary that takes 55# an instance of this class as argument and returns the appropriate 56# precedence value. 57 58# Precedence functions 59 60 61def precedence_Mul(item): 62 if _coeff_isneg(item): 63 return PRECEDENCE["Add"] 64 return PRECEDENCE["Mul"] 65 66 67def precedence_Rational(item): 68 if item.p < 0: 69 return PRECEDENCE["Add"] 70 return PRECEDENCE["Mul"] 71 72 73def precedence_Integer(item): 74 if item.p < 0: 75 return PRECEDENCE["Add"] 76 return PRECEDENCE["Atom"] 77 78 79def precedence_Float(item): 80 if item < 0: 81 return PRECEDENCE["Add"] 82 return PRECEDENCE["Atom"] 83 84 85def precedence_PolyElement(item): 86 if item.is_generator: 87 return PRECEDENCE["Atom"] 88 elif item.is_ground: 89 return precedence(item.coeff(1)) 90 elif item.is_term: 91 return PRECEDENCE["Mul"] 92 else: 93 return PRECEDENCE["Add"] 94 95 96def precedence_FracElement(item): 97 if item.denom == 1: 98 return precedence_PolyElement(item.numer) 99 else: 100 return PRECEDENCE["Mul"] 101 102 103def precedence_UnevaluatedExpr(item): 104 return precedence(item.args[0]) 105 106 107PRECEDENCE_FUNCTIONS = { 108 "Integer": precedence_Integer, 109 "Mul": precedence_Mul, 110 "Rational": precedence_Rational, 111 "Float": precedence_Float, 112 "PolyElement": precedence_PolyElement, 113 "FracElement": precedence_FracElement, 114 "UnevaluatedExpr": precedence_UnevaluatedExpr, 115} 116 117 118def precedence(item): 119 """Returns the precedence of a given object. 120 121 This is the precedence for StrPrinter. 122 """ 123 if hasattr(item, "precedence"): 124 return item.precedence 125 try: 126 mro = item.__class__.__mro__ 127 except AttributeError: 128 return PRECEDENCE["Atom"] 129 for i in mro: 130 n = i.__name__ 131 if n in PRECEDENCE_FUNCTIONS: 132 return PRECEDENCE_FUNCTIONS[n](item) 133 elif n in PRECEDENCE_VALUES: 134 return PRECEDENCE_VALUES[n] 135 return PRECEDENCE["Atom"] 136 137 138PRECEDENCE_TRADITIONAL = PRECEDENCE.copy() 139PRECEDENCE_TRADITIONAL['Integral'] = PRECEDENCE["Mul"] 140PRECEDENCE_TRADITIONAL['Sum'] = PRECEDENCE["Mul"] 141PRECEDENCE_TRADITIONAL['Product'] = PRECEDENCE["Mul"] 142PRECEDENCE_TRADITIONAL['Limit'] = PRECEDENCE["Mul"] 143PRECEDENCE_TRADITIONAL['Derivative'] = PRECEDENCE["Mul"] 144PRECEDENCE_TRADITIONAL['TensorProduct'] = PRECEDENCE["Mul"] 145PRECEDENCE_TRADITIONAL['Transpose'] = PRECEDENCE["Pow"] 146PRECEDENCE_TRADITIONAL['Adjoint'] = PRECEDENCE["Pow"] 147PRECEDENCE_TRADITIONAL['Dot'] = PRECEDENCE["Mul"] - 1 148PRECEDENCE_TRADITIONAL['Cross'] = PRECEDENCE["Mul"] - 1 149PRECEDENCE_TRADITIONAL['Gradient'] = PRECEDENCE["Mul"] - 1 150PRECEDENCE_TRADITIONAL['Divergence'] = PRECEDENCE["Mul"] - 1 151PRECEDENCE_TRADITIONAL['Curl'] = PRECEDENCE["Mul"] - 1 152PRECEDENCE_TRADITIONAL['Laplacian'] = PRECEDENCE["Mul"] - 1 153PRECEDENCE_TRADITIONAL['Union'] = PRECEDENCE['Xor'] 154PRECEDENCE_TRADITIONAL['Intersection'] = PRECEDENCE['Xor'] 155PRECEDENCE_TRADITIONAL['Complement'] = PRECEDENCE['Xor'] 156PRECEDENCE_TRADITIONAL['SymmetricDifference'] = PRECEDENCE['Xor'] 157PRECEDENCE_TRADITIONAL['ProductSet'] = PRECEDENCE['Xor'] 158 159 160def precedence_traditional(item): 161 """Returns the precedence of a given object according to the 162 traditional rules of mathematics. 163 164 This is the precedence for the LaTeX and pretty printer. 165 """ 166 # Integral, Sum, Product, Limit have the precedence of Mul in LaTeX, 167 # the precedence of Atom for other printers: 168 from sympy.core.expr import UnevaluatedExpr 169 170 if isinstance(item, UnevaluatedExpr): 171 return precedence_traditional(item.args[0]) 172 173 n = item.__class__.__name__ 174 if n in PRECEDENCE_TRADITIONAL: 175 return PRECEDENCE_TRADITIONAL[n] 176 177 return precedence(item) 178