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