This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

Notebooks · lib/nprandom/mt19937

NumPy's Mersenne Twister, word for word

np.random.seed(s) and every draw of NumPy's legacy functions (np.random.rand, randint, shuffle, ...) come from one MT19937 generator. This is that generator, transcribed from NumPy 1.24.4 (numpy/random/src/mt19937/mt19937.c and mt19937.h, and _legacy_seeding in numpy/random/_mt19937.pyx; tag v1.24.4, commit 9315a9072b2636f75c831b4eca9f42a5f67ca2fb). The constants carry the reference's names.

The state is an array of NPR_MT_LEN numbers: the 624 key words, the position of the next word, and a flag that says whether it was seeded (a draw from an unseeded state has no reproducible value, so the py2viv translation stops on one). Each word is a double in [0, 2^32), and the bit operations are Viv's builtins, so the interpreter, compiled C and wasm compute the same words.

  • npr_mt_new(): an unseeded state.
  • npr_mt_seed(st, s): np.random.seed(s) for an int s in [0, 2^32 - 1], by Knuth's recurrence, key[i] = 1812433253 * (key[i-1] ^ (key[i-1] >> 30)) + i.
  • npr_mt_seed_array(st, key): np.random.seed([k0, k1, ...]), the reference's init_by_array.
  • npr_mt_next32(st): the next tempered word.
  • npr_mt_double(st): NumPy's double in [0, 1), made from a = next >> 5 and b = next >> 6 as (a * 2^26 + b) / 2^53.
  • npr_mt_masked64(st, mask): a 64-bit draw, (next << 32) | next with the first word high (as NumPy's build evaluates it), ANDed with mask, as Ints.

Used with import nprandom.mt19937.

Look inside this program

  • Atlas

    The program’s map: every function and which calls which.

  • There’s no recorded run of this program yet.

Shift+Enter in a cell runs it and moves to the next. Running a cell runs every cell above it too, as one program.

[1]lines 32–184