00001 #include "random.h" 00002 00007 #include <cassert> 00008 00010 00011 GltRandomLCG GltRandomLCG::rng; 00012 00013 const int32 GltRandomLCG::a = 16807; 00014 const int32 GltRandomLCG::m = 2147483647; 00015 const int32 GltRandomLCG::q = 127773; 00016 const int32 GltRandomLCG::r = 2836; 00017 00018 GltRandomLCG::GltRandomLCG(const uint32 seed) 00019 : _idum(0) 00020 { 00021 GltRandomLCG::seed(seed); 00022 assert(_idum!=0); 00023 } 00024 00025 GltRandomLCG::GltRandomLCG(const GltRandomLCG &rng) 00026 { 00027 _idum = rng._idum; 00028 } 00029 00030 GltRandomLCG::~GltRandomLCG() 00031 { 00032 } 00033 00034 uint32 00035 GltRandomLCG::rand() const 00036 { 00037 // 00038 // Based on Numerical Recipes in C 00039 // and FreeBSD implementation of libkern/random.c 00040 // 00041 // See also: 00042 // http://minnie.cs.adfa.edu.au/FreeBSD-srctree/newsrc/libkern/random.c.html 00043 // http://www.scd.ucar.edu/zine/96/spring/articles/3.random-6.html 00044 // http://www.mactech.com/articles/mactech/Vol.08/08.03/RandomNumbers/ 00045 // http://wad.www.media.mit.edu/people/wad/mas864/psrc/random.c.txt 00046 // http://prog.cz/swag/swag/numbers/0081.htm 00047 // http://www.dcs.gla.ac.uk/mail-www/glasgow-haskell-users/msg00158.html 00048 00049 int32 t = a*(_idum%q) - r*(_idum/q); 00050 if (t <= 0) 00051 t += m; 00052 _idum = t; 00053 00054 assert(_idum<=max()); 00055 00056 return _idum; 00057 } 00058 00059 void 00060 GltRandomLCG::seed(const uint32 seed) 00061 { 00062 if (seed) 00063 _idum = seed; 00064 else 00065 _idum = 25101974; 00066 00067 assert(_idum!=0); 00068 } 00069 00070 uint32 GltRandomLCG::max() const { return m-1; } 00071 00073 00074 GltRandomLFSRMix GltRandomLFSRMix::rng; 00075 00076 GltRandomLFSRMix::GltRandomLFSRMix(const uint32 seed1,const uint32 seed2,const uint32 seed3) 00077 : _regA(seed1), _regB(seed2), _regC(seed3) 00078 { 00079 } 00080 00081 GltRandomLFSRMix::GltRandomLFSRMix(const GltRandomLFSRMix &rng) 00082 : _regA(rng._regA), _regB(rng._regB), _regC(rng._regC) 00083 { 00084 } 00085 00086 GltRandomLFSRMix::~GltRandomLFSRMix() 00087 { 00088 } 00089 00090 uint32 00091 GltRandomLFSRMix::rand() const 00092 { 00093 uint32 result = 0; 00094 00095 for (int j=0; j<32; j++) 00096 { 00097 _regA = ((( (_regA >> 31) ^ (_regA >> 6) ^ (_regA >> 4) ^ (_regA >> 2) ^ (_regA << 1) ^ _regA) & 0x00000001) << 31) | (_regA >> 1); 00098 _regB = ((( (_regB >> 30) ^ (_regB >> 2)) & 0x00000001) << 30) | (_regB >> 1); 00099 _regC = ((( (_regC >> 28) ^ (_regC >> 1)) & 0x00000001) << 28) | (_regC >> 1); 00100 result = (result << 1) ^ (((_regA & _regB) | (~_regA & _regC)) & 0x00000001); 00101 } 00102 00103 assert(result<=max()); 00104 00105 return result; 00106 } 00107 00108 uint32 GltRandomLFSRMix::max() const { return 0xffffffff; } 00109