📄 mtwist.h
字号:
mts_refresh(state); random_value_1 = state->statevec[--state->stateptr]; } else { random_value_1 = state->statevec[state->stateptr]; mts_refresh(state); } } else random_value_1 = state->statevec[--state->stateptr]; MT_TEMPER(random_value_1); random_value_2 = state->statevec[--state->stateptr]; MT_PRE_TEMPER(random_value_2); return ((unsigned long long) random_value_1 << 32) | (unsigned long long) MT_FINAL_TEMPER(random_value_2); }#endif /* MT_NO_LONGLONG *//* * Generate a double-precision random number between 0 (inclusive) and 1.0 * (exclusive). This function is optimized for speed, but it only generates * 32 bits of precision. Use mts_ldrand to get 64 bits of precision. */MT_EXTERN MT_INLINE double mts_drand( register mt_state* state) /* State for the PRNG */ { register unsigned long random_value; /* Pseudorandom value generated */ if (state->stateptr <= 0) mts_refresh(state); random_value = state->statevec[--state->stateptr]; MT_TEMPER(random_value); return random_value * mt_32_to_double; }/* * Generate a double-precision random number between 0 (inclusive) and 1.0 * (exclusive). This function generates 64 bits of precision. Use * mts_drand for more speed but less precision. */MT_EXTERN MT_INLINE double mts_ldrand( register mt_state* state) /* State for the PRNG */ {#if MT_MACHINE_BITS == 64 unsigned long long final_value; /* Final (integer) value */#endif /* MT_MACHINE_BITS */ register unsigned long random_value_1; /* 1st pseudorandom value generated */ register unsigned long random_value_2; /* 2nd pseudorandom value generated */ /* * For maximum speed, we'll handle the two overflow cases * together. That will save us one test in the common case, at * the expense of an extra one in the overflow case. */ if (--state->stateptr <= 0) { if (state->stateptr < 0) { mts_refresh(state); random_value_1 = state->statevec[--state->stateptr]; } else { random_value_1 = state->statevec[state->stateptr]; mts_refresh(state); } } else random_value_1 = state->statevec[--state->stateptr]; MT_TEMPER(random_value_1); random_value_2 = state->statevec[--state->stateptr]; MT_TEMPER(random_value_2);#if MT_MACHINE_BITS == 64 final_value = ((unsigned long long) random_value_1 << 32) | (unsigned long long) random_value_2; return final_value * mt_64_to_double;#else /* MT_MACHINE_BITS */ return random_value_1 * mt_32_to_double + random_value_2 * mt_64_to_double;#endif /* MT_MACHINE_BITS */ }/* * Generate a random number in the range 0 to 2^32-1, inclusive, working * from the default state vector. * * See mts_lrand for full commentary. */MT_EXTERN MT_INLINE unsigned long mt_lrand() { register unsigned long random_value; /* Pseudorandom value generated */ if (mt_default_state.stateptr <= 0) mts_refresh(&mt_default_state); random_value = mt_default_state.statevec[--mt_default_state.stateptr]; MT_PRE_TEMPER(random_value); return MT_FINAL_TEMPER(random_value); }#ifndef MT_NO_LONGLONG/* * Generate a random number in the range 0 to 2^64-1, inclusive, working * from the default state vector. * * See mts_llrand for full commentary. */MT_EXTERN MT_INLINE unsigned long long mt_llrand() { register unsigned long random_value_1; /* 1st pseudorandom value generated */ register unsigned long random_value_2; /* 2nd pseudorandom value generated */ /* * For maximum speed, we'll handle the two overflow cases * together. That will save us one test in the common case, at * the expense of an extra one in the overflow case. */ if (--mt_default_state.stateptr <= 0) { if (mt_default_state.stateptr < 0) { mts_refresh(&mt_default_state); random_value_1 = mt_default_state.statevec[--mt_default_state.stateptr]; } else { random_value_1 = mt_default_state.statevec[mt_default_state.stateptr]; mts_refresh(&mt_default_state); } } else random_value_1 = mt_default_state.statevec[--mt_default_state.stateptr]; MT_TEMPER(random_value_1); random_value_2 = mt_default_state.statevec[--mt_default_state.stateptr]; MT_PRE_TEMPER(random_value_2); return ((unsigned long long) random_value_1 << 32) | (unsigned long long) MT_FINAL_TEMPER(random_value_2); }#endif /* MT_NO_LONGLONG *//* * Generate a double-precision random number between 0 (inclusive) and 1.0 * (exclusive). This function is optimized for speed, but it only generates * 32 bits of precision. Use mt_ldrand to get 64 bits of precision. */MT_EXTERN MT_INLINE double mt_drand() { register unsigned long random_value; /* Pseudorandom value generated */ if (mt_default_state.stateptr <= 0) mts_refresh(&mt_default_state); random_value = mt_default_state.statevec[--mt_default_state.stateptr]; MT_TEMPER(random_value); return random_value * mt_32_to_double; }/* * Generate a double-precision random number between 0 (inclusive) and 1.0 * (exclusive). This function generates 64 bits of precision. Use * mts_drand for more speed but less precision. */MT_EXTERN MT_INLINE double mt_ldrand(void) {#if MT_MACHINE_BITS == 64 unsigned long long final_value; /* Final (integer) value */#endif /* MT_MACHINE_BITS */ register unsigned long random_value_1; /* 1st pseudorandom value generated */ register unsigned long random_value_2; /* 2nd pseudorandom value generated */ /* * For maximum speed, we'll handle the two overflow cases * together. That will save us one test in the common case, at * the expense of an extra one in the overflow case. */ if (--mt_default_state.stateptr <= 0) { if (mt_default_state.stateptr < 0) { mts_refresh(&mt_default_state); random_value_1 = mt_default_state.statevec[--mt_default_state.stateptr]; } else { random_value_1 = mt_default_state.statevec[mt_default_state.stateptr]; mts_refresh(&mt_default_state); } } else random_value_1 = mt_default_state.statevec[--mt_default_state.stateptr]; MT_TEMPER(random_value_1); random_value_2 = mt_default_state.statevec[--mt_default_state.stateptr]; MT_TEMPER(random_value_2);#if MT_MACHINE_BITS == 64 final_value = ((unsigned long long) random_value_1 << 32) | (unsigned long long) random_value_2; return final_value * mt_64_to_double;#else /* MT_MACHINE_BITS */ return random_value_1 * mt_32_to_double + random_value_2 * mt_64_to_double;#endif /* MT_MACHINE_BITS */ }#endif /* MT_NO_INLINE */#ifdef __cplusplus/* * C++ interface to the Mersenne Twist PRNG. This class simply * provides a more C++-ish way to access the PRNG. Only state-based * functions are provided. All functions are inlined, both for speed * and so that the same implementation code can be used in C and C++. */class mt_prng { public: /* * Constructors and destructors. The default constructor * leaves initialization (seeding) for later unless pickSeed * is true, in which case the seed is chosen based on either * /dev/urandom (if available) or the system time. The other * constructors accept either a 32-bit seed, or a full * 624-long seed. */ mt_prng( // Default constructor bool pickSeed = false) // True to get seed from /dev/urandom // ..or time { state.stateptr = 0; state.initialized = 0; if (pickSeed) mts_seed(&state); } mt_prng(unsigned long seed) // Construct with 32-bit seeding { state.stateptr = 0; state.initialized = 0; mts_seed32(&state, seed); } mt_prng(unsigned long seeds[MT_STATE_SIZE]) // Construct with full seeding { state.stateptr = 0; state.initialized = 0; mts_seedfull(&state, seeds); } ~mt_prng() { } /* * Copy and assignment are best left defaulted. */ /* * PRNG seeding functions. */ void seed32(unsigned long seed) // Set 32-bit random seed { mts_seed32(&state, seed); } void seed32new(unsigned long seed) // Set 32-bit random seed { mts_seed32new(&state, seed); } void seedfull(unsigned long seeds[MT_STATE_SIZE]) // Set complicated random seed { mts_seedfull(&state, seeds); } void seed() // Choose seed from random input { mts_seed(&state); } void goodseed() // Choose better seed from random input { mts_goodseed(&state); } void bestseed() // Choose best seed from random input { mts_bestseed(&state); } friend std::ostream& operator<<(std::ostream& stream, const mt_prng& rng); friend std::istream& operator>>(std::istream& stream, mt_prng& rng); /* * PRNG generation functions */ unsigned long lrand() // Generate 32-bit pseudo-random value { return mts_lrand(&state); }#ifndef MT_NO_LONGLONG unsigned long long llrand() // Generate 64-bit pseudo-random value { return mts_llrand(&state); }#endif /* MT_NO_LONGLONG */ double drand() // Generate fast 32-bit floating value { return mts_drand(&state); } double ldrand() // Generate slow 64-bit floating value { return mts_ldrand(&state); } /* * Following Richard J. Wagner's example, we overload the * function-call operator to return a 32-bit floating value. * That allows the common use of the PRNG to be simplified as * in the following example: * * mt_prng ranno(true); * // ... * coinFlip = ranno() >= 0.5 ? heads : tails; */ double operator()() { return mts_drand(&state); } protected: /* * Protected data */ mt_state state; // Current state of the PRNG };/* * Save state to a stream. See mts_savestate. */MT_INLINE std::ostream& operator<<( std::ostream& stream, // Stream to save to const mt_prng& rng) // PRNG to save { for (int i = MT_STATE_SIZE; --i >= 0; ) { if (!(stream << rng.state.statevec[i] << ' ')) return stream; } return stream << rng.state.stateptr; }/* * Restore state from a stream. See mts_loadstate. */MT_INLINE std::istream& operator>>( std::istream& stream, // Stream to laod from mt_prng& rng) // PRNG to load { rng.state.initialized = rng.state.stateptr = 0; for (int i = MT_STATE_SIZE; --i >= 0; ) { if (!(stream >> rng.state.statevec[i])) return stream; } if (!(stream >> rng.state.stateptr)) { rng.state.stateptr = 0; return stream; } /* * If the state is invalid, all we can do is to make it uninitialized. */ if (rng.state.stateptr < 0 || rng.state.stateptr > MT_STATE_SIZE) { rng.state.stateptr = 0; return stream; } mts_mark_initialized(&rng.state); return stream; }#endif#endif /* MTWIST_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -