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