Coverage for /usr/lib/python3/dist-packages/sympy/printing/precedence.py: 63%
75 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1"""A module providing information about the necessity of brackets"""
4# Default precedence values for some basic types
5PRECEDENCE = {
6 "Lambda": 1,
7 "Xor": 10,
8 "Or": 20,
9 "And": 30,
10 "Relational": 35,
11 "Add": 40,
12 "Mul": 50,
13 "Pow": 60,
14 "Func": 70,
15 "Not": 100,
16 "Atom": 1000,
17 "BitwiseOr": 36,
18 "BitwiseXor": 37,
19 "BitwiseAnd": 38
20}
22# A dictionary assigning precedence values to certain classes. These values are
23# treated like they were inherited, so not every single class has to be named
24# here.
25# Do not use this with printers other than StrPrinter
26PRECEDENCE_VALUES = {
27 "Equivalent": PRECEDENCE["Xor"],
28 "Xor": PRECEDENCE["Xor"],
29 "Implies": PRECEDENCE["Xor"],
30 "Or": PRECEDENCE["Or"],
31 "And": PRECEDENCE["And"],
32 "Add": PRECEDENCE["Add"],
33 "Pow": PRECEDENCE["Pow"],
34 "Relational": PRECEDENCE["Relational"],
35 "Sub": PRECEDENCE["Add"],
36 "Not": PRECEDENCE["Not"],
37 "Function" : PRECEDENCE["Func"],
38 "NegativeInfinity": PRECEDENCE["Add"],
39 "MatAdd": PRECEDENCE["Add"],
40 "MatPow": PRECEDENCE["Pow"],
41 "MatrixSolve": PRECEDENCE["Mul"],
42 "Mod": 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}
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.
58# Precedence functions
61def precedence_Mul(item):
62 if item.could_extract_minus_sign():
63 return PRECEDENCE["Add"]
64 return PRECEDENCE["Mul"]
67def precedence_Rational(item):
68 if item.p < 0:
69 return PRECEDENCE["Add"]
70 return PRECEDENCE["Mul"]
73def precedence_Integer(item):
74 if item.p < 0:
75 return PRECEDENCE["Add"]
76 return PRECEDENCE["Atom"]
79def precedence_Float(item):
80 if item < 0:
81 return PRECEDENCE["Add"]
82 return PRECEDENCE["Atom"]
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"]
96def precedence_FracElement(item):
97 if item.denom == 1:
98 return precedence_PolyElement(item.numer)
99 else:
100 return PRECEDENCE["Mul"]
103def precedence_UnevaluatedExpr(item):
104 return precedence(item.args[0]) - 0.5
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}
118def precedence(item):
119 """Returns the precedence of a given object.
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"]
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']
160def precedence_traditional(item):
161 """Returns the precedence of a given object according to the
162 traditional rules of mathematics.
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
170 if isinstance(item, UnevaluatedExpr):
171 return precedence_traditional(item.args[0])
173 n = item.__class__.__name__
174 if n in PRECEDENCE_TRADITIONAL:
175 return PRECEDENCE_TRADITIONAL[n]
177 return precedence(item)