Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Correct incorrect advance in PCG with emulated int128 #20080

Merged
merged 1 commit into from Oct 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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