From e76ea8ef220d67d32d8feb155ba65bfa45403039 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sun, 5 Jul 2009 15:35:12 +0200 Subject: [PATCH] fix constant folding: calculate float values but do not aggregate them into ConstNodes --- Cython/Compiler/Optimize.py | 51 ++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 8c20674e..f40a301b 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -894,34 +894,43 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): self._calculate_const(node) if node.constant_result is ExprNodes.not_a_constant: return node + if isinstance(node.constant_result, float): + # We calculate float constants to make them available to + # the compiler, but we do not aggregate them into a + # constant node to prevent any loss of precision. + return node + if not isinstance(node.operand1, ExprNodes.ConstNode) or \ + not isinstance(node.operand1, ExprNodes.ConstNode): + # We calculate other constants to make them available to + # the compiler, but we only aggregate constant nodes + # recursively, so non-const nodes are straight out. + return node + + # now inject a new constant node with the calculated value try: - if node.operand1.type is None or node.operand2.type is None: + type1, type2 = node.operand1.type, node.operand2.type + if type1 is None or type2 is None: return node except AttributeError: return node - type1, type2 = node.operand1.type, node.operand2.type - if isinstance(node.operand1, ExprNodes.ConstNode) and \ - isinstance(node.operand1, ExprNodes.ConstNode): - if type1 is type2: + if type1 is type2: + new_node = node.operand1 + else: + widest_type = PyrexTypes.widest_numeric_type(type1, type2) + if type(node.operand1) is type(node.operand2): + new_node = node.operand1 + new_node.type = widest_type + elif type1 is widest_type: new_node = node.operand1 + elif type2 is widest_type: + new_node = node.operand2 else: - widest_type = PyrexTypes.widest_numeric_type(type1, type2) - if type(node.operand1) is type(node.operand2): - new_node = node.operand1 - new_node.type = widest_type - elif type1 is widest_type: - new_node = node.operand1 - elif type2 is widest_type: - new_node = node.operand2 - else: - target_class = self._widest_node_class( - node.operand1, node.operand2) - if target_class is None: - return node - new_node = target_class(type = widest_type) - else: - return node + target_class = self._widest_node_class( + node.operand1, node.operand2) + if target_class is None: + return node + new_node = target_class(pos=node.pos, type = widest_type) new_node.constant_result = node.constant_result new_node.value = str(node.constant_result) -- 2.26.2