ThreeB 1.1
|
00001 #ifndef MT19937_H 00002 #define MT19937_H 00003 00004 #include "randomc.h" 00005 #include <iostream> 00006 #include <sstream> 00007 #include <string> 00008 #include <cmath> 00009 #include <iomanip> 00010 00011 ///Useful wrapper for MT19937 random number generator class. 00012 ///@ingroup gUtility 00013 struct MT19937 00014 { 00015 ///Null struct thrown if attempting to load 00016 ///state from stream yields a parse error. 00017 struct ParseError{}; 00018 00019 ///Underlying RNG. 00020 CRandomMersenne rng; 00021 00022 public: 00023 MT19937() 00024 :rng(0) 00025 {} 00026 00027 ///Seed state with a simple RNG 00028 ///@param seed 00029 void simple_seed(int seed) 00030 { 00031 rng.RandomInit(seed); 00032 } 00033 00034 ///Duplicate RNG state 00035 ///@param r RNG to duplicate 00036 void copy_state(const MT19937& r) 00037 { 00038 rng = r.rng; 00039 } 00040 00041 ///Generate a double 00042 double operator()() 00043 { 00044 return rng.Random(); 00045 } 00046 00047 ///Generate an int 00048 uint32_t rand_int() 00049 { 00050 return rng.BRandom(); 00051 } 00052 00053 ///Generate a Gaussian variate 00054 double gaussian() 00055 { 00056 double x1, x2, w; 00057 do { 00058 x1 = 2.0 * (*this)() - 1.0; 00059 x2 = 2.0 * (*this)() - 1.0; 00060 w = x1 * x1 + x2 * x2; 00061 } while ( w >= 1.0 ); 00062 00063 w = std::sqrt( (-2.0 * std::log( w ) ) / w ); 00064 return x1 * w; 00065 //spare so we don't have to save that one extra bit of state y2 = x2 * w; 00066 } 00067 00068 ///Serialise state 00069 ///@param o Stream to serialise to 00070 void write(std::ostream& o) 00071 { 00072 using namespace std; 00073 char f = o.fill(); 00074 ios_base::fmtflags fl = o.flags(); 00075 o << "MT19937 " << hex << setfill('0') << setw(3) << rng.get_index(); 00076 for(int i=0; i < MERS_N; i++) 00077 o << " " << hex << setw(8) << rng.get_state()[i]; 00078 00079 o << setfill(f) << setiosflags(fl); 00080 } 00081 00082 ///De serialise state 00083 ///param is Stream to de-serialise from 00084 void read(std::istream& is) 00085 { 00086 using namespace std; 00087 00088 string ls; 00089 getline(is, ls); 00090 if(ls.size() != 5627) 00091 { 00092 cerr << "MT19937: Expected string of length 5627. Got " << ls.size() << endl; 00093 throw ParseError(); 00094 } 00095 00096 istringstream l(ls); 00097 00098 string s; 00099 uint32_t i; 00100 00101 l >> s; 00102 00103 if(s != "MT19937") 00104 { 00105 cerr << "MT19937: Expected MT19937. Got " << s << endl; 00106 throw ParseError(); 00107 } 00108 00109 for(int n=0; n < MERS_N + 1; n++) 00110 { 00111 l >> hex >> i; 00112 if(l.bad()) 00113 { 00114 cerr << "MT19937: Expected hex number. Got "; 00115 if(l.eof()) 00116 cerr << "EOF" << endl; 00117 else 00118 { 00119 cerr << l.get() << endl; 00120 } 00121 00122 throw ParseError(); 00123 } 00124 00125 if(n==0) 00126 rng.get_index() = i; 00127 else 00128 rng.get_state()[n-1]=i; 00129 00130 } 00131 00132 } 00133 private: 00134 /// Disallow copying, since one almost never wants to do this. 00135 /// Copying has to be explicit via MT19937::copy_state(). 00136 MT19937(const MT19937&); 00137 00138 }; 00139 00140 00141 #endif