Skip to content

Commit

Permalink
BUG: Correct incorrect advance in PCG with emulated int128
Browse files Browse the repository at this point in the history
Correct incorrect implemetation of carry in PCG64 and PCG64DXSM
when advancing more than 2**64 steps

closes #20048
  • Loading branch information
bashtage authored and charris committed Oct 10, 2021
1 parent c3de0e6 commit a26be10
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 a26be10

Please sign in to comment.