Skip to content

Commit

Permalink
Merge pull request #20080 from charris/backport-20049
Browse files Browse the repository at this point in the history
BUG: Correct incorrect advance in PCG with emulated int128
  • Loading branch information
charris committed Oct 10, 2021
2 parents c3de0e6 + a26be10 commit 94c8a3c
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
5 changes: 5 additions & 0 deletions doc/release/upcoming_changes/20049.change.rst
@@ -0,0 +1,5 @@
Corrected ``advance`` in ``PCG64DSXM`` and ``PCG64``
----------------------------------------------------
Fixed a bug in the ``advance`` method of ``PCG64DSXM`` and ``PCG64``. The bug only
affects results when the step was larger than :math:`2^{64}` on platforms
that do not support 128-bit integers(e.g., Windows and 32-bit Linux).
3 changes: 1 addition & 2 deletions numpy/random/src/pcg64/pcg64.c
Expand Up @@ -109,8 +109,7 @@ pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, pcg128_t cur_mult,
cur_plus = pcg128_mult(pcg128_add(cur_mult, PCG_128BIT_CONSTANT(0u, 1u)),
cur_plus);
cur_mult = pcg128_mult(cur_mult, cur_mult);
delta.low >>= 1;
delta.low += delta.high & 1;
delta.low = (delta.low >> 1) | (delta.high << 63);
delta.high >>= 1;
}
return pcg128_add(pcg128_mult(acc_mult, state), acc_plus);
Expand Down
22 changes: 22 additions & 0 deletions numpy/random/tests/test_direct.py
Expand Up @@ -358,6 +358,17 @@ def test_advance_symmetry(self):
assert val_neg == val_pos
assert val_big == val_pos

def test_advange_large(self):
rs = Generator(self.bit_generator(38219308213743))
pcg = rs.bit_generator
state = pcg.state["state"]
initial_state = 287608843259529770491897792873167516365
assert state["state"] == initial_state
pcg.advance(sum(2**i for i in (96, 64, 32, 16, 8, 4, 2, 1)))
state = pcg.state["state"]
advanced_state = 135275564607035429730177404003164635391
assert state["state"] == advanced_state


class TestPCG64DXSM(Base):
@classmethod
Expand Down Expand Up @@ -386,6 +397,17 @@ def test_advance_symmetry(self):
assert val_neg == val_pos
assert val_big == val_pos

def test_advange_large(self):
rs = Generator(self.bit_generator(38219308213743))
pcg = rs.bit_generator
state = pcg.state
initial_state = 287608843259529770491897792873167516365
assert state["state"]["state"] == initial_state
pcg.advance(sum(2**i for i in (96, 64, 32, 16, 8, 4, 2, 1)))
state = pcg.state["state"]
advanced_state = 277778083536782149546677086420637664879
assert state["state"] == advanced_state


class TestMT19937(Base):
@classmethod
Expand Down

0 comments on commit 94c8a3c

Please sign in to comment.