[pypy-commit] pypy default: random.getrandbits() is no longer quadratic.

amauryfa noreply at buildbot.pypy.org
Sun Dec 2 00:36:52 CET 2012


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r59207:f43af8306780
Date: 2012-12-02 00:36 +0100
http://bitbucket.org/pypy/pypy/changeset/f43af8306780/

Log:	random.getrandbits() is no longer quadratic.

diff --git a/pypy/module/_random/interp_random.py b/pypy/module/_random/interp_random.py
--- a/pypy/module/_random/interp_random.py
+++ b/pypy/module/_random/interp_random.py
@@ -3,7 +3,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.rlib.rarithmetic import r_uint, intmask
-from pypy.rlib import rrandom
+from pypy.rlib import rbigint, rrandom, rstring
 
 import time
 
@@ -89,25 +89,21 @@
             strerror = space.wrap("number of bits must be greater than zero")
             raise OperationError(space.w_ValueError, strerror)
         bytes = ((k - 1) // 32 + 1) * 4
-        bytesarray = [0] * bytes
+        bytesarray = rstring.StringBuilder(bytes)
         for i in range(0, bytes, 4):
             r = self._rnd.genrand32()
             if k < 32:
                 r >>= (32 - k)
-            bytesarray[i + 0] = r & r_uint(0xff)
-            bytesarray[i + 1] = (r >> 8) & r_uint(0xff)
-            bytesarray[i + 2] = (r >> 16) & r_uint(0xff)
-            bytesarray[i + 3] = (r >> 24) & r_uint(0xff)
+            bytesarray.append(chr(r & r_uint(0xff)))
+            bytesarray.append(chr((r >> 8) & r_uint(0xff)))
+            bytesarray.append(chr((r >> 16) & r_uint(0xff)))
+            bytesarray.append(chr((r >> 24) & r_uint(0xff)))
             k -= 32
 
-        # XXX so far this is quadratic
-        w_result = space.newint(0)
-        w_eight = space.newint(8)
-        for i in range(len(bytesarray) - 1, -1, -1):
-            byte = bytesarray[i]
-            w_result = space.or_(space.lshift(w_result, w_eight),
-                                 space.newint(intmask(byte)))
-        return w_result
+        # little endian order to match bytearray assignment order
+        result = rbigint.rbigint.frombytes(
+            bytesarray.build(), 'little', signed=False)
+        return space.newlong_from_rbigint(result)
 
 
 W_Random.typedef = TypeDef("Random",
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -143,6 +143,9 @@
     def newcomplex(self, x, y):
         return w_some_obj()
 
+    def newlong_from_rbigint(self, x):
+        return w_some_obj()
+
     def marshal_w(self, w_obj):
         "NOT_RPYTHON"
         raise NotImplementedError


More information about the pypy-commit mailing list