Author: Armin Rigo <ar...@tunes.org>
Branch: int-float-list-strategy
Changeset: r78386:d38f6591e679
Date: 2015-07-01 19:18 +0200
http://bitbucket.org/pypy/pypy/changeset/d38f6591e679/

Log:    in-progress

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
@@ -14,6 +14,7 @@
 from rpython.rlib.listsort import make_timsort_class
 from rpython.rlib.objectmodel import (
     import_from_mixin, instantiate, newlist_hint, resizelist_hint, specialize)
+from rpython.rlib import longlong2float
 from rpython.tool.sourcetools import func_with_new_name
 
 from pypy.interpreter.baseobjspace import W_Root
@@ -73,33 +74,56 @@
             return SizeListStrategy(space, sizehint)
         return space.fromcache(EmptyListStrategy)
 
-    # check for ints
-    for w_obj in list_w:
-        if not type(w_obj) is W_IntObject:
+    w_firstobj = list_w[0]
+    check_int_or_float = False
+
+    if type(w_firstobj) is W_IntObject:
+        # check for all-ints
+        for i in range(1, len(list_w)):
+            w_obj = list_w[i]
+            if type(w_obj) is not W_IntObject:
+                check_int_or_float = (type(w_obj) is W_FloatObject)
+                break
+        else:
+            return space.fromcache(IntegerListStrategy)
+
+    elif type(w_firstobj) is W_BytesObject:
+        # check for all-strings
+        for i in range(1, len(list_w)):
+            if type(list_w[i]) is not W_BytesObject:
+                break
+        else:
+            return space.fromcache(BytesListStrategy)
+
+    elif type(w_firstobj) is W_UnicodeObject:
+        # check for all-unicodes
+        for i in range(1, len(list_w)):
+            if type(list_w[i]) is not W_UnicodeObject:
+                break
+        else:
+            return space.fromcache(UnicodeListStrategy)
+
+    elif type(w_firstobj) is W_FloatObject:
+        # check for all-floats
+        for i in range(1, len(list_w)):
+            w_obj = list_w[i]
+            if type(w_obj) is not W_FloatObject:
+                check_int_or_float = (type(w_obj) is W_IntObject)
+                break
+        else:
+            return space.fromcache(FloatListStrategy)
+
+    if check_int_or_float:
+        for w_obj in list_w:
+            if type(w_obj) is W_IntObject:
+                if longlong2float.can_encode_int32(space.int_w(w_obj)):
+                    continue    # ok
+            elif type(w_obj) is W_FloatObject:
+                if longlong2float.can_encode_float(space.float_w(w_obj)):
+                    continue    # ok
             break
-    else:
-        return space.fromcache(IntegerListStrategy)
-
-    # check for strings
-    for w_obj in list_w:
-        if not type(w_obj) is W_BytesObject:
-            break
-    else:
-        return space.fromcache(BytesListStrategy)
-
-    # check for unicode
-    for w_obj in list_w:
-        if not type(w_obj) is W_UnicodeObject:
-            break
-    else:
-        return space.fromcache(UnicodeListStrategy)
-
-    # check for floats
-    for w_obj in list_w:
-        if not type(w_obj) is W_FloatObject:
-            break
-    else:
-        return space.fromcache(FloatListStrategy)
+        else:
+            return space.fromcache(IntOrFloatListStrategy)
 
     return space.fromcache(ObjectListStrategy)
 
@@ -1382,12 +1406,15 @@
             return W_ListObject.from_storage_and_strategy(
                     self.space, storage, self)
 
+    def switch_to_next_strategy(self, w_list, w_sample_item):
+        w_list.switch_to_object_strategy()
+
     def append(self, w_list, w_item):
         if self.is_correct_type(w_item):
             self.unerase(w_list.lstorage).append(self.unwrap(w_item))
             return
 
-        w_list.switch_to_object_strategy()
+        self.switch_to_next_strategy(w_list, w_item)
         w_list.append(w_item)
 
     def insert(self, w_list, index, w_item):
@@ -1397,7 +1424,7 @@
             l.insert(index, self.unwrap(w_item))
             return
 
-        w_list.switch_to_object_strategy()
+        self.switch_to_next_strategy(w_list, w_item)
         w_list.insert(index, w_item)
 
     def _extend_from_list(self, w_list, w_other):
@@ -1673,7 +1700,6 @@
 
     def _safe_find(self, w_list, obj, start, stop):
         from rpython.rlib.rfloat import isnan
-        from rpython.rlib.longlong2float import float2longlong
         #
         l = self.unerase(w_list.lstorage)
         stop = min(stop, len(l))
@@ -1683,10 +1709,10 @@
                 if val == obj:
                     return i
         else:
-            search = float2longlong(obj)
+            search = longlong2float.float2longlong(obj)
             for i in range(start, stop):
                 val = l[i]
-                if float2longlong(val) == search:
+                if longlong2float.float2longlong(val) == search:
                     return i
         raise ValueError
 
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
@@ -733,6 +733,11 @@
         list_copy[0] = 42
         assert list_orig == [1, 2, 3]
 
+    def test_int_or_float(self):
+        space = self.space
+        w_l = W_ListObject(space, [space.wrap(1), space.wrap(2.3)])
+        xxxxx
+
 
 class TestW_ListStrategiesDisabled:
     spaceconfig = {"objspace.std.withliststrategies": False}
diff --git a/rpython/rlib/longlong2float.py b/rpython/rlib/longlong2float.py
--- a/rpython/rlib/longlong2float.py
+++ b/rpython/rlib/longlong2float.py
@@ -7,6 +7,7 @@
 """
 
 from __future__ import with_statement
+import sys
 from rpython.annotator import model as annmodel
 from rpython.rlib.rarithmetic import r_int64
 from rpython.rtyper.lltypesystem import lltype, rffi
@@ -99,3 +100,29 @@
         [v_longlong] = hop.inputargs(lltype.SignedLongLong)
         hop.exception_cannot_occur()
         return hop.genop("convert_longlong_bytes_to_float", [v_longlong], 
resulttype=lltype.Float)
+
+# ____________________________________________________________
+
+
+# For encoding integers inside nonstandard NaN bit patterns.
+#   ff ff ff fe xx xx xx xx    (signed 32-bit int)
+nan_high_word_int32 = -2       # -2 == (int)0xfffffffe
+nan_encoded_zero = rffi.cast(rffi.LONGLONG, nan_high_word_int32 << 32)
+
+def encode_int32_into_longlong_nan(value):
+    return (nan_encoded_zero +
+            rffi.cast(rffi.LONGLONG, rffi.cast(rffi.UINT, value)))
+
+def decode_int32_from_longlong_nan(value):
+    return rffi.cast(lltype.Signed, rffi.cast(rffi.INT, value))
+
+def is_int32_from_longlong_nan(value):
+    return (value >> 32) == nan_high_word_int32
+
+def can_encode_int32(value):
+    if sys.maxint == 2147483647:
+        return True
+    return value == rffi.cast(lltype.Signed, rffi.cast(rffi.INT, value))
+
+def can_encode_float(value):
+    return (float2longlong(value) >> 32) != nan_high_word_int32
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to