/* * Initialize a Mersenne Twist PRNG from a 32-bit seed, using * Matsumoto and Nishimura's newer reference implementation (Jan. 9, * 2002). */ void mts_seed32new( mt_state* state, /* State vector to initialize */ uint32_t seed) /* 32-bit seed to start from */ { int i; /* Loop index */ uint32_t nextval; /* Next value being calculated */ /* * Fill the state vector using Knuth's PRNG. Be sure to mask down * to 32 bits in case we're running on a machine with 64-bit * ints. */ state->statevec[MT_STATE_SIZE - 1] = seed & 0xffffffffUL; for (i = MT_STATE_SIZE - 2; i >= 0; i--) { nextval = state->statevec[i + 1] >> KNUTH_SHIFT; nextval ^= state->statevec[i + 1]; nextval *= KNUTH_MULTIPLIER_NEW; nextval += (MT_STATE_SIZE - 1) - i; state->statevec[i] = nextval & 0xffffffffUL; } state->stateptr = MT_STATE_SIZE; mts_mark_initialized(state); /* * Matsumoto and Nishimura's implementation refreshes the PRNG * immediately after running the Knuth algorithm. This is * probably a good thing, since Knuth's PRNG doesn't generate very * good numbers. */ mts_refresh(state); }
/* * Save state to a file. The save format is compatible with Richard * J. Wagner's format, although the details are different. Returns NZ * if the save succeeded. Produces one very long line containing 625 * numbers. */ int mts_savestate( FILE* statefile, /* File to save to */ mt_state* state) /* State to be saved */ { int i; /* Next word to save */ if (!state->initialized) mts_seed32(state, DEFAULT_SEED32_OLD); /* * Ensure the state pointer is valid. */ if (state->stateptr < 0 || state->stateptr > MT_STATE_SIZE) { fprintf(stderr, "Mtwist internal: Trying to write invalid state pointer %d\n", state->stateptr); mts_refresh(state); } for (i = MT_STATE_SIZE; --i >= 0; ) { if (fprintf(statefile, "%" PRIu32 " ", state->statevec[i]) < 0) return 0; } if (fprintf(statefile, "%d\n", state->stateptr) < 0) return 0; return 1; }
/* * Initialize a Mersenne Twist PRNG from a 32-bit seed. * * According to Matsumoto and Nishimura's paper, the seed array needs to be * filled with nonzero values. (My own interpretation is that there needs * to be at least one nonzero value). They suggest using Knuth's PRNG from * Line 25, Table 1, p.102, "The Art of Computer Programming," Vol. 2 (2nd * ed.), 1981. I find that rather odd, since that particular PRNG is * sensitive to having an initial seed of zero (there are many other PRNGs * out there that have an additive component, so that a seed of zero does * not generate a repeating-zero sequence). However, one thing I learned * from reading Knuth is that you shouldn't second-guess mathematicians * about PRNGs. Also, by following M & N's approach, we will be compatible * with other implementations. So I'm going to stick with their version, * with the single addition that a zero seed will be changed to their * default seed. */ void mts_seed32( mt_state* state, /* State vector to initialize */ uint32_t seed) /* 32-bit seed to start from */ { int i; /* Loop index */ if (seed == 0) seed = DEFAULT_SEED32_OLD; /* * Fill the state vector using Knuth's PRNG. Be sure to mask down * to 32 bits in case we're running on a machine with 64-bit * ints. */ state->statevec[MT_STATE_SIZE - 1] = seed & 0xffffffff; for (i = MT_STATE_SIZE - 2; i >= 0; i--) state->statevec[i] = (KNUTH_MULTIPLIER_OLD * state->statevec[i + 1]) & 0xffffffff; state->stateptr = MT_STATE_SIZE; mts_mark_initialized(state); /* * Matsumoto and Nishimura's implementation refreshes the PRNG * immediately after running the Knuth algorithm. This is * probably a good thing, since Knuth's PRNG doesn't generate very * good numbers. */ mts_refresh(state); }
void mts_seed32new( mt_state* state, uint32_t seed) { int i; uint32_t nextval; state->statevec[MT_STATE_SIZE - 1] = seed & 0xffffffffUL; for (i = MT_STATE_SIZE - 2; i >= 0; i--) { nextval = state->statevec[i + 1] >> KNUTH_SHIFT; nextval ^= state->statevec[i + 1]; nextval *= KNUTH_MULTIPLIER_NEW; nextval += (MT_STATE_SIZE - 1) - i; state->statevec[i] = nextval & 0xffffffffUL; } state->stateptr = MT_STATE_SIZE; mts_mark_initialized(state); mts_refresh(state); }