/* * Initialize a Mersenne Twist RNG from a 624-int seed. * * The 32-bit seeding routine given by Matsumoto and Nishimura has the * drawback that there are only 2^32 different PRNG sequences that can be * generated by calling that function. This function solves that problem by * allowing a full 624*32-bit state to be given. (Note that 31 bits of the * given state are ignored; see the paper for details.) * * Since an all-zero state would cause the PRNG to cycle, we detect * that case and abort the program (silently, since there is no * portable way to produce a message in both C and C++ environments). * An alternative would be to artificially force the state to some * known nonzero value. However, I feel that if the user is providing * a full state, it's a bug to provide all zeros and we we shouldn't * conceal the bug by generating apparently correct output. */ void mts_seedfull( mt_state* state, /* State vector to initialize */ uint32_t seeds[MT_STATE_SIZE]) /* Seed array to start from */ { int had_nz = 0; /* NZ if at least one NZ seen */ int i; /* Loop index */ for (i = 0; i < MT_STATE_SIZE; i++) { if (seeds[i] != 0) had_nz = 1; state->statevec[MT_STATE_SIZE - i - 1] = seeds[i]; } if (!had_nz) { /* * It would be nice to abort with a message. Unfortunately, fprintf * isn't compatible with all implementations of C++. In the * interest of C++ compatibility, therefore, we will simply abort * silently. It will unfortunately be up to a programmer to run * under a debugger (or examine the core dump) to discover the cause * of the abort. */ /* abort(); */ return; } state->stateptr = MT_STATE_SIZE; mts_mark_initialized(state); }
/* * 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); }
/* * 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); }
/* * Load state from a file. Returns NZ if the load succeeded. */ int mts_loadstate( FILE* statefile, /* File to load from */ mt_state* state) /* State to be loaded */ { int i; /* Next word to load */ /* * Set the state to "uninitialized" in case the load fails. */ state->initialized = state->stateptr = 0; for (i = MT_STATE_SIZE; --i >= 0; ) { if (fscanf(statefile, "%" SCNu32, &state->statevec[i]) != 1) return 0; } if (fscanf(statefile, "%d", &state->stateptr) != 1) return 0; /* * The only validity checking we can do is to insist that the * state pointer be valid. */ if (state->stateptr < 0 || state->stateptr > MT_STATE_SIZE) { state->stateptr = 0; return 0; } mts_mark_initialized(state); return 1; }
int cvar_revalidate_handle(void *cvar_handle) { handle_t *h = (handle_t *) cvar_handle; mts_mark_initialized(&h->state); return 0; }
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); }