00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "randomc.h"
00019
00020 void CRandomMersenne::Init0(uint32 seed) {
00021
00022 union {double f; uint32 i[2];} convert;
00023 convert.f = 1.0;
00024 if (convert.i[1] == 0x3FF00000) Architecture = LITTLE_ENDIAN1;
00025 else if (convert.i[0] == 0x3FF00000) Architecture = BIG_ENDIAN1;
00026 else Architecture = NONIEEE;
00027
00028
00029 mt[0]= seed;
00030 for (mti=1; mti < MERS_N; mti++) {
00031 mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
00032 }
00033 }
00034
00035 void CRandomMersenne::RandomInit(uint32 seed) {
00036
00037 Init0(seed);
00038
00039
00040 for (int i = 0; i < 37; i++) BRandom();
00041 }
00042
00043
00044 void CRandomMersenne::RandomInitByArray(uint32 seeds[], int length) {
00045
00046 int i, j, k;
00047
00048
00049 Init0(19650218);
00050
00051 if (length <= 0) return;
00052
00053
00054 i = 1; j = 0;
00055 k = (MERS_N > length ? MERS_N : length);
00056 for (; k; k--) {
00057 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + seeds[j] + j;
00058 i++; j++;
00059 if (i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;}
00060 if (j >= length) j=0;}
00061 for (k = MERS_N-1; k; k--) {
00062 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i;
00063 if (++i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;}}
00064 mt[0] = 0x80000000UL;
00065
00066
00067 mti = 0;
00068 for (int i = 0; i <= MERS_N; i++) BRandom();
00069 }
00070
00071
00072 uint32 CRandomMersenne::BRandom() {
00073
00074 uint32 y;
00075
00076 if (mti >= MERS_N) {
00077
00078 const uint32 LOWER_MASK = (1LU << MERS_R) - 1;
00079 const uint32 UPPER_MASK = 0xFFFFFFFF << MERS_R;
00080 static const uint32 mag01[2] = {0, MERS_A};
00081
00082 int kk;
00083 for (kk=0; kk < MERS_N-MERS_M; kk++) {
00084 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
00085 mt[kk] = mt[kk+MERS_M] ^ (y >> 1) ^ mag01[y & 1];}
00086
00087 for (; kk < MERS_N-1; kk++) {
00088 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
00089 mt[kk] = mt[kk+(MERS_M-MERS_N)] ^ (y >> 1) ^ mag01[y & 1];}
00090
00091 y = (mt[MERS_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
00092 mt[MERS_N-1] = mt[MERS_M-1] ^ (y >> 1) ^ mag01[y & 1];
00093 mti = 0;
00094 }
00095
00096 y = mt[mti++];
00097
00098 #if 1
00099
00100 y ^= y >> MERS_U;
00101 y ^= (y << MERS_S) & MERS_B;
00102 y ^= (y << MERS_T) & MERS_C;
00103 y ^= y >> MERS_L;
00104 #endif
00105
00106 return y;
00107 }
00108
00109
00110 double CRandomMersenne::Random() {
00111
00112 union {double f; uint32 i[2];} convert;
00113 uint32 r = BRandom();
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 #if defined(_M_IX86) || defined(_M_X64) || defined(__LITTLE_ENDIAN__)
00125 Architecture = LITTLE_ENDIAN1;
00126 #elif defined(__BIG_ENDIAN__)
00127 Architecture = BIG_ENDIAN1;
00128 #endif
00129
00130 switch (Architecture) {
00131 case LITTLE_ENDIAN1:
00132 convert.i[0] = r << 20;
00133 convert.i[1] = (r >> 12) | 0x3FF00000;
00134 return convert.f - 1.0;
00135 case BIG_ENDIAN1:
00136 convert.i[1] = r << 20;
00137 convert.i[0] = (r >> 12) | 0x3FF00000;
00138 return convert.f - 1.0;
00139 case NONIEEE: default: ;
00140 }
00141
00142
00143 return (double)r * (1./((double)(uint32)(-1L)+1.));
00144 }
00145
00146
00147 int CRandomMersenne::IRandom(int min, int max) {
00148
00149
00150 if (max <= min) {
00151 if (max == min) return min; else return 0x80000000;
00152 }
00153
00154 int r = int((max - min + 1) * Random()) + min;
00155 if (r > max) r = max;
00156 return r;
00157 }
00158
00159
00160 int CRandomMersenne::IRandomX(int min, int max) {
00161
00162
00163
00164
00165 if (max <= min) {
00166 if (max == min) return min; else return 0x80000000;
00167 }
00168 #ifdef INT64_DEFINED
00169
00170 uint32 interval;
00171 uint64 longran;
00172 uint32 iran;
00173 uint32 remainder;
00174
00175 interval = uint32(max - min + 1);
00176 if (interval != LastInterval) {
00177
00178
00179
00180 RLimit = uint32(((uint64)1 << 32) / interval) * interval - 1;
00181 LastInterval = interval;
00182 }
00183 do {
00184 longran = (uint64)BRandom() * interval;
00185 iran = (uint32)(longran >> 32);
00186 remainder = (uint32)longran;
00187 } while (remainder > RLimit);
00188
00189 return (int32)iran + min;
00190
00191 #else
00192
00193 uint32 interval;
00194 uint32 bran;
00195 uint32 iran;
00196 uint32 remainder;
00197
00198 interval = uint32(max - min + 1);
00199 if (interval != LastInterval) {
00200
00201
00202
00203 RLimit = (uint32)0xFFFFFFFF / interval;
00204 if ((uint32)0xFFFFFFFF % interval == interval - 1) RLimit++;
00205 }
00206 do {
00207 bran = BRandom();
00208 iran = bran / interval;
00209 remainder = bran % interval;
00210 } while (iran >= RLimit);
00211
00212 return (int32)remainder + min;
00213
00214 #endif
00215 }