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
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include "RandomLib/Random.hpp"
00062
00063 #include <fstream>
00064 #include <ctime>
00065 #include <sstream>
00066 #include <iomanip>
00067 #if !WINDOWS
00068 #include <sys/time.h>
00069 #include <unistd.h>
00070 #else
00071 #include <windows.h>
00072 #include <winbase.h>
00073 #include <process.h>
00074 #define getpid _getpid
00075 #define gmtime_r(t,g) gmtime_s(g,t)
00076 #endif
00077
00078 #if WINDOWS || defined(__CYGWIN__)
00079 #define strtoull strtoul
00080 #endif
00081
00082 #define RANDOM_CPP "$Id: Random.cpp 6489 2008-11-10 21:37:47Z ckarney $"
00083
00084 RCSID_DECL(RANDOM_CPP);
00085 RCSID_DECL(RANDOMTYPE_HPP);
00086 RCSID_DECL(RANDOMSEED_HPP);
00087 RCSID_DECL(RANDOMENGINE_HPP);
00088 RCSID_DECL(RANDOMMIXER_HPP);
00089 RCSID_DECL(RANDOMALGORITHM_HPP);
00090 RCSID_DECL(RANDOMPOWER2_HPP);
00091 RCSID_DECL(RANDOMCANONICAL_HPP);
00092
00093 namespace RandomLib {
00094
00095
00096
00097 template<>
00098 void Random_u32::Write32(std::ostream& os, bool bin, int& cnt,
00099 Random_u32::type x)
00100 throw(std::ios::failure) {
00101 if (bin) {
00102 unsigned char buf[4];
00103
00104 buf[3] = (unsigned char)(x);
00105 buf[2] = (unsigned char)(x >>= 8);
00106 buf[1] = (unsigned char)(x >>= 8);
00107 buf[0] = (unsigned char)(x >>= 8);
00108 os.write(reinterpret_cast<const char *>(buf), 4);
00109 } else {
00110 const int longsperline = 72/9;
00111
00112
00113 std::ostringstream str;
00114
00115 if (cnt > 0)
00116
00117 str << (cnt % longsperline ? ' ' : '\n');
00118 str << std::hex << x;
00119 os << str.str();
00120 ++cnt;
00121 }
00122 }
00123
00124 template<>
00125 void Random_u32::Read32(std::istream& is, bool bin, Random_u32::type& x)
00126 throw(std::ios::failure) {
00127 if (bin) {
00128 unsigned char buf[4];
00129 is.read(reinterpret_cast<char *>(buf), 4);
00130
00131 x = Random_u32::type(buf[0]) << 24 | Random_u32::type(buf[1]) << 16 |
00132 Random_u32::type(buf[2]) << 8 | Random_u32::type(buf[3]);
00133 } else {
00134 std::string s;
00135 is >> std::ws >> s;
00136
00137
00138 std::istringstream str(s);
00139 str >> std::hex >> x;
00140 }
00141 x &= Random_u32::mask;
00142 }
00143
00144 template<>
00145 void Random_u64::Write32(std::ostream& os, bool bin, int& cnt,
00146 Random_u64::type x)
00147 throw(std::ios::failure) {
00148 Random_u32::Write32(os, bin, cnt, Random_u32::cast(x >> 32));
00149 Random_u32::Write32(os, bin, cnt, Random_u32::cast(x ));
00150 }
00151
00152 template<>
00153 void Random_u64::Read32(std::istream& is, bool bin, Random_u64::type& x)
00154 throw(std::ios::failure) {
00155 Random_u32::type t;
00156 Random_u32::Read32(is, bin, t);
00157 x = Random_u64::type(t) << 32;
00158 Random_u32::Read32(is, bin, t);
00159 x |= Random_u64::type(t);
00160 }
00161
00162
00163
00164 RandomSeed::seed_type RandomSeed::SeedWord() {
00165
00166
00167 STATIC_ASSERT(std::numeric_limits<seed_type>::radix == 2 &&
00168 !std::numeric_limits<seed_type>::is_signed &&
00169 std::numeric_limits<seed_type>::digits >= 32,
00170 "seed_type is a bad type");
00171 u32::type t = 0;
00172
00173
00174 {
00175 std::ifstream f("/dev/urandom", std::ios::binary | std::ios::in);
00176 if (f.good()) {
00177
00178 f.read(reinterpret_cast<char *>(&t), sizeof(t));
00179 }
00180 }
00181 std::vector<seed_type> v = SeedVector();
00182 for (size_t i = v.size(); i--;)
00183 u32::CheckSum(v[i], t);
00184 return seed_t::cast(t);
00185 }
00186
00187 std::vector<RandomSeed::seed_type> RandomSeed::SeedVector() {
00188 std::vector<seed_type> v;
00189 {
00190
00191 #if !WINDOWS
00192 timeval tv;
00193 if (gettimeofday(&tv, 0) == 0)
00194 v.push_back(seed_t::cast(tv.tv_usec));
00195 #else
00196 LARGE_INTEGER taux;
00197 if (QueryPerformanceCounter((LARGE_INTEGER *)&taux)) {
00198 v.push_back(seed_t::cast(taux.LowPart));
00199 v.push_back(seed_t::cast(taux.HighPart));
00200 }
00201 #endif
00202 }
00203
00204 const time_t tim = std::time(0);
00205 v.push_back(seed_t::cast(seed_type(tim)));
00206
00207 v.push_back(seed_t::cast(getpid()));
00208 #if !WINDOWS
00209
00210 v.push_back(seed_t::cast(gethostid()));
00211 #endif
00212 {
00213
00214 tm gt;
00215 gmtime_r(&tim, >);
00216 v.push_back((seed_type(1900) + seed_t::cast(gt.tm_year)));
00217 }
00218 std::transform(v.begin(), v.end(), v.begin(), seed_t::cast<seed_type>);
00219 return v;
00220 }
00221
00222 std::vector<RandomSeed::seed_type>
00223 RandomSeed::StringToVector(const std::string& s)
00224 throw(std::bad_alloc) {
00225 std::vector<seed_type> v(0);
00226 const char* c = s.c_str();
00227 char* q;
00228 std::string::size_type p = 0;
00229 while (true) {
00230 p = s.find_first_of("0123456789", p);
00231 if (p == std::string::npos)
00232 break;
00233 v.push_back(seed_t::cast(std::strtoull(c + p, &q, 0)));
00234 p = q - c;
00235 }
00236 return v;
00237 }
00238
00239
00240
00241 template<class Algorithm, class Mixer>
00242 void RandomEngine<Algorithm, Mixer>::Init() throw() {
00243
00244
00245 STATIC_ASSERT(std::numeric_limits<typename mixer_t::type>::radix == 2 &&
00246 !std::numeric_limits<typename mixer_t::type>::is_signed &&
00247 std::numeric_limits<typename mixer_t::type>::digits >=
00248 int(mixer_t::width),
00249 "mixer_type is a bad type");
00250
00251 STATIC_ASSERT(std::numeric_limits<result_type>::radix == 2 &&
00252 !std::numeric_limits<result_type>::is_signed &&
00253 std::numeric_limits<result_type>::digits >= width,
00254 "engine_type is a bad type");
00255
00256 STATIC_ASSERT(mixer_t::width == 32 || mixer_t::width == 64,
00257 "Mixer width must be 32 or 64");
00258
00259 STATIC_ASSERT(width == 32 || width == 64,
00260 "Algorithm width must be 32 or 64");
00261
00262
00263 STATIC_ASSERT(!(mixer_t::width == width) ||
00264 sizeof(_stateu) == sizeof(_state),
00265 "Same bit-widths but different storage");
00266
00267
00268
00269 STATIC_ASSERT(!(mixer_t::width < width) ||
00270 sizeof(_stateu) >= sizeof(_state),
00271 "Narrow data type uses less storage");
00272
00273 STATIC_ASSERT(!(mixer_t::width > width) ||
00274 sizeof(_stateu) <= sizeof(_state),
00275 "Narrow data type uses less storage");
00276
00277
00278
00279 STATIC_ASSERT(sizeof(_statev) == sizeof(_state),
00280 "Storage mismatch with internal engine data type");
00281
00282
00283 Mixer::SeedToState(_seed, _stateu, NU);
00284
00285
00286 if (mixer_t::width < width) {
00287 for (size_t i = 0; i < N; ++i)
00288
00289 _state[i] = result_type(_stateu[2*i]) |
00290 result_type(_stateu[2*i + 1]) <<
00291 (mixer_t::width < width ? mixer_t::width : 0);
00292 } else if (mixer_t::width > width) {
00293 for (size_t i = N; i--;)
00294
00295 _state[i] = result_t::cast(_stateu[i>>1] >> width * (i&1u));
00296 }
00297
00298 Algorithm::NormalizeState(_state);
00299
00300 _rounds = -1;
00301 _ptr = N;
00302 }
00303
00304 template<class Algorithm, class Mixer> Random_u32::type
00305 RandomEngine<Algorithm, Mixer>::Check(u64::type v, u32::type e,
00306 u32::type m) const
00307 throw(std::out_of_range) {
00308 if (v != version)
00309 throw std::out_of_range(Name() + ": Unknown version");
00310 if (e != Algorithm::version)
00311 throw std::out_of_range(Name() + ": Algorithm mismatch");
00312 if (m != Mixer::version)
00313 throw std::out_of_range(Name() + ": Mixer mismatch");
00314 u32::type check = 0;
00315 u64::CheckSum(v, check);
00316 u32::CheckSum(e, check);
00317 u32::CheckSum(m, check);
00318 u32::CheckSum(u32::type(_seed.size()), check);
00319 for (std::vector<seed_type>::const_iterator n = _seed.begin();
00320 n != _seed.end(); ++n) {
00321 if (*n != seed_t::cast(*n))
00322 throw std::out_of_range(Name() + ": Illegal seed value");
00323 u32::CheckSum(u32::type(*n), check);
00324 }
00325 u32::CheckSum(_ptr, check);
00326 if (_stride == 0 || _stride > UNINIT/2)
00327 throw std::out_of_range(Name() + ": Invalid stride");
00328 u32::CheckSum(_stride, check);
00329 if (_ptr != UNINIT) {
00330 if (_ptr >= N + _stride)
00331 throw std::out_of_range(Name() + ": Invalid pointer");
00332 u64::CheckSum(_rounds, check);
00333 Algorithm::CheckState(_state, check);
00334 }
00335 return check;
00336 }
00337
00338 template<typename Algorithm, typename Mixer>
00339 RandomEngine<Algorithm, Mixer>::RandomEngine(std::istream& is, bool bin)
00340 throw(std::ios::failure, std::out_of_range, std::bad_alloc) {
00341 u64::type versionr;
00342 u32::type versione, versionm, t;
00343 u64::Read32(is, bin, versionr);
00344 u32::Read32(is, bin, versione);
00345 u32::Read32(is, bin, versionm);
00346 u32::Read32(is, bin, t);
00347 _seed.resize(size_t(t));
00348 for (std::vector<seed_type>::iterator n = _seed.begin();
00349 n != _seed.end(); ++n) {
00350 u32::Read32(is, bin, t);
00351 *n = seed_type(t);
00352 }
00353 u32::Read32(is, bin, t);
00354
00355 _ptr = unsigned(t);
00356 u32::Read32(is, bin, t);
00357 _stride = unsigned(t);
00358 if (_ptr != UNINIT) {
00359 u64::type p;
00360 u64::Read32(is, bin, p);
00361 _rounds = (long long)(p);
00362
00363 _rounds <<= 63 - std::numeric_limits<long long>::digits;
00364 _rounds >>= 63 - std::numeric_limits<long long>::digits;
00365 for (unsigned i = 0; i < N; ++i)
00366 result_t::Read32(is, bin, _state[i]);
00367 }
00368 u32::Read32(is, bin, t);
00369 if (t != Check(versionr, versione, versionm))
00370 throw std::out_of_range(Name() + ": Checksum failure");
00371 }
00372
00373 template<typename Algorithm, typename Mixer>
00374 void RandomEngine<Algorithm, Mixer>::Save(std::ostream& os,
00375 bool bin) const
00376 throw(std::ios::failure) {
00377 u32::type check = Check(version, Algorithm::version, Mixer::version);
00378 int c = 0;
00379 u64::Write32(os, bin, c, version);
00380 u32::Write32(os, bin, c, Algorithm::version);
00381 u32::Write32(os, bin, c, Mixer::version);
00382 u32::Write32(os, bin, c, u32::type(_seed.size()));
00383 for (std::vector<seed_type>::const_iterator n = _seed.begin();
00384 n != _seed.end(); ++n)
00385 u32::Write32(os, bin, c, u32::type(*n));
00386 u32::Write32(os, bin, c, _ptr);
00387 u32::Write32(os, bin, c, _stride);
00388 if (_ptr != UNINIT) {
00389 u64::Write32(os, bin, c, u64::type(_rounds));
00390 for (unsigned i = 0; i < N; ++i)
00391 result_t::Write32(os, bin, c, _state[i]);
00392 }
00393 u32::Write32(os, bin, c, check);
00394 }
00395
00396 template<typename Algorithm, typename Mixer>
00397 void RandomEngine<Algorithm, Mixer>::StepCount(long long n) throw() {
00398
00399 if (_ptr == UNINIT)
00400 Init();
00401 const long long ncount = n + Count();
00402 long long nrounds = ncount / N;
00403 int nptr = int(ncount - nrounds * N);
00404
00405
00406
00407 if (nptr < 0) {
00408 --nrounds;
00409 nptr += N;
00410 } else if (nptr == 0 && nrounds > _rounds) {
00411 nptr = N;
00412 --nrounds;
00413 }
00414 if (nrounds != _rounds)
00415 Algorithm::Transition(nrounds - _rounds, _statev);
00416 _rounds = nrounds;
00417 _ptr = nptr;
00418 }
00419
00420 template<typename Algorithm, typename Mixer>
00421 void RandomEngine<Algorithm, Mixer>::SelfTest() {
00422 RandomEngine g(std::vector<seed_type>(0));
00423 g.SetCount(10000-1);
00424 result_type x = g();
00425 if (SelfTestResult(0) && x != SelfTestResult(1))
00426 throw std::out_of_range(Name() + ": Incorrect result with seed " +
00427 g.SeedString());
00428 seed_type s[] = {0x1234U, 0x5678U, 0x9abcU, 0xdef0U};
00429
00430 g.Reseed(s, s+4);
00431 g.StepCount(-20000);
00432 std::string save;
00433 {
00434 std::ostringstream stream;
00435 stream << g << std::endl;
00436 save = stream.str();
00437 }
00438 g.Reset();
00439 {
00440 std::istringstream stream(save);
00441 stream >> g;
00442 }
00443 g.SetCount(10000);
00444 {
00445 std::ostringstream stream;
00446 g.Save(stream, true);
00447 save = stream.str();
00448 }
00449 {
00450 std::istringstream stream(save);
00451 RandomEngine h(std::vector<seed_type>(0));
00452 h.Load(stream, true);
00453 h.SetCount(1000000-1);
00454 x = h();
00455 if (SelfTestResult(0) && x != SelfTestResult(2))
00456 throw std::out_of_range(Name() + ": Incorrect result with seed " +
00457 h.SeedString());
00458 g.SetCount(1000000);
00459 if (h != g)
00460 throw std::out_of_range(Name() + ": Comparison failure");
00461 }
00462 }
00463
00464 template<> Random_u32::type
00465 RandomEngine<MT19937<Random_u32>, MixerMT0<Random_u32> >::
00466 SelfTestResult(unsigned i)
00467 throw() {
00468 return i == 0 ? 1 :
00469 i == 1 ? 4123659995UL : 3016432305UL;
00470 }
00471
00472 template<> Random_u64::type
00473 RandomEngine<MT19937<Random_u64>, MixerMT0<Random_u64> >::
00474 SelfTestResult(unsigned i)
00475 throw() {
00476 return i == 0 ? 1 :
00477 i == 1 ? 9981545732273789042ULL : 1384037754719008581ULL;
00478 }
00479
00480 template<> Random_u32::type
00481 RandomEngine<MT19937<Random_u32>, MixerMT1<Random_u32> >::
00482 SelfTestResult(unsigned i)
00483 throw() {
00484 return i == 0 ? 1 :
00485 i == 1 ? 4123659995UL : 2924523180UL;
00486 }
00487
00488 template<> Random_u64::type
00489 RandomEngine<MT19937<Random_u64>, MixerMT1<Random_u64> >::
00490 SelfTestResult(unsigned i)
00491 throw() {
00492 return i == 0 ? 1 :
00493 i == 1 ? 9981545732273789042ULL : 5481486777409645478ULL;
00494 }
00495
00496 template<> Random_u32::type
00497 RandomEngine<MT19937<Random_u32>, MixerSFMT>::
00498 SelfTestResult(unsigned i)
00499 throw() {
00500 return i == 0 ? 1 :
00501 i == 1 ? 666528879UL : 2183745132UL;
00502 }
00503
00504 template<> Random_u64::type
00505 RandomEngine<MT19937<Random_u64>, MixerSFMT>::
00506 SelfTestResult(unsigned i)
00507 throw() {
00508 return i == 0 ? 1 :
00509 i == 1 ? 12176471137395770412ULL : 66914054428611861ULL;
00510 }
00511
00512 template<> Random_u32::type
00513 RandomEngine<SFMT19937<Random_u32>, MixerSFMT>::
00514 SelfTestResult(unsigned i)
00515 throw() {
00516 return i == 0 ? 1 :
00517 i == 1 ? 2695024307UL : 782200760UL;
00518 }
00519
00520 template<> Random_u64::type
00521 RandomEngine<SFMT19937<Random_u64>, MixerSFMT>::
00522 SelfTestResult(unsigned i)
00523 throw() {
00524 return i == 0 ? 1 :
00525 i == 1 ? 1464461649847485149ULL : 5050640804923595109ULL;
00526 }
00527
00528
00529
00530 template<class RandomType> void MixerMT0<RandomType>::
00531 SeedToState(const std::vector<RandomSeed::seed_type>& seed,
00532 mixer_type state[], unsigned n) throw() {
00533
00534
00535
00536 const unsigned s = unsigned(seed.size());
00537 const unsigned w = mixer_t::width;
00538
00539 mixer_type r = s ? a1 : a0;
00540 state[0] = r;
00541 for (unsigned k = 1; k < n; ++k) {
00542 r = b * (r ^ r >> w - 2) + k;
00543 r &= mask;
00544 state[k] = r;
00545 }
00546 if (s > 0) {
00547 const unsigned m = mixer_t::width / 32,
00548 s2 = (s + m - 1)/m;
00549 unsigned i1 = 1;
00550 r = state[0];
00551 for (unsigned k = (n > s2 ? n : s2), j = 0;
00552 k; --k, i1 = i1 == n - 1 ? 1 : i1 + 1,
00553 j = j == s2 - 1 ? 0 : j + 1 ) {
00554 r = state[i1] ^ c * (r ^ r >> w - 2);
00555 r += j + mixer_type(seed[m * j]) +
00556 (m == 1 || 2 * j + 1 == s ? mixer_type(0) :
00557 mixer_type(seed[m * j + 1]) << w - 32);
00558 r &= mask;
00559 state[i1] = r;
00560 }
00561 for (unsigned k = n - 1; k; --k,
00562 i1 = i1 == n - 1 ? 1 : i1 + 1) {
00563 r = state[i1] ^ d * (r ^ r >> w - 2);
00564 r -= i1;
00565 r &= mask;
00566 state[i1] = r;
00567 }
00568 state[0] = typename mixer_t::type(1) << w - 1;
00569 }
00570 }
00571
00572 template<class RandomType> void MixerMT1<RandomType>::
00573 SeedToState(const std::vector<RandomSeed::seed_type>& seed,
00574 mixer_type state[], unsigned n) throw() {
00575
00576
00577
00578
00579
00580 const unsigned s = unsigned(seed.size());
00581 const unsigned w = mixer_t::width;
00582
00583 mixer_type r = (a + s) & mask;
00584 state[0] = r;
00585 for (unsigned k = 1; k < n; ++k) {
00586 r = b * (r ^ r >> w - 2) + k;
00587 r &= mask;
00588 state[k] = r;
00589 }
00590 if (s > 0) {
00591 const unsigned m = mixer_t::width / 32,
00592 s2 = (s + m - 1)/m;
00593 unsigned i1 = 0;
00594 for (unsigned k = (n > s2 ? n : s2), j = 0;
00595 k; --k, i1 = i1 == n - 1 ? 0 : i1 + 1,
00596 j = j == s2 - 1 ? 0 : j + 1 ) {
00597 r = state[i1] ^ c * (r ^ r >> w - 2);
00598 r += j + mixer_type(seed[m * j]) +
00599 (m == 1 || 2 * j + 1 == s ? mixer_type(0) :
00600 mixer_type(seed[m * j + 1]) << w - 32);
00601 r &= mask;
00602 state[i1] = r;
00603 }
00604 for (unsigned k = n; k; --k,
00605 i1 = i1 == n - 1 ? 0 : i1 + 1) {
00606 r = state[i1] ^ d * (r ^ r >> w - 2);
00607 r -= i1;
00608 r &= mask;
00609 state[i1] = r;
00610 }
00611 }
00612 }
00613
00614 void MixerSFMT::SeedToState(const std::vector<RandomSeed::seed_type>& seed,
00615 mixer_type state[], unsigned n)
00616 throw() {
00617
00618
00619
00620 if (n == 0)
00621 return;
00622
00623 const unsigned s = unsigned(seed.size()),
00624
00625
00626
00627 lag = n >= 623 ? 11 : (n >= 68 ? 7 : (n >= 39 ? 5 :
00628 (n >= 7 ? 3 : (n - 1)/2))),
00629
00630 count = s + 1 > n ? s + 1 : n;
00631
00632 std::fill(state, state + n, mixer_type(a));
00633 const unsigned w = mixer_t::width;
00634
00635 unsigned i = 0, k = (n - lag) / 2, l = k + lag;
00636 mixer_type r = state[n - 1];
00637 for (unsigned j = 0; j < count; ++j,
00638 i = i == n - 1 ? 0 : i + 1,
00639 k = k == n - 1 ? 0 : k + 1,
00640 l = l == n - 1 ? 0 : l + 1) {
00641
00642
00643
00644
00645 r ^= state[i] ^ state[k];
00646 r &= mask;
00647 r = b * (r ^ r >> (w - 5));
00648 state[k] += r;
00649 r += i + (j > s ? 0 : (j ? mixer_type(seed[j - 1]) : s));
00650 state[l] += r;
00651 state[i] = r;
00652 }
00653
00654 for (unsigned j = n; j; --j,
00655 i = i == n - 1 ? 0 : i + 1,
00656 k = k == n - 1 ? 0 : k + 1,
00657 l = l == n - 1 ? 0 : l + 1) {
00658
00659
00660
00661 r += state[i] + state[k];
00662 r &= mask;
00663 r = c * (r ^ r >> (w - 5));
00664 r &= mask;
00665 state[k] ^= r;
00666 r -= i;
00667 r &= mask;
00668 state[l] ^= r;
00669 state[i] = r;
00670 }
00671 }
00672
00673
00674
00675
00676
00677 #define MT19937_STEP(I, J, K) statev[I] = statev[K] ^ \
00678 (statev[J] & engine_type(1) ? magic : engine_type(0)) ^ \
00679 ((statev[I] & upper) | (statev[J] & lower)) >> 1
00680
00681
00682
00683
00684
00685
00686
00687
00688 #define MT19937_REVSTEP(I, J, K) { \
00689 engine_type q = statev[J] ^ statev[K], s = q >> (width - 1); \
00690 q = (q ^ (s ? magic : engine_type(0))) << 1 | s; \
00691 statev[I] = (p & upper) | (q & lower); \
00692 p = q; \
00693 }
00694
00695 template<class RandomType>
00696 void MT19937<RandomType>::Transition(long long count, internal_type statev[])
00697 throw() {
00698 if (count > 0)
00699 for (; count; --count) {
00700
00701 unsigned i = 0;
00702 for (; i < N - M; ++i) MT19937_STEP(i, i + 1, i + M );
00703 for (; i < N - 1; ++i) MT19937_STEP(i, i + 1, i + M - N);
00704 MT19937_STEP(N - 1, 0, M - 1);
00705 }
00706 else if (count < 0)
00707 for (; count; ++count) {
00708
00709 engine_type p = statev[0];
00710
00711 MT19937_REVSTEP(0, N - 1, M - 1);
00712 unsigned i = N - 1;
00713 for (; i > N - M; --i) MT19937_REVSTEP(i, i - 1, i + M - 1 - N);
00714 for (; i ; --i) MT19937_REVSTEP(i, i - 1, i + M - 1 );
00715 MT19937_REVSTEP(0, N - 1, M - 1);
00716 }
00717 }
00718
00719 #undef MT19937_STEP
00720 #undef MT19937_REVSTEP
00721
00722 template<class RandomType>
00723 void MT19937<RandomType>::NormalizeState(engine_type state[]) throw () {
00724
00725
00726
00727 state[0] &= upper;
00728 unsigned i = 0;
00729 while (i < N && state[i] == 0)
00730 ++i;
00731 if (i >= N)
00732 state[0] = engine_type(1) << (width - 1);
00733
00734
00735
00736
00737
00738 engine_type q = state[N - 1] ^ state[M - 1], s = q >> (width - 1);
00739 q = (q ^ (s ? magic : engine_type(0))) << 1 | s;
00740 state[0] = (state[0] & upper) | (q & lower);
00741 }
00742
00743 template<class RandomType>
00744 void MT19937<RandomType>::CheckState(const engine_type state[],
00745 Random_u32::type& check)
00746 throw(std::out_of_range) {
00747 engine_type x = 0;
00748 Random_u32::type c = check;
00749 for (unsigned i = 0; i < N; ++i) {
00750 engine_t::CheckSum(state[i], c);
00751 x |= state[i];
00752 }
00753 if (x == 0)
00754 throw std::out_of_range("MT19937: All-zero state");
00755
00756
00757
00758
00759 engine_type q = state[N - 1] ^ state[M - 1], s = q >> (width - 1);
00760 q = (q ^ (s ? magic : engine_type(0))) << 1 | s;
00761 if ((q ^ state[0]) & lower)
00762 throw std::out_of_range("MT19937: Invalid state");
00763
00764 check = c;
00765 }
00766
00767 #if HAVE_SSE2
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 #define SFMT19937_STEP128(I, J) { \
00801 internal_type x = _mm_load_si128(statev + I), \
00802 y = _mm_srli_epi32(statev[J], 11), \
00803 z = _mm_srli_si128(s, 1); \
00804 s = _mm_slli_epi32(r, 18); \
00805 z = _mm_xor_si128(z, x); \
00806 x = _mm_slli_si128(x, 1); \
00807 z = _mm_xor_si128(z, s); \
00808 y = _mm_and_si128(y, m); \
00809 z = _mm_xor_si128(z, x); \
00810 s = r; \
00811 r = _mm_xor_si128(z, y); \
00812 _mm_store_si128(statev + I, r); \
00813 }
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840 #define SFMT19937_REVSTEP128(I, J, K, L) { \
00841 internal_type x = _mm_load_si128(statev + I), \
00842 y = _mm_srli_epi32(statev[J], 11), \
00843 z = _mm_slli_epi32(statev[L], 18); \
00844 y = _mm_and_si128(y, m); \
00845 x = _mm_xor_si128(x, _mm_srli_si128(statev[K], 1)); \
00846 x = _mm_xor_si128(x, z); \
00847 x = _mm_xor_si128(x, y); \
00848 x = _mm_xor_si128(_mm_slli_si128(x, 8), x); \
00849 x = _mm_xor_si128(_mm_slli_si128(x, 4), x); \
00850 x = _mm_xor_si128(_mm_slli_si128(x, 2), x); \
00851 x = _mm_xor_si128(_mm_slli_si128(x, 1), x); \
00852 _mm_store_si128(statev + I, x); \
00853 }
00854
00855 template<class RandomType>
00856 void SFMT19937<RandomType>::Transition(long long count, internal_type statev[])
00857 throw() {
00858 const internal_type m = _mm_set_epi32(magic3, magic2, magic1, magic0);
00859 if (count > 0) {
00860 internal_type s = _mm_load_si128(statev + N128 - 2),
00861 r = _mm_load_si128(statev + N128 - 1);
00862 for (; count; --count) {
00863 unsigned i = 0;
00864 for (; i + M128 < N128; ++i) SFMT19937_STEP128(i, i + M128 );
00865 for (; i < N128 ; ++i) SFMT19937_STEP128(i, i + M128 - N128);
00866 }
00867 } else if (count < 0)
00868 for (; count; ++count) {
00869 unsigned i = N128;
00870 for (; i + M128 > N128;) {
00871 --i; SFMT19937_REVSTEP128(i, i + M128 - N128, i - 2, i - 1);
00872 }
00873 for (; i > 2;) {
00874 --i; SFMT19937_REVSTEP128(i, i + M128, i - 2, i - 1);
00875 }
00876 SFMT19937_REVSTEP128(1, M128 + 1, N128 - 1, 0 );
00877 SFMT19937_REVSTEP128(0, M128 , N128 - 2, N128 - 1);
00878 }
00879 }
00880
00881 #undef SFMT19937_STEP128
00882 #undef SFMT19937_REVSTEP128
00883
00884 #elif HAVE_ALTIVEC
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 #define ALTIVEC_PERM(X, P) vec_perm(X, P, P)
00895
00896 #define SFMT19937_STEP128(I, J) { \
00897 internal_type x = statev[I], \
00898 z = vec_xor(vec_xor(ALTIVEC_PERM(s, right1), x), \
00899 vec_sl(r, bitleft)); \
00900 s = r; \
00901 r = vec_xor(z, \
00902 vec_xor(ALTIVEC_PERM(x, left1), \
00903 vec_and(vec_sr(statev[J], bitright), \
00904 magic))); \
00905 statev[I] = r; \
00906 }
00907
00908 #define SFMT19937_REVSTEP128(I, J, K, L) { \
00909 internal_type x = statev[I], \
00910 y = vec_sr(statev[J], bitright), \
00911 z = vec_sl(statev[L], bitleft); \
00912 y = vec_and(y, magic); \
00913 x = vec_xor(x, ALTIVEC_PERM(statev[K], right1)); \
00914 x = vec_xor(x, z); \
00915 x = vec_xor(x, y); \
00916 x = vec_xor(ALTIVEC_PERM(x, left8), x); \
00917 x = vec_xor(ALTIVEC_PERM(x, left4), x); \
00918 x = vec_xor(ALTIVEC_PERM(x, left2), x); \
00919 statev[I] = vec_xor(ALTIVEC_PERM(x, left1), x); \
00920 }
00921
00922 template<class RandomType>
00923 void SFMT19937<RandomType>::Transition(long long count, internal_type statev[])
00924 throw() {
00925 const internal_type magic = width == 32 ?
00926 (vector unsigned)(magic0, magic1, magic2, magic3) :
00927 (vector unsigned)(magic1, magic0, magic3, magic2),
00928 bitleft = (vector unsigned)(18, 18, 18, 18),
00929 bitright = (vector unsigned)(11, 11, 11, 11);
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 const vector unsigned char left1 = width == 32 ?
00955 (vector unsigned char)(1,2,3,23, 5,6,7,0, 9,10,11,4, 13,14,15,8) :
00956 (vector unsigned char)(1,2,3,4,5,6,7,31, 9,10,11,12,13,14,15,0),
00957 right1 = width == 32 ?
00958 (vector unsigned char)(7,0,1,2, 11,4,5,6, 15,8,9,10, 17,12,13,14) :
00959 (vector unsigned char)(15,0,1,2,3,4,5,6, 17,8,9,10,11,12,13,14);
00960 if (count > 0) {
00961 internal_type s = statev[N128 - 2],
00962 r = statev[N128 - 1];
00963 for (; count; --count) {
00964 unsigned i = 0;
00965 for (; i + M128 < N128; ++i) SFMT19937_STEP128(i, i + M128 );
00966 for (; i < N128 ; ++i) SFMT19937_STEP128(i, i + M128 - N128);
00967 }
00968 } else if (count < 0) {
00969
00970 const vector unsigned char left2 = width == 32 ?
00971 (vector unsigned char)(2,3,22,22, 6,7,0,1, 10,11,4,5, 14,15,8,9) :
00972 (vector unsigned char)(2,3,4,5,6,7,30,30, 10,11,12,13,14,15,0,1),
00973 left4 = width == 32 ?
00974 (vector unsigned char)(20,20,20,20, 0,1,2,3, 4,5,6,7, 8,9,10,11) :
00975 (vector unsigned char)(4,5,6,7,28,28,28,28, 12,13,14,15,0,1,2,3),
00976 left8 = (vector unsigned char)(24,24,24,24,24,24,24,24,0,1,2,3,4,5,6,7);
00977 for (; count; ++count) {
00978 unsigned i = N128;
00979 for (; i + M128 > N128;) {
00980 --i; SFMT19937_REVSTEP128(i, i + M128 - N128, i - 2, i - 1);
00981 }
00982 for (; i > 2;) {
00983 --i; SFMT19937_REVSTEP128(i, i + M128, i - 2, i - 1);
00984 }
00985 SFMT19937_REVSTEP128(1, M128 + 1, N128 - 1, 0 );
00986 SFMT19937_REVSTEP128(0, M128 , N128 - 2, N128 - 1);
00987 }
00988 }
00989 }
00990
00991 #undef SFMT19937_STEP128
00992 #undef SFMT19937_REVSTEP128
00993 #undef ALTVEC_PERM
00994
00995 #else // neither HAVE_SSE2 or HAVE_ALTIVEC
00996
00997 #define SFMT19937_STEP32(I, J) { \
00998 internal_type t = statev[I] ^ statev[I] << 8 ^ \
00999 statev[J] >> 11 & magic0 ^ \
01000 (s0 >> 8 | s1 << 24) ^ r0 << 18; \
01001 s0 = r0; r0 = t & mask; \
01002 t = statev[I + 1] ^ \
01003 (statev[I + 1] << 8 | statev[I] >> 24) ^ \
01004 statev[J + 1] >> 11 & magic1 ^ \
01005 (s1 >> 8 | s2 << 24) ^ r1 << 18; \
01006 s1 = r1; r1 = t & mask; \
01007 t = statev[I + 2] ^ \
01008 (statev[I + 2] << 8 | statev[I + 1] >> 24) ^ \
01009 statev[J + 2] >> 11 & magic2 ^ \
01010 (s2 >> 8 | s3 << 24) ^ r2 << 18; \
01011 s2 = r2; r2 = t & mask; \
01012 t = statev[I + 3] ^ \
01013 (statev[I + 3] << 8 | statev[I + 2] >> 24) ^ \
01014 statev[J + 3] >> 11 & magic3 ^ s3 >> 8 ^ r3 << 18; \
01015 s3 = r3; r3 = t & mask; \
01016 statev[I ] = r0; statev[I + 1] = r1; \
01017 statev[I + 2] = r2; statev[I + 3] = r3; \
01018 }
01019
01020 #define SFMT19937_REVSTEP32(I, J, K, L) { \
01021 internal_type \
01022 t0 = (statev[I] ^ statev[J] >> 11 & magic0 ^ \
01023 (statev[K] >> 8 | statev[K + 1] << 24) ^ \
01024 statev[L] << 18) & mask, \
01025 t1 = (statev[I + 1] ^ \
01026 statev[J + 1] >> 11 & magic1 ^ \
01027 (statev[K + 1] >> 8 | statev[K + 2] << 24) ^ \
01028 statev[L + 1] << 18) & mask, \
01029 t2 = (statev[I + 2] ^ \
01030 statev[J + 2] >> 11 & magic2 ^ \
01031 (statev[K + 2] >> 8 | statev[K + 3] << 24) ^ \
01032 statev[L + 2] << 18) & mask, \
01033 t3 = (statev[I + 3] ^ \
01034 statev[J + 3] >> 11 & magic3 ^ \
01035 statev[K + 3] >> 8 ^ \
01036 statev[L + 3] << 18) & mask; \
01037 t3 ^= t1; t2 ^= t0; t3 ^= t2; t2 ^= t1; t1 ^= t0; \
01038 t3 ^= t2 >> 16 | t3 << 16 & mask; \
01039 t2 ^= t1 >> 16 | t2 << 16 & mask; \
01040 t1 ^= t0 >> 16 | t1 << 16 & mask; \
01041 t0 ^= t0 << 16 & mask; \
01042 statev[I ] = t0 ^ t0 << 8 & mask; \
01043 statev[I + 1] = t1 ^ (t0 >> 24 | t1 << 8 & mask); \
01044 statev[I + 2] = t2 ^ (t1 >> 24 | t2 << 8 & mask); \
01045 statev[I + 3] = t3 ^ (t2 >> 24 | t3 << 8 & mask); \
01046 }
01047
01048 template<>
01049 void SFMT19937<Random_u32>::Transition(