[pypy-svn] r17612 - in pypy/dist/pypy/objspace/std: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Sep 17 14:03:25 CEST 2005


Author: cfbolz
Date: Sat Sep 17 14:03:24 2005
New Revision: 17612

Modified:
   pypy/dist/pypy/objspace/std/slicetype.py
   pypy/dist/pypy/objspace/std/test/test_sliceobject.py
Log:
rewrite the indices implementation of slices at interplevel to make it a bit
less slow. Following the CPython source code


Modified: pypy/dist/pypy/objspace/std/slicetype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/slicetype.py	(original)
+++ pypy/dist/pypy/objspace/std/slicetype.py	Sat Sep 17 14:03:24 2005
@@ -1,3 +1,4 @@
+import sys
 from pypy.interpreter import baseobjspace
 from pypy.objspace.std.stdtypedef import *
 from pypy.objspace.std.register_all import register_all
@@ -5,82 +6,77 @@
 
 slice_indices = MultiMethod('indices', 2)
 
-# default application-level implementations for some operations
-# gateway is imported in the stdtypedef module
-app = gateway.applevel("""
-
-    def indices(slice, length):
-        # this is used internally, analogous to CPython's PySlice_GetIndicesEx
-        step = slice.step
-        if step is None:
-            step = 1
-        elif step == 0:
-            raise ValueError, "slice step cannot be zero"
-        if step < 0:
-            defstart = length - 1
-            defstop = -1
+def slice_indices__ANY_ANY(space, w_slice, w_length):
+    length = space.int_w(w_length)
+    start, stop, step = indices3(space, w_slice, length)
+    return space.newtuple([space.wrap(start), space.wrap(stop),
+                           space.wrap(step)])
+
+# utility functions
+def _Eval_SliceIndex(space, w_int):
+    try:
+        x = space.int_w(w_int)
+    except OperationError, e:
+        if not e.match(space, space.w_OverflowError):
+            raise
+        cmp = space.is_true(space.ge(w_int, space.wrap(0)))
+        if cmp:
+            x = sys.maxint
         else:
-            defstart = 0
-            defstop = length
+            x = -sys.maxint
+    return x
 
-        start = slice.start
-        if start is None:
-            start = defstart
+def indices3(space, w_slice, length):
+    if space.is_true(space.is_(w_slice.w_step, space.w_None)):
+        step = 1
+    else:
+        step = _Eval_SliceIndex(space, w_slice.w_step)
+        if step == 0:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("slice step cannot be zero"))
+    if space.is_true(space.is_(w_slice.w_start, space.w_None)):
+        if step < 0:
+            start = length - 1
         else:
+            start = 0
+    else:
+        start = _Eval_SliceIndex(space, w_slice.w_start)
+        if start < 0:
+            start += length
             if start < 0:
-                start += length
-                if start < 0:
-                    if step < 0:
-                        start = -1
-                    else:
-                        start = 0
-            elif start >= length:
                 if step < 0:
-                    start = length - 1
+                    start = -1
                 else:
-                    start = length
-
-        stop = slice.stop
-        if stop is None:
-            stop = defstop
+                    start = 0
+        elif start >= length:
+            if step < 0:
+                start = length - 1
+            else:
+                start = length
+    if space.is_true(space.is_(w_slice.w_stop, space.w_None)):
+        if step < 0:
+            stop = -1
         else:
+            stop = length
+    else:
+        stop = _Eval_SliceIndex(space, w_slice.w_stop)
+        if stop < 0:
+            stop += length
             if stop < 0:
-                stop += length
-                if stop < 0:
-                    stop = -1
-            elif stop > length:
-                stop = length
-
-        return start, stop, step
-
-    def slice_indices4(slice, sequencelength):
-        start, stop, step = indices(slice, sequencelength)
-        slicelength = stop - start
-        lengthsign = cmp(slicelength, 0)
-        stepsign = cmp(step, 0)
-        if stepsign == lengthsign:
-            slicelength = (slicelength - lengthsign) // step + 1
-        else:
-            slicelength = 0
-
-        return start, stop, step, slicelength
-""", filename=__file__)
-
-slice_indices__ANY_ANY = app.interphook("indices")
-slice_indices3         = slice_indices__ANY_ANY
-slice_indices4         = app.interphook("slice_indices4")
-
-# utility functions
-def indices3(space, w_slice, length):
-    w_result = slice_indices3(space, w_slice, space.wrap(length))
-    w_1, w_2, w_3 = space.unpacktuple(w_result, 3)
-    return space.int_w(w_1), space.int_w(w_2), space.int_w(w_3)
+                stop =-1
+        elif stop > length:
+            stop = length
+    return start, stop, step
 
 def indices4(space, w_slice, length):
-    w_result = slice_indices4(space, w_slice, space.wrap(length))
-    w_1, w_2, w_3, w_4 = space.unpacktuple(w_result, 4)
-    return (space.int_w(w_1), space.int_w(w_2),
-            space.int_w(w_3), space.int_w(w_4))
+    start, stop, step = indices3(space, w_slice, length)
+    if (step < 0 and stop >= start) or (step > 0 and start >= stop):
+        slicelength = 0
+    elif step < 0:
+        slicelength = (stop - start + 1) / step + 1
+    else:
+        slicelength = (stop - start - 1) / step + 1
+    return start, stop, step, slicelength
 
 def adapt_bound(space, w_index, w_size):
     if not (space.is_true(space.isinstance(w_index, space.w_int)) or

Modified: pypy/dist/pypy/objspace/std/test/test_sliceobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_sliceobject.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_sliceobject.py	Sat Sep 17 14:03:24 2005
@@ -24,6 +24,7 @@
         self.space.raises_w(space.w_ValueError,
                             slicetype.indices3, space, w_slice, 10)
 
+
 class AppTest_SliceObject:
     def test_new(self):
         def cmp_slice(sl1, sl2):
@@ -64,3 +65,14 @@
         assert not (slice(1, 2, 3) < slice(1, 0, 0))
         assert not (slice(1, 2, 3) < slice(1, 2, 0))
         assert not (slice(1, 2, 3) < slice(1, 2, 3))
+
+    def test_long_indices(self):
+        assert slice(-2 ** 100, 10, 1).indices(1000) == (0, 10, 1)
+        assert slice(-2 ** 200, -2 ** 100, 1).indices(1000) == (0, -1, 1)
+        assert slice(2 ** 100, 0, -1).indices(1000) == (999, 0, -1)
+        assert slice(2 ** 100, -2 ** 100, -1).indices(1000) == (999, -1, -1)
+        start, stop, step = slice(0, 1000, 2 ** 200).indices(1000)
+        assert start == 0
+        assert stop == 1000
+        assert step >= 1000
+        raises(OverflowError, "slice(0, 1000, 1).indices(2 ** 100)")



More information about the Pypy-commit mailing list