Author: Armin Rigo <ar...@tunes.org>
Branch: int-float-list-strategy
Changeset: r78390:12404829e22a
Date: 2015-07-01 23:17 +0200
http://bitbucket.org/pypy/pypy/changeset/12404829e22a/

Log:    More tests, and float -> int-or-float

diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -1675,18 +1675,17 @@
                 if not longlong2float.can_encode_int32(intval):
                     break
             else:
-                floatval = self.space.float_w(w_sample_item)
-                if longlong2float.can_encode_float(floatval):
-                    # yes, we can switch to IntOrFloatListStrategy
-                    generalized_list = [
-                        longlong2float.encode_int32_into_longlong_nan(intval)
-                        for intval in l]
-                    generalized_list.append(
-                        longlong2float.float2longlong(floatval))
-                    strategy = self.space.fromcache(IntOrFloatListStrategy)
-                    w_list.strategy = strategy
-                    w_list.lstorage = strategy.erase(generalized_list)
-                    return
+                # yes, we can switch to IntOrFloatListStrategy
+                # (ignore here the extremely unlikely case where
+                # w_sample_item is just the wrong nonstandard NaN float;
+                # it will caught later and yet another switch will occur)
+                generalized_list = [
+                    longlong2float.encode_int32_into_longlong_nan(intval)
+                    for intval in l]
+                strategy = self.space.fromcache(IntOrFloatListStrategy)
+                w_list.strategy = strategy
+                w_list.lstorage = strategy.erase(generalized_list)
+                return
         # no, fall back to ObjectListStrategy
         w_list.switch_to_object_strategy()
 
@@ -1740,6 +1739,29 @@
                     return i
         raise ValueError
 
+    def switch_to_next_strategy(self, w_list, w_sample_item):
+        if type(w_sample_item) is W_IntObject:
+            intval = self.space.int_w(w_sample_item)
+            if longlong2float.can_encode_int32(intval):
+                # xxx we should be able to use the same lstorage, but
+                # there is a typing issue (float vs longlong)...
+                l = self.unerase(w_list.lstorage)
+                generalized_list = []
+                for floatval in l:
+                    if not longlong2float.can_encode_float(floatval):
+                        break
+                    generalized_list.append(
+                        longlong2float.float2longlong(floatval))
+                else:
+                    # yes, we can switch to IntOrFloatListStrategy
+                    strategy = self.space.fromcache(IntOrFloatListStrategy)
+                    w_list.strategy = strategy
+                    w_list.lstorage = strategy.erase(generalized_list)
+                    return
+        # no, fall back to ObjectListStrategy
+        w_list.switch_to_object_strategy()
+
+
 class IntOrFloatListStrategy(ListStrategy):
     import_from_mixin(AbstractUnwrappedStrategy)
 
diff --git a/pypy/objspace/std/test/test_liststrategies.py 
b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -789,6 +789,72 @@
         assert isinstance(w_l.strategy, IntOrFloatListStrategy)
         assert space.int_w(w_l.getitem(0)) == -2**31
         assert space.float_w(w_l.getitem(1)) == -5.1
+        assert space.len_w(w_l) == 2
+
+    def test_int_or_float_from_integer_overflow(self):
+        if sys.maxint == 2147483647:
+            py.test.skip("only on 64-bit")
+        space = self.space
+        w = space.wrap
+        ovf1 = -2**31 - 1
+        w_l = W_ListObject(space, [space.wrap(ovf1)])
+        assert isinstance(w_l.strategy, IntegerListStrategy)
+        w_l.append(w(-5.1))
+        assert isinstance(w_l.strategy, ObjectListStrategy)
+        assert space.int_w(w_l.getitem(0)) == ovf1
+        assert space.float_w(w_l.getitem(1)) == -5.1
+        assert space.len_w(w_l) == 2
+
+    def test_int_or_float_from_integer_special_nan(self):
+        from rpython.rlib import longlong2float, rarithmetic
+        space = self.space
+        w = space.wrap
+        w_l = W_ListObject(space, [space.wrap(int(-2**31))])
+        assert isinstance(w_l.strategy, IntegerListStrategy)
+        ll = rarithmetic.r_longlong(0xfffffffe12345678 - 2**64)
+        specialnan = longlong2float.longlong2float(ll)
+        w_l.append(w(specialnan))
+        assert isinstance(w_l.strategy, ObjectListStrategy)
+        assert space.int_w(w_l.getitem(0)) == -2**31
+        assert space.len_w(w_l) == 2
+
+    def test_int_or_float_from_float(self):
+        space = self.space
+        w = space.wrap
+        w_l = W_ListObject(space, [space.wrap(-42.5)])
+        assert isinstance(w_l.strategy, FloatListStrategy)
+        w_l.append(w(-15))
+        assert isinstance(w_l.strategy, IntOrFloatListStrategy)
+        assert space.float_w(w_l.getitem(0)) == -42.5
+        assert space.int_w(w_l.getitem(1)) == -15
+        assert space.len_w(w_l) == 2
+
+    def test_int_or_float_from_float_int_overflow(self):
+        if sys.maxint == 2147483647:
+            py.test.skip("only on 64-bit")
+        space = self.space
+        w = space.wrap
+        ovf1 = 2 ** 31
+        w_l = W_ListObject(space, [space.wrap(1.2)])
+        assert isinstance(w_l.strategy, FloatListStrategy)
+        w_l.append(w(ovf1))
+        assert isinstance(w_l.strategy, ObjectListStrategy)
+        assert space.float_w(w_l.getitem(0)) == 1.2
+        assert space.int_w(w_l.getitem(1)) == ovf1
+        assert space.len_w(w_l) == 2
+
+    def test_int_or_float_from_float_special_nan(self):
+        from rpython.rlib import longlong2float, rarithmetic
+        space = self.space
+        w = space.wrap
+        ll = rarithmetic.r_longlong(0xfffffffe12345678 - 2**64)
+        specialnan = longlong2float.longlong2float(ll)
+        w_l = W_ListObject(space, [space.wrap(specialnan)])
+        assert isinstance(w_l.strategy, FloatListStrategy)
+        w_l.append(w(42))
+        assert isinstance(w_l.strategy, ObjectListStrategy)
+        assert space.int_w(w_l.getitem(1)) == 42
+        assert space.len_w(w_l) == 2
 
 
 class TestW_ListStrategiesDisabled:
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to