Commits

committed 0ec3d77

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)

• Participants
• Parent commits 9fe829a

File rpython/rlib/rrandom.py

` `
`     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`

File rpython/rlib/test/test_rrandom.py

`     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)`