00001
00002
00003 #ifndef RANDGENMersenneTwister_HPP_
00004 #define RANDGENMersenneTwister_HPP_
00005
00006 #include "../RandGen.hpp"
00007 #include <limits.h>
00008
00009 class RandGenMersenneTwister: public RandGen
00010 {
00011 private:
00012 static const unsigned int GEN_STATE_LENGTH = 624;
00013 static const unsigned int MASK_1 = 0xffffffff;
00014 static const unsigned int MASK_2 = 0x80000000;
00015 static const unsigned int MASK_3 = 0x7fffffff;
00016
00017 static const unsigned int CONSTANT_1 = 0x6c078965;
00018 static const unsigned int CONSTANT_2 = 0x9d2c5680;
00019 static const unsigned int CONSTANT_3 = 0xefc60000;
00020 static const unsigned int CONSTANT_4 = 0x9908b0df;
00021 unsigned int MT[GEN_STATE_LENGTH];
00022 int index;
00023
00024 void GenNum()
00025 {
00026 register int i;
00027 unsigned int y;
00028 for (i = 0; i < GEN_STATE_LENGTH; i++)
00029 {
00030 y = (MT[i] ^ MASK_2) + (MT[(i + 1) % GEN_STATE_LENGTH] ^ MASK_3);
00031 MT[i] = MT[(i + 397) % GEN_STATE_LENGTH] ^ (y >> 1);
00032 if ((y % 2) == 1)
00033 {
00034 MT[i] = MT[i] ^ CONSTANT_4;
00035 }
00036 }
00037 }
00038
00039 unsigned mt_rand()
00040 {
00041 if (!RandGen::init)
00042 {
00043 initialize();
00044 RandGen::init = true;
00045 }
00046
00047 unsigned int y;
00048
00049 if (index == 0)
00050 GenNum();
00051
00052 y = MT[index];
00053 y = y ^ (y >> 11);
00054 y = y ^ ((y << 7) & CONSTANT_2);
00055 y = y ^ ((y << 15) & CONSTANT_3);
00056 y = y ^ (y >> 18);
00057
00058 index = (index + 1) % GEN_STATE_LENGTH;
00059
00060 return y;
00061 }
00062
00063 public:
00064
00065 RandGenMersenneTwister() :
00066 RandGen()
00067 {
00068 }
00069
00070 RandGenMersenneTwister(long seed) :
00071 RandGen(seed)
00072 {
00073 }
00074
00075 using RandGen::rand;
00076
00077
00078 void initialize()
00079 {
00080 register int i;
00081
00082 index = 0;
00083 MT[0] = seed;
00084 for (i = 1; i < GEN_STATE_LENGTH; i++)
00085 {
00086 MT[i] = ((CONSTANT_1 * (MT[i - 1] ^ (MT[i - 1] >> 30))) + i) & MASK_1;
00087 }
00088 }
00089
00090
00091 int rand()
00092 {
00093 return mt_rand();
00094 }
00095
00096
00097 int rand(int n)
00098 {
00099 if (n < 0)
00100 n *= (-1);
00101
00102 return mt_rand() % n;
00103 }
00104
00105
00106 double rand01()
00107 {
00108 return (double) mt_rand() / UINT_MAX;
00109 }
00110 };
00111
00112 #endif