Author: Amaury Forgeot d'Arc <[email protected]>
Branch:
Changeset: r60498:0ec3d77645a2
Date: 2013-01-25 22:02 +0100
http://bitbucket.org/pypy/pypy/changeset/0ec3d77645a2/
Log: Issue1381 resolved: Prevent random.jumpahead() to yield random
values above 1.0.
Similar to CPython issue14591, even if we don't use exactly the same
algorithm (The n%i operation operates on C ints, when CPython uses
Python numbers)
diff --git a/rpython/rlib/rrandom.py b/rpython/rlib/rrandom.py
--- a/rpython/rlib/rrandom.py
+++ b/rpython/rlib/rrandom.py
@@ -100,9 +100,21 @@
def jumpahead(self, n):
mt = self.state
- for i in range(N - 1, 0, -1):
+ for i in range(N - 1, 1, -1):
j = n % i
mt[i], mt[j] = mt[j], mt[i]
- for i in range(N):
+ nonzero = False
+ for i in range(1, N):
mt[i] += r_uint(i + 1)
+ mt[i] &= r_uint(0xffffffff)
+ nonzero |= bool(mt[i])
+ # Ensure the state is nonzero: in the unlikely event that mt[1] through
+ # mt[N-1] are all zero, set the MSB of mt[0] (see issue #14591). In the
+ # normal case, we fall back to the pre-issue 14591 behaviour for mt[0].
+ if nonzero:
+ mt[0] += r_uint(1)
+ mt[0] &= r_uint(0xffffffff)
+ else:
+ mt[0] = r_uint(0x80000000)
+ print mt[:3]
self.index = N
diff --git a/rpython/rlib/test/test_rrandom.py
b/rpython/rlib/test/test_rrandom.py
--- a/rpython/rlib/test/test_rrandom.py
+++ b/rpython/rlib/test/test_rrandom.py
@@ -46,6 +46,15 @@
assert tuple(rnd.state) + (rnd.index, ) == cpyrandom.getstate()
+def test_jumpahead_badstate():
+ rnd = Random()
+ s, j = 4043161618, 2674112291824205302
+ rnd.init_by_array([s])
+ rnd.jumpahead(j)
+ for i in range(500):
+ r = rnd.random()
+ assert r <= 1.0, (r, i)
+
def test_translate():
def f(x, y):
x = r_uint(x)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit