[pypy-svn] pypy default: (fijal, arigo)

arigo commits-noreply at bitbucket.org
Thu Jan 20 10:25:54 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r40966:dde6582af142
Date: 2011-01-20 10:23 +0100
http://bitbucket.org/pypy/pypy/changeset/dde6582af142/

Log:	(fijal, arigo)

	Finish reimplementing range() at interp-level.

diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -13,6 +13,7 @@
 from pypy.rlib.objectmodel import specialize
 from inspect import getsource, getfile
 from pypy.rlib.jit import unroll_safe
+from pypy.rlib.rbigint import rbigint
 
 
 def get_len_of_range(space, lo, hi, step):
@@ -103,6 +104,38 @@
     from pypy.objspace.std.rangeobject import W_RangeListObject
     return W_RangeListObject(start, step, howmany)
 
+bigint_one = rbigint.fromint(1)
+
+def range_with_longs(space, w_start, w_stop, w_step):
+
+    start = lo = space.bigint_w(w_start)
+    stop  = hi = space.bigint_w(w_stop)
+    step  = st = space.bigint_w(w_step)
+
+    if not step.tobool():
+        raise OperationError(space.w_ValueError,
+                             space.wrap("step argument must not be zero"))
+    elif step.sign < 0:
+        lo, hi, st = hi, lo, st.neg()
+
+    if lo.lt(hi):
+        diff = hi.sub(lo).sub(bigint_one)
+        n = diff.floordiv(st).add(bigint_one)
+        try:
+            howmany = n.toint()
+        except OverflowError:
+            raise OperationError(space.w_OverflowError,
+                                 space.wrap("result has too many items"))
+    else:
+        howmany = 0
+
+    res_w = [None] * howmany
+    v = start
+    for idx in range(howmany):
+        res_w[idx] = space.wrap(v)
+        v = v.add(step)
+    return space.newlist(res_w)
+
 
 @unroll_safe
 @specialize.arg(2)

diff --git a/pypy/module/__builtin__/test/test_range.py b/pypy/module/__builtin__/test/test_range.py
--- a/pypy/module/__builtin__/test/test_range.py
+++ b/pypy/module/__builtin__/test/test_range.py
@@ -91,3 +91,24 @@
        assert range(a+2, a, -1L) == [a+2, a+1]
        assert range(a+4, a, -2) == [a+4, a+2]
        assert range(a, a*5, a) == [a, 2*a, 3*a, 4*a]
+
+   def test_range_cases(self):
+       import sys
+       for start in [10, 10 * sys.maxint]:
+           for stop in [start-4, start-1, start, start+1, start+4]:
+              for step in [1, 2, 3, 4]:
+                  lst = range(start, stop, step)
+                  expected = []
+                  a = start
+                  while a < stop:
+                      expected.append(a)
+                      a += step
+                  assert lst == expected
+              for step in [-1, -2, -3, -4]:
+                  lst = range(start, stop, step)
+                  expected = []
+                  a = start
+                  while a > stop:
+                      expected.append(a)
+                      a += step
+                  assert lst == expected


More information about the Pypy-commit mailing list