[pypy-svn] pypy cmath: (lac, arigo)
arigo
commits-noreply at bitbucket.org
Tue Jan 18 15:45:26 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: cmath
Changeset: r40863:263f1644fa25
Date: 2011-01-18 15:43 +0100
http://bitbucket.org/pypy/pypy/changeset/263f1644fa25/
Log: (lac, arigo)
Fix the detection of 0.0 vs -0.0, and more generally of nested
tuples.
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -834,21 +834,7 @@
def visit_Const(self, const):
self.update_position(const.lineno)
space = self.space
- value = const.value
- # Constant tuples are tricky because we have to avoid letting equal
- # values of the tuple that are not the same types being held together in
- # the constant dict. So we make the key include the type of each item
- # in the sequence.
- if space.is_true(space.isinstance(value, space.w_tuple)):
- length = space.int_w(space.len(value))
- key_w = [None]*(length + 2)
- key_w[0] = value
- for i in range(1, length + 1):
- key_w[i] = space.type(space.getitem(value, space.wrap(i - 1)))
- key_w[-1] = space.w_tuple
- self.load_const(value, space.newtuple(key_w))
- else:
- self.load_const(value)
+ self.load_const(const.value)
def visit_UnaryOp(self, op):
self.update_position(op.lineno)
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -204,49 +204,61 @@
container[name] = index
return index
- def add_const(self, obj, w_key=None):
+ def add_const(self, obj):
"""Add a W_Root to the constant array and return its location."""
space = self.space
- # To avoid confusing equal but separate types, we hash store the type of
- # the constant in the dictionary.
- if w_key is None:
- # We have to keep the difference between -0.0 and 0.0 floats.
- w_type = space.type(obj)
- if space.is_w(w_type, space.w_float):
- val = space.float_w(obj)
- if val == 0.0 and rarithmetic.copysign(1., val) < 0:
- w_key = space.newtuple([obj, space.w_float, space.w_None])
- else:
- w_key = space.newtuple([obj, space.w_float])
- elif space.is_w(w_type, space.w_complex):
- w_real = space.getattr(obj, space.wrap("real"))
- w_imag = space.getattr(obj, space.wrap("imag"))
- real = space.float_w(w_real)
- imag = space.float_w(w_imag)
- real_negzero = (real == 0.0 and
- rarithmetic.copysign(1., real) < 0)
- imag_negzero = (imag == 0.0 and
- rarithmetic.copysign(1., imag) < 0)
- if real_negzero and imag_negzero:
- tup = [obj, space.w_complex, space.w_None, space.w_None,
- space.w_None]
- elif imag_negzero:
- tup = [obj, space.w_complex, space.w_None, space.w_None]
- elif real_negzero:
- tup = [obj, space.w_complex, space.w_None]
- else:
- tup = [obj, space.w_complex]
- w_key = space.newtuple(tup)
- else:
- w_key = space.newtuple([obj, w_type])
+ # To avoid confusing equal but separate types, we hash store the type
+ # of the constant in the dictionary. Moreover, we have to keep the
+ # difference between -0.0 and 0.0 floats, and this recursively in
+ # tuples.
+ w_key = self._make_key(obj)
+
w_len = space.finditem(self.w_consts, w_key)
if w_len is None:
w_len = space.len(self.w_consts)
space.setitem(self.w_consts, w_key, w_len)
return space.int_w(w_len)
- def load_const(self, obj, w_key=None):
- index = self.add_const(obj, w_key)
+ def _make_key(self, obj):
+ # see the tests 'test_zeros_not_mixed*' in ../test/test_compiler.py
+ space = self.space
+ w_type = space.type(obj)
+ if space.is_w(w_type, space.w_float):
+ val = space.float_w(obj)
+ if val == 0.0 and rarithmetic.copysign(1., val) < 0:
+ w_key = space.newtuple([obj, space.w_float, space.w_None])
+ else:
+ w_key = space.newtuple([obj, space.w_float])
+ elif space.is_w(w_type, space.w_complex):
+ w_real = space.getattr(obj, space.wrap("real"))
+ w_imag = space.getattr(obj, space.wrap("imag"))
+ real = space.float_w(w_real)
+ imag = space.float_w(w_imag)
+ real_negzero = (real == 0.0 and
+ rarithmetic.copysign(1., real) < 0)
+ imag_negzero = (imag == 0.0 and
+ rarithmetic.copysign(1., imag) < 0)
+ if real_negzero and imag_negzero:
+ tup = [obj, space.w_complex, space.w_None, space.w_None,
+ space.w_None]
+ elif imag_negzero:
+ tup = [obj, space.w_complex, space.w_None, space.w_None]
+ elif real_negzero:
+ tup = [obj, space.w_complex, space.w_None]
+ else:
+ tup = [obj, space.w_complex]
+ w_key = space.newtuple(tup)
+ elif space.is_w(w_type, space.w_tuple):
+ result_w = [obj, w_type]
+ for w_item in space.fixedview(obj):
+ result_w.append(self._make_key(w_item))
+ w_key = space.newtuple(result_w[:])
+ else:
+ w_key = space.newtuple([obj, w_type])
+ return w_key
+
+ def load_const(self, obj):
+ index = self.add_const(obj)
self.emit_op_arg(ops.LOAD_CONST, index)
def update_position(self, lineno, force=False):
diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -714,17 +714,42 @@
class AppTestCompiler:
+ def test_values_of_different_types(self):
+ exec "a = 0; b = 0L; c = 0.0; d = 0j"
+ assert type(a) is int
+ assert type(b) is long
+ assert type(c) is float
+ assert type(d) is complex
+
+ def test_values_of_different_types_in_tuples(self):
+ exec "a = ((0,),); b = ((0L,),); c = ((0.0,),); d = ((0j,),)"
+ assert type(a[0][0]) is int
+ assert type(b[0][0]) is long
+ assert type(c[0][0]) is float
+ assert type(d[0][0]) is complex
+
def test_zeros_not_mixed(self):
import math
code = compile("x = -0.0; y = 0.0", "<test>", "exec")
consts = code.co_consts
- assert len(consts) == 3
- assert math.copysign(1, consts[0]) != math.copysign(1, consts[1])
+ x, y, z = consts
+ assert isinstance(x, float) and isinstance(y, float)
+ assert math.copysign(1, x) != math.copysign(1, y)
ns = {}
exec "z1, z2 = 0j, -0j" in ns
assert math.atan2(ns["z1"].imag, -1.) == math.atan2(0., -1.)
assert math.atan2(ns["z2"].imag, -1.) == math.atan2(-0., -1.)
+ def test_zeros_not_mixed_in_tuples(self):
+ import math
+ exec "a = (0.0, 0.0); b = (-0.0, 0.0); c = (-0.0, -0.0)"
+ assert math.copysign(1., a[0]) == 1.0
+ assert math.copysign(1., a[1]) == 1.0
+ assert math.copysign(1., b[0]) == -1.0
+ assert math.copysign(1., b[1]) == 1.0
+ assert math.copysign(1., c[0]) == -1.0
+ assert math.copysign(1., c[1]) == -1.0
+
##class TestPythonAstCompiler(BaseTestCompiler):
## def setup_method(self, method):
More information about the Pypy-commit
mailing list