Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 244 | chris | 1 | /* |
| 2 | Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, |
||
| 3 | All rights reserved. |
||
| 4 | |||
| 5 | Redistribution and use in source and binary forms, with or without |
||
| 6 | modification, are permitted provided that the following conditions |
||
| 7 | are met: |
||
| 8 | |||
| 9 | 1. Redistributions of source code must retain the above copyright |
||
| 10 | notice, this list of conditions and the following disclaimer. |
||
| 11 | |||
| 12 | 2. Redistributions in binary form must reproduce the above copyright |
||
| 13 | notice, this list of conditions and the following disclaimer in the |
||
| 14 | documentation and/or other materials provided with the distribution. |
||
| 15 | |||
| 16 | 3. The names of its contributors may not be used to endorse or promote |
||
| 17 | products derived from this software without specific prior written |
||
| 18 | permission. |
||
| 19 | |||
| 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
| 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
| 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
| 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||
| 24 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||
| 25 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||
| 26 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||
| 27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||
| 28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||
| 29 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
| 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
| 31 | |||
| 32 | |||
| 33 | Any feedback is very welcome. |
||
| 34 | http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html |
||
| 35 | email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) |
||
| 36 | */ |
||
| 37 | |||
| 38 | #include <windows.h> |
||
| 39 | #include "MTRand.h" |
||
| 40 | #include "Debug.h" |
||
| 41 | #include <stdio.h> |
||
| 42 | |||
| 43 | using namespace Sexy; |
||
| 44 | |||
| 45 | /* Period parameters */ |
||
| 46 | #define MTRAND_M 397 |
||
| 47 | #define MATRIX_A 0x9908b0dfUL /* constant vector a */ |
||
| 48 | #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ |
||
| 49 | #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ |
||
| 50 | |||
| 51 | /* Tempering parameters */ |
||
| 52 | #define TEMPERING_MASK_B 0x9d2c5680 |
||
| 53 | #define TEMPERING_MASK_C 0xefc60000 |
||
| 54 | #define TEMPERING_SHIFT_U(y) (y >> 11) |
||
| 55 | #define TEMPERING_SHIFT_S(y) (y << 7) |
||
| 56 | #define TEMPERING_SHIFT_T(y) (y << 15) |
||
| 57 | #define TEMPERING_SHIFT_L(y) (y >> 18) |
||
| 58 | |||
| 59 | |||
| 60 | MTRand::MTRand(const std::string& theSerialData) |
||
| 61 | { |
||
| 62 | SRand(theSerialData); |
||
| 63 | mti=MTRAND_N+1; /* mti==MTRAND_N+1 means mt[MTRAND_N] is not initialized */ |
||
| 64 | } |
||
| 65 | |||
| 66 | MTRand::MTRand(unsigned long seed) |
||
| 67 | { |
||
| 68 | SRand(seed); |
||
| 69 | } |
||
| 70 | |||
| 71 | MTRand::MTRand() |
||
| 72 | { |
||
| 73 | SRand(4357); |
||
| 74 | } |
||
| 75 | |||
| 76 | static int gRandAllowed = 0; |
||
| 77 | void MTRand::SetRandAllowed(bool allowed) |
||
| 78 | { |
||
| 79 | if (allowed) |
||
| 80 | { |
||
| 81 | if (gRandAllowed>0) |
||
| 82 | gRandAllowed--; |
||
| 83 | else |
||
| 84 | DBG_ASSERT(false); // mismatched calls |
||
| 85 | } |
||
| 86 | else |
||
| 87 | gRandAllowed++; |
||
| 88 | } |
||
| 89 | |||
| 90 | void MTRand::SRand(const std::string& theSerialData) |
||
| 91 | { |
||
| 92 | if (theSerialData.size() == MTRAND_N*4) |
||
| 93 | { |
||
| 94 | memcpy(mt, theSerialData.c_str(), MTRAND_N*4); |
||
| 95 | } |
||
| 96 | else |
||
| 97 | SRand(4357); |
||
| 98 | } |
||
| 99 | |||
| 100 | void MTRand::SRand(unsigned long seed) |
||
| 101 | { |
||
| 102 | if (seed == 0) |
||
| 103 | seed = 4357; |
||
| 104 | |||
| 105 | /* setting initial seeds to mt[MTRAND_N] using */ |
||
| 106 | /* the generator Line 25 of Table 1 in */ |
||
| 107 | /* [KNUTH 1981, The Art of Computer Programming */ |
||
| 108 | /* Vol. 2 (2nd Ed.), pp102] */ |
||
| 109 | mt[0]= seed & 0xffffffffUL; |
||
| 110 | for (mti=1; mti< MTRAND_N; mti++) |
||
| 111 | { |
||
| 112 | mt[mti] = |
||
| 113 | (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); |
||
| 114 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ |
||
| 115 | /* In the previous versions, MSBs of the seed affect */ |
||
| 116 | /* only MSBs of the array mt[]. */ |
||
| 117 | /* 2002/01/09 modified by Makoto Matsumoto */ |
||
| 118 | mt[mti] &= 0xffffffffUL; |
||
| 119 | /* for >32 bit machines */ |
||
| 120 | } |
||
| 121 | } |
||
| 122 | |||
| 123 | unsigned long MTRand::Next() |
||
| 124 | { |
||
| 125 | DBG_ASSERT(gRandAllowed==0); |
||
| 126 | return NextNoAssert(); |
||
| 127 | } |
||
| 128 | |||
| 129 | unsigned long MTRand::NextNoAssert() |
||
| 130 | { |
||
| 131 | unsigned long y; |
||
| 132 | static unsigned long mag01[2]={0x0, MATRIX_A}; |
||
| 133 | /* mag01[x] = x * MATRIX_A for x=0,1 */ |
||
| 134 | |||
| 135 | if (mti >= MTRAND_N) { /* generate MTRAND_N words at one time */ |
||
| 136 | int kk; |
||
| 137 | |||
| 138 | for (kk=0;kk<MTRAND_N-MTRAND_M;kk++) { |
||
| 139 | y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); |
||
| 140 | mt[kk] = mt[kk+MTRAND_M] ^ (y >> 1) ^ mag01[y & 0x1UL]; |
||
| 141 | } |
||
| 142 | for (;kk<MTRAND_N-1;kk++) { |
||
| 143 | y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); |
||
| 144 | mt[kk] = mt[kk+(MTRAND_M-MTRAND_N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; |
||
| 145 | } |
||
| 146 | y = (mt[MTRAND_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); |
||
| 147 | mt[MTRAND_N-1] = mt[MTRAND_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; |
||
| 148 | |||
| 149 | mti = 0; |
||
| 150 | } |
||
| 151 | |||
| 152 | y = mt[mti++]; |
||
| 153 | y ^= TEMPERING_SHIFT_U(y); |
||
| 154 | y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; |
||
| 155 | y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; |
||
| 156 | y ^= TEMPERING_SHIFT_L(y); |
||
| 157 | |||
| 158 | y &= 0x7FFFFFFF; |
||
| 159 | |||
| 160 | /*char aStr[256]; |
||
| 161 | sprintf(aStr, "Rand=%d\r\n", y); |
||
| 162 | OutputDebugString(aStr);*/ |
||
| 163 | |||
| 164 | return y; |
||
| 165 | } |
||
| 166 | |||
| 167 | unsigned long MTRand::NextNoAssert(unsigned long range) |
||
| 168 | { |
||
| 169 | return NextNoAssert() % range; |
||
| 170 | } |
||
| 171 | |||
| 172 | unsigned long MTRand::Next(unsigned long range) |
||
| 173 | { |
||
| 174 | DBG_ASSERT(gRandAllowed==0); |
||
| 175 | return NextNoAssert( range ); |
||
| 176 | } |
||
| 177 | |||
| 178 | float MTRand::NextNoAssert(float range) |
||
| 179 | { |
||
| 180 | return (float) ((double)NextNoAssert() / (double)0x7FFFFFFF * range); |
||
| 181 | } |
||
| 182 | |||
| 183 | float MTRand::Next(float range) |
||
| 184 | { |
||
| 185 | DBG_ASSERT(gRandAllowed==0); |
||
| 186 | return NextNoAssert(range); |
||
| 187 | } |
||
| 188 | |||
| 189 | std::string MTRand::Serialize() |
||
| 190 | { |
||
| 191 | std::string aString; |
||
| 192 | |||
| 193 | aString.resize(MTRAND_N*4); |
||
| 194 | memcpy((char*) aString.c_str(), mt, MTRAND_N*4); |
||
| 195 | |||
| 196 | return aString; |
||
| 197 | } |