|
||||
File indexing completed on 2025-01-18 09:55:04
0001 // mersenne.h - written and placed in public domain by Jeffrey Walton. 0002 0003 /// \file mersenne.h 0004 /// \brief Class file for Mersenne Twister 0005 /// \warning MersenneTwister is suitable for Monte-Carlo simulations, where uniformaly distributed 0006 /// numbers are required quickly. It should not be used for cryptographic purposes. 0007 /// \since Crypto++ 5.6.3 0008 #ifndef CRYPTOPP_MERSENNE_TWISTER_H 0009 #define CRYPTOPP_MERSENNE_TWISTER_H 0010 0011 #include "cryptlib.h" 0012 #include "secblock.h" 0013 #include "misc.h" 0014 0015 NAMESPACE_BEGIN(CryptoPP) 0016 0017 /// \brief Mersenne Twister class for Monte-Carlo simulations 0018 /// \tparam K Magic constant 0019 /// \tparam M Period parameter 0020 /// \tparam N Size of the state vector 0021 /// \tparam F Multiplier constant 0022 /// \tparam S Initial seed 0023 /// \details Provides the MersenneTwister implementation. The class is a header-only implementation. 0024 /// \details You should reseed the generator after a fork() to avoid multiple generators 0025 /// with the same internal state. 0026 /// \warning MersenneTwister is suitable for simulations, where uniformaly distributed numbers are 0027 /// required quickly. It should not be used for cryptographic purposes. 0028 /// \sa MT19937, MT19937ar 0029 /// \since Crypto++ 5.6.3 0030 template <unsigned int K, unsigned int M, unsigned int N, unsigned int F, word32 S> 0031 class MersenneTwister : public RandomNumberGenerator 0032 { 0033 public: 0034 CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return (S==5489 ? "MT19937ar" : (S==4537 ? "MT19937" : "MT19937x")); } 0035 0036 ~MersenneTwister() {} 0037 0038 /// \brief Construct a Mersenne Twister 0039 /// \param seed 32-bit seed 0040 /// \details Defaults to template parameter S due to changing algorithm 0041 /// parameters over time 0042 MersenneTwister(word32 seed = S) : m_idx(N) 0043 { 0044 Reset(seed); 0045 } 0046 0047 bool CanIncorporateEntropy() const {return true;} 0048 0049 /// \brief Update RNG state with additional unpredictable values 0050 /// \param input the entropy to add to the generator 0051 /// \param length the size of the input buffer 0052 /// \details MersenneTwister uses the first 32-bits of <tt>input</tt> to reseed the 0053 /// generator. If fewer bytes are provided, then the seed is padded with 0's. 0054 void IncorporateEntropy(const byte *input, size_t length) 0055 { 0056 // Handle word32 size blocks 0057 FixedSizeSecBlock<word32, 1> temp; 0058 temp[0] = 0; 0059 0060 if (length > 4) 0061 length = 4; 0062 0063 for (size_t i=0; i<length; ++i) 0064 { 0065 temp[0] <<= 8; 0066 temp[0] = temp[0] | input[i]; 0067 } 0068 0069 Reset(temp[0]); 0070 } 0071 0072 /// \brief Generate random array of bytes 0073 /// \param output byte buffer 0074 /// \param size length of the buffer, in bytes 0075 /// \details Bytes are written to output in big endian order. If output length 0076 /// is not a multiple of word32, then unused bytes are not accumulated for subsequent 0077 /// calls to GenerateBlock. Rather, the unused tail bytes are discarded, and the 0078 /// stream is continued at the next word32 boundary from the state array. 0079 void GenerateBlock(byte *output, size_t size) 0080 { 0081 // Handle word32 size blocks 0082 FixedSizeSecBlock<word32, 1> temp; 0083 for (size_t i=0; i < size/4; i++, output += 4) 0084 { 0085 temp[0] = NextMersenneWord(); 0086 std::memcpy(output, temp+0, 4); 0087 } 0088 0089 // No tail bytes 0090 if (size%4 == 0) 0091 return; 0092 0093 // Handle tail bytes 0094 temp[0] = NextMersenneWord(); 0095 switch (size%4) 0096 { 0097 case 3: output[2] = CRYPTOPP_GET_BYTE_AS_BYTE(temp[0], 1); /* fall through */ 0098 case 2: output[1] = CRYPTOPP_GET_BYTE_AS_BYTE(temp[0], 2); /* fall through */ 0099 case 1: output[0] = CRYPTOPP_GET_BYTE_AS_BYTE(temp[0], 3); break; 0100 0101 default: CRYPTOPP_ASSERT(0);; 0102 } 0103 } 0104 0105 /// \brief Generate a random 32-bit word in the range min to max, inclusive 0106 /// \return random 32-bit word in the range min to max, inclusive 0107 /// \details If the 32-bit candidate is not within the range, then it is discarded 0108 /// and a new candidate is used. 0109 word32 GenerateWord32(word32 min=0, word32 max=0xffffffffL) 0110 { 0111 const word32 range = max-min; 0112 if (range == 0xffffffffL) 0113 return NextMersenneWord(); 0114 0115 const int maxBits = BitPrecision(range); 0116 word32 value; 0117 0118 do{ 0119 value = Crop(NextMersenneWord(), maxBits); 0120 } while (value > range); 0121 0122 return value+min; 0123 } 0124 0125 /// \brief Generate and discard n bytes 0126 /// \param n the number of bytes to discard, rounded up to a <tt>word32</tt> size 0127 /// \details If n is not a multiple of <tt>word32</tt>, then unused bytes are 0128 /// not accumulated for subsequent calls to GenerateBlock. Rather, the unused 0129 /// tail bytes are discarded, and the stream is continued at the next 0130 /// <tt>word32</tt> boundary from the state array. 0131 void DiscardBytes(size_t n) 0132 { 0133 for(size_t i=0; i < RoundUpToMultipleOf(n, 4U); i++) 0134 NextMersenneWord(); 0135 } 0136 0137 protected: 0138 0139 void Reset(word32 seed) 0140 { 0141 m_idx = N; 0142 0143 m_state[0] = seed; 0144 for (unsigned int i = 1; i < N+1; i++) 0145 m_state[i] = word32(F * (m_state[i-1] ^ (m_state[i-1] >> 30)) + i); 0146 } 0147 0148 /// \brief Returns the next 32-bit word from the state array 0149 /// \return the next 32-bit word from the state array 0150 /// \details fetches the next word frm the state array, performs bit operations on 0151 /// it, and then returns the value to the caller. 0152 word32 NextMersenneWord() 0153 { 0154 if (m_idx >= N) { Twist(); } 0155 0156 word32 temp = m_state[m_idx++]; 0157 0158 temp ^= (temp >> 11); 0159 temp ^= (temp << 7) & 0x9D2C5680; // 0x9D2C5680 (2636928640) 0160 temp ^= (temp << 15) & 0xEFC60000; // 0xEFC60000 (4022730752) 0161 0162 return temp ^ (temp >> 18); 0163 } 0164 0165 /// \brief Performs the twist operation on the state array 0166 void Twist() 0167 { 0168 static const word32 magic[2]={0x0UL, K}; 0169 word32 kk, temp; 0170 0171 CRYPTOPP_ASSERT(N >= M); 0172 for (kk=0;kk<N-M;kk++) 0173 { 0174 temp = (m_state[kk] & 0x80000000)|(m_state[kk+1] & 0x7FFFFFFF); 0175 m_state[kk] = m_state[kk+M] ^ (temp >> 1) ^ magic[temp & 0x1UL]; 0176 } 0177 0178 for (;kk<N-1;kk++) 0179 { 0180 temp = (m_state[kk] & 0x80000000)|(m_state[kk+1] & 0x7FFFFFFF); 0181 m_state[kk] = m_state[kk+(M-N)] ^ (temp >> 1) ^ magic[temp & 0x1UL]; 0182 } 0183 0184 temp = (m_state[N-1] & 0x80000000)|(m_state[0] & 0x7FFFFFFF); 0185 m_state[N-1] = m_state[M-1] ^ (temp >> 1) ^ magic[temp & 0x1UL]; 0186 0187 // Reset index 0188 m_idx = 0; 0189 0190 // Wipe temp 0191 SecureWipeArray(&temp, 1); 0192 } 0193 0194 private: 0195 0196 /// \brief 32-bit word state array of size N 0197 FixedSizeSecBlock<word32, N+1> m_state; 0198 /// \brief the current index into the state array 0199 word32 m_idx; 0200 }; 0201 0202 /// \brief Original MT19937 generator provided in the ACM paper. 0203 /// \details MT19937 uses 4537 as default initial seed. 0204 /// \details You should reseed the generator after a fork() to avoid multiple generators 0205 /// with the same internal state. 0206 /// \sa MT19937ar, <A HREF="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">Mersenne twister: 0207 /// a 623-dimensionally equidistributed uniform pseudo-random number generator</A> 0208 /// \since Crypto++ 5.6.3 0209 #if CRYPTOPP_DOXYGEN_PROCESSING 0210 class MT19937 : public MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x10DCD /*69069*/, 4537> {}; 0211 #else 0212 typedef MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x10DCD /*69069*/, 4537> MT19937; 0213 #endif 0214 0215 /// \brief Updated MT19937 generator adapted to provide an array for initialization. 0216 /// \details MT19937 uses 5489 as default initial seed. Use this generator when interoperating with C++11's 0217 /// mt19937 class. 0218 /// \details You should reseed the generator after a fork() to avoid multiple generators 0219 /// with the same internal state. 0220 /// \sa MT19937, <A HREF="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html">Mersenne Twister 0221 /// with improved initialization</A> 0222 /// \since Crypto++ 5.6.3 0223 #if CRYPTOPP_DOXYGEN_PROCESSING 0224 class MT19937ar : public MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x6C078965 /*1812433253*/, 5489> {}; 0225 #else 0226 typedef MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x6C078965 /*1812433253*/, 5489> MT19937ar; 0227 #endif 0228 0229 NAMESPACE_END 0230 0231 #endif // CRYPTOPP_MERSENNE_TWISTER_H
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |