/** * @file XorShiftRand.h * @note: * - xor shift 関係のサイト http://www.jstatsoft.org/v08/i14/paper * http://www.iro.umontreal.ca/~lecuyer/myftp/papers/xorshift.pdf * よい乱数悪い乱数 http://www001.upp.so-net.ne.jp/isaku/rand.html * 2ch 擬似乱数2 http://pc12.2ch.net/test/read.cgi/tech/1192628099/ (42, 55, 76) * * - とりあえずtemplateにして特殊化で 32,64,96,128,160,192,256の周期を指定にしている. * 当初の目論見ではinit(),get()をinline化させないような記述のためだったが * 特殊化クラスのメンバーの記述がよくわからず結局class内に実装. * - なので普通に XorShiftRand32 のように書いたほうがよかったかも. (が面倒なんでこのまま) */ #ifndef XORSHIFTRAND_H #define XORSHIFTRAND_H /// intが32ビットかを確認. typedef char check_int_is_32bits[ sizeof(int) == 4 ? 1/*OK*/ : -1/*NG*/ ]; /// 32bit符号無整数を返す XOR SHIFT 法の乱数. C=周期のビット数. template<unsigned C> class XorShiftRand { // この定義は実体化することはない(したらエラー). typedef char check[(C==32||C==64||C==96||C==128||C==160||C==192||C==256) ? 1/*ok*/ : -1/*ng*/]; }; #ifdef XORSHIFTRAND_TEST /// 周期2**32 - 1のxor shift 乱数. (paper文中の奴) template<> class XorShiftRand<32> { unsigned seed_; public: XorShiftRand(unsigned s=0) { init(s); } void init(unsigned s) { seed_ = s ? s : 2463534242U; } unsigned get() { unsigned x = seed_; x ^= (x << 13); x ^= (x >> 17); seed_ = (x ^= (x<<5)); return x; } unsigned operator()() { return get(); } }; #endif /// 周期2**64 - 1のxor shift 乱数. (paper文中のabc3組の内の1つを適当に設定) template<> class XorShiftRand<64> { unsigned seed_[2]; public: XorShiftRand(unsigned s=0) { init(s); } void init(unsigned s) { seed_[0] = s = 1812433253U * (s ^ (s>>30)) + 1; seed_[1] = 1812433253U * (s ^ (s>>30)) + 2; } unsigned get() { enum { A =10, B =13, C =10 }; // [10,13,10][8,9,22][2,7,3][23,3,24] unsigned t, y; unsigned* a = seed_; t = a[0]; t = (t ^ (t<<A)); a[0] = y = a[1]; t = (y ^ (y>>C)) ^ (t ^ (t>>B)); a[1] = t; return t; } unsigned operator()() { return get(); } }; /// 周期2**96 - 1のxor shift 乱数. (paper文中のabc3組の内の1つを適当に設定) template<> class XorShiftRand<96> { unsigned seed_[3]; public: XorShiftRand(unsigned s=0) { init(s); } void init(unsigned s) { for (unsigned i = 0; i < 3; ++i) seed_[i] = s = 1812433253U * (s ^ (s>>30)) + i+1; } unsigned get() { enum { A =10, B = 1, C =26 }; // [10,5,26][13,19,3][1,17,2][10,1,26] unsigned t, z; unsigned* a = seed_; t = a[0]; t = (t ^ (t<<A)); a[0] = a[1]; a[1] = z = a[2]; t = (z ^ (z>>C)) ^ (t ^ (t>>B)); a[2] = t; return t; } unsigned operator()() { return get(); } }; /// 周期2**128 - 1のxor shift 乱数. (paper文中のもの) template<> class XorShiftRand<128> { unsigned seed_[4]; public: XorShiftRand(unsigned s=0) { init(s); } void init(unsigned s) { for (unsigned i = 0; i < 4; ++i) seed_[i] = s = 1812433253U * (s ^ (s>>30)) + i+1; } unsigned get() { enum { A =11, B = 8, C =19 }; unsigned t, w; unsigned* a = seed_; t = a[0]; a[0] = a[1]; a[1] = a[2]; a[2] = w = a[3]; t = t ^ (t<<A); w = (w ^ (w>>C)) ^ (t ^ (t>>B)); a[3] = w; return w; } unsigned operator()() { return get(); } }; /// 周期 2**160 - 1 のxor shift 乱数. (paper文中のabc3組の内の1つを適当に設定) template<> class XorShiftRand<160> { unsigned seed_[5]; public: XorShiftRand(unsigned s=0) { init(s); } void init(unsigned s) { for (unsigned i = 0; i < 5; ++i) seed_[i] = s = 1812433253U * (s ^ (s>>30)) + i+1; } unsigned get() { enum { A = 2, B = 1, C = 4 }; // [2,1,4][7,13,6][1,1,20] unsigned t, v; unsigned* a = seed_; t = a[0]; a[0] = a[1]; a[1] = a[2]; a[2] = a[3]; a[3] = v = a[4]; //t = (t ^ (t>>A)); t = (t ^ (t<<A)); v = (v ^ (v>>C)) ^ (t ^ (t>>B)); a[4] = v; return v; } unsigned operator()() { return get(); } }; /// 周期 2**192 - 232 のxor shift 乱数. (paper.pdf: xorwow()) template<> class XorShiftRand<192> { unsigned seed_[6]; public: XorShiftRand(unsigned s=0) { init(s); } void init(unsigned s) { for (unsigned i = 0; i < 6; ++i) seed_[i] = s = 1812433253U * (s ^ (s>>30)) + i+1; } unsigned get() { unsigned t, v; unsigned* a = seed_; t = a[0]; a[0] = a[1]; a[1] = a[2]; a[2] = a[3]; a[3] = v = a[4]; t = (t ^ (t>>2)); v = (v ^ (v<<4)) ^ (t ^ (t<<1)); a[4] = v; t = (a[5] += 362437); t += v; return t; } unsigned operator()() { return get(); } }; #ifdef XORSHIFTRAND_TEST /// 周期 2**256 - 1 のxor shift 乱数. (xorshift.pdf文中の) template<> class XorShiftRand<256> { unsigned k_; unsigned seed_[8]; public: XorShiftRand(unsigned s=0) { init(s); } void init(unsigned s) { k_ = 0; for (unsigned i = 0; i < 8; ++i) seed_[i] = s = 1812433253U * (s ^ (s>>30)) + i+1; } unsigned get() { unsigned t, y; unsigned* a = seed_; unsigned k = k_; t = a[(k+7) & 0x7U]; t = t ^ (t<<13); y = t ^ (t<< 9); t = a[(k+4) & 0x7U]; y^= t ^ (t<< 7); t = a[(k+3) & 0x7U]; y^= t ^ (t>> 3); t = a[(k+1) & 0x7U]; y^= t ^ (t>>10); t = a[k ]; t = t ^ (t>> 7); y^= t ^ (t<<24); a[k] = y; k_ = (k+1) & 0x7U; return y; } unsigned operator()() { return get(); } }; #endif #endif