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

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

2 

3 

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} 

21 

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} 

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 item.could_extract_minus_sign(): 

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]) - 0.5 

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)