ThreeB 1.1
mt19937.h
Go to the documentation of this file.
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