Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members  

trng.h

00001 // ---------------------------------------------------------------------
00002 // Time-stamp: <Dienstag, 30.04.2002, 12:02:35; edited by heiko>
00003 // 
00004 // Tina's random number generators TRNG
00005 //
00006 // Copyright (C) 2001, 2002 Heiko Bauke
00007 //
00008 // heiko.bauke@student.uni-magdeburg.de
00009 //
00010 // TRNG is free software; you can redistribute it and/or
00011 // modify it under the terms of the GNU General Public License
00012 // as published by the Free Software Foundation. This program
00013 // is distributed WITHOUT ANY WARRANTY; without even the implied
00014 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00015 // See the GNU General Public License for more details.
00016 //
00017 // ---------------------------------------------------------------------
00018 
00019 #if !defined TRNG_H
00020 
00021 #define TRNG_H
00022 
00023 #include <iostream>
00024 #include <cmath>
00025 #include <climits>
00026 #include <vector>
00027 #include <trnglib.h>
00028 
00029 #define TRNG_VERSION "2"
00030 #define TRNG_REVISION "0"
00031 
00032 
00034 
00037 namespace TRNG {
00038   
00040 
00044   enum RNG_type {
00045     RNG_t,          
00046     generic_MLCG_t, 
00047     ParkMiller_t,   
00048     LCG32_t,        
00049     LCG64_t,        
00050     MRG2_t,         
00051     MRG3_t,         
00052     MRG4_t,         
00053     CLCG2_t,        
00054     CLCG3_t,        
00055     CLCG4_t,        
00056     EINV_t,         
00057     EINVLCG64_t,    
00058     user1_t,        
00059     user2_t,        
00060     user3_t         
00061   };   
00062  
00064   struct vector2d_struct {
00066     double x1;
00068     double x2;
00069   };
00070 
00072 
00076   typedef struct vector2d_struct vector2d;
00077   
00079   struct vector3d_struct {
00081     double x1;
00083     double x2;
00085     double x3;
00086   };
00087 
00089 
00093   typedef struct vector3d_struct vector3d;
00094 
00096   struct vector4d_struct {
00098     double x1;
00100     double x2;
00102     double x3;
00104     double x4;
00105   };
00106 
00108 
00112   typedef struct vector4d_struct vector4d;
00113 
00114   // -------------------------------------------------------------------
00115 
00117 
00126   template<class RNG_type> class RNG {
00127   private:
00128     RNG_type & derived(void) {
00129       return static_cast<RNG_type &>(*this);
00130     }
00131     
00132   protected:
00134     long max_val;
00136     long max_val2;
00137   public:
00139 
00142     static const TRNG::RNG_type type=RNG_t;
00143     
00145 
00150     const char * name(void) {
00151       return derived().name(); 
00152     }
00153     
00155 
00159     void reset(void)  { 
00160       derived().reset(); 
00161     }
00162     
00164 
00172     void seed(long s=0l) { 
00173       derived().seed(s);
00174     }
00175     
00177 
00184     long rand(void) { 
00185       return derived().rand(); 
00186     }
00187 
00189 
00192     long max(void) {
00193       return max_val;
00194     };
00195     
00197 
00201     bool boolean(void) {
00202       return (rand()<max_val2) ? true : false;
00203     }
00204 
00206 
00210     bool boolean(const double p) {
00211       return (rand()<static_cast<long>(p*max())+1.0) ? true : false;
00212     }
00213     
00215 
00218     double uniform(void) {
00219       return uniformco();
00220     }
00221 
00223 
00228     double uniform(const double a, const double b) {
00229       return uniformco(a, b);
00230     }
00231 
00233 
00236     double uniformco(void) {
00237       return static_cast<double>(rand())/
00238         (static_cast<double>(max())+1.0);
00239     }
00240 
00242 
00247     double uniformco(const double a, const double b) {
00248       return a+(b-a)*static_cast<double>(rand())/
00249         (static_cast<double>(max())+1.0);
00250     }
00251 
00253 
00256     double uniformcc(void) {
00257       return static_cast<double>(rand())/
00258         static_cast<double>(max());
00259     }
00260     
00262 
00267     double uniformcc(const double a, const double b) {
00268       return a+(b-a)*static_cast<double>(rand())/
00269         static_cast<double>(max());
00270     }
00271 
00273 
00276     double uniformoc(void) {
00277       return (static_cast<double>(rand())+1.0)/
00278         (static_cast<double>(max())+1.0);
00279     }
00280     
00282 
00287     double uniformoc(const double a, const double b) {
00288       return a+(b-a)*(static_cast<double>(rand())+1.0)/
00289         (static_cast<double>(max())+1.0);
00290     }
00291     
00293 
00296     double uniformoo(void) {
00297       return (static_cast<double>(rand())+1.0)/
00298         (static_cast<double>(max())+2.0);
00299     }
00300 
00302 
00307     double uniformoo(const double a, const double b) {
00308       return a+(b-a)*(static_cast<double>(rand())+1.0)/
00309         (static_cast<double>(max())+2.0);
00310     }
00311     
00313 
00317     long uniforml(const long b) {
00318       return static_cast<long>(uniform(0.0, static_cast<double>(b)));
00319     }
00320     
00322 
00327     long uniforml(const long a, const long b) {
00328       return static_cast<long>(uniform(static_cast<double>(a),
00329                                        static_cast<double>(b)));
00330     }
00331     
00333 
00347     double normal_dist(const double sigma=1.0, const double mu=0.0) {
00348       // static double s, t1, t2;
00349       double s, t1, t2;
00350       // static bool calc=true;
00351       if (sigma<=0.0)
00352         throw error("negative or zero standard deviation in TRNG::RNG::normal_dist");
00353       // if (calc) {
00354       // calc=false;
00355       do {
00356         t1=uniformoo(-1.0, 1.0);
00357         t2=uniformoo(-1.0, 1.0);
00358         s=t1*t1+t2*t2;
00359       } while (s>=1.0);
00360       s=std::sqrt(-2.0*std::log(s)/s);
00361       return t1*s*sigma+mu;
00362       // } else {
00363       // calc=true;
00364       // return t2*s*sigma+mu;
00365       // }
00366     }
00367 
00369 
00388     double exp_dist(const double mu=1.0) {
00389       if (mu<=0.0)
00390         throw error("negative or zero parameter in TRNG::RNG::exp_dist");
00391       double t=uniformoc();
00392       return -mu*std::log(t);
00393     }
00394 
00396 
00410     double laplace_dist(const double a=1.0) {
00411       if (a<=0.0)
00412         throw error("parameter less or equal zero in TRNG::RNG::laplace_dist");
00413       double u;
00414       do {
00415         u=uniformoo(-1.0, 1.0);
00416       } while (u==0.0);
00417       return u<0.0 ? a*std::log(-u) : -a*std::log(u);
00418     }
00419 
00421 
00441     double tent_dist(const double a=1.0) {
00442       if (a<=0.0)
00443         throw error("parameter less or equal zero in TRNG::RNG::tent_dist");
00444       double y=uniformoo();
00445       if (y<0.5)
00446         return (-1.0+std::sqrt(2*y))*a;
00447       else
00448         return (1.0-std::sqrt(2.0-2.0*y))*a;
00449     }
00450     
00452 
00471     double Gamma_dist(const double a, const double b) {
00472       if (a<=0.0 || b<=0.0)
00473         throw error("parameter less or equal zero in TRNG::RNG::Gamma_dist");
00474       double a_int=std::floor(a);
00475       if (a_int==a) {
00476         // if a is an integer
00477         if (a<12) {
00478           double prod=1.0;
00479           for (int i=0; i<a; ++i)
00480             prod*=uniformoo();
00481           // Note: for 12 iterations we are safe against underflow, since
00482           // the smallest positive random number is O(2^-32). This means
00483           // the smallest possible product is 2^(-12*32) = 10^-116 which
00484           // is within the range of double precision.
00485           return -b*std::log(prod);
00486         } else {
00487           // Works only if a>1, and is most efficient if a is large
00488           // This algorithm, reported in Knuth, is attributed to Ahrens.  A
00489           // faster one, we are told, can be found in: J. H. Ahrens and
00490           // U. Dieter, Computing 12 (1974) 223-246.
00491           double sqa, x, y, v;
00492           sqa=std::sqrt(2.0*a-1.0);
00493           do {
00494             do {
00495               const double pi=3.14159265358979324;
00496               y=std::tan(pi*uniformco());
00497               x=sqa*y+a-1.0;
00498             }
00499             while (x<=0.0);
00500             v=uniformco();
00501           }
00502           while (v>(1.0+y*y)*std::exp((a-1.0)*log(x/(a-1))-sqa*y));
00503           return b*x;
00504         }
00505       }
00506       if (a_int==0.0) {
00507         // if a<1
00508         // This is exercise 16 from Knuth; see page 135, and the solution is
00509         // on page 551.
00510         const double e=2.71828182844;
00511         double p, q, x, u, v;
00512         p=e/(a+e);
00513         do {
00514           u=uniformco();
00515           v=uniformoo();
00516           if (u<p) {
00517             x=std::exp((1.0/a)*std::log(v));
00518             q=std::exp(-x);
00519           } else {
00520             x=1.0-std::log(v);
00521             q=std::exp((a-1.0)*std::log(x));
00522           }
00523         } while (uniformco()>=q);
00524         return b*x;
00525       }
00526       return Gamma_dist(a_int, b)+Gamma_dist(a-a_int, b); 
00527     }
00528 
00530 
00549     double Beta_dist(const double a, const double b) {
00550       if (a<=0.0 || b<=0.0)
00551         throw error("negative or zero parameter in TRNG::RNG::Beta_dist");
00552       double t1=Gamma_dist(a, 1.0);
00553       double t2=Gamma_dist(b, 1.0);
00554       return t1/(t1+t2);
00555     }
00556 
00558 
00574     double chi_square_dist(const double nu) {
00575       if (nu<1.0)
00576         throw error("parameter less than one in TRNG::RNG::chi_square_dist");
00577       return 2.0*Gamma_dist(0.5*nu, 1.0);
00578     }
00579 
00581 
00596     long binomial_dist(long n, double p=0.5) {
00597       if (p<=0.0 || p>1.0)
00598         throw error("probability <=0.0 or >1.0 in TRNG::RNG::binomial_dist");
00599       if (n<1l)
00600         throw error("less than one trail TRNG::RNG::binomial_dist");
00601       long i, a, b, k=0;
00602       while (n>12l) {  // This parameter is tunable
00603         double X;
00604         a=1l+(n/2l);
00605         b=1l+n-a;
00606         X=Beta_dist(static_cast<double>(a), static_cast<double>(b));
00607         if (X>=p) {
00608           n=a-1l;
00609           p/=X;
00610         } else {
00611           k+=a;
00612           n=b-1l;
00613           p=(p-X)/(1l-X);
00614         }
00615       }
00616       for (i=0l; i<n; i++)
00617         if (uniformco()<p)
00618           k++;
00619       return k;
00620     }
00621 
00623 
00636     long binomial_dist_tab(long n, double p=0.5) {
00637       if (p<=0.0 || p>1.0)
00638         throw error("probability <=0.0 or >1.0 in TRNG::RNG::binomial_dist_tab");
00639       if (n<1l)
00640         throw error("less than one trail TRNG::RNG::binomial_dist_tab");
00641       static long n_=0l;
00642       static double p_=0.0;
00643       static vector<double> prob;
00644       if (n!=n_ || p!=p_) {
00645         n_=n;
00646         p_=p;
00647         prob.resize(n_);
00648         // use
00649         // ( n )            (  n  )   n-k ( n )
00650         // (   ) = 1  and   (     ) = --- (   )
00651         // ( 0 )            ( k+1 )   k+1 ( k )
00652         double b=1.0;
00653         for (int k=0l; k<n_; ++k) {
00654           prob[k]=b*std::pow(p_, static_cast<double>(k))*
00655             std::pow(1.0-p_, static_cast<double>(n_-k));
00656           if (k>0l)
00657             prob[k]+=prob[k-1l];
00658           b=std::floor(b*static_cast<double>(n_-k)/
00659                        static_cast<double>(k+1l)+0.5); 
00660         }
00661       }
00662       return find_interval(prob, uniformco());
00663     }
00664 
00666 
00682     double Student_t_dist(const double nu) {
00683       if (nu<=0.0)
00684         throw error("parameter less than or equal zero in TRNG::RNG::Student_t_dist");
00685       if (nu<=2.0) 
00686         return normal_dist()/std::sqrt(chi_square_dist(nu)/nu);
00687       else {
00688         double y1, y2, z;
00689         do {
00690           y1=normal_dist();
00691           y2=exp_dist(1.0/(0.5*nu-1.0));
00692           z=y1*y1/(nu-2.0);
00693         } while (1.0-z<0.0 || std::exp(-y2-z)>(1.0-z));
00694         // Note that there is a typo in Knuth's formula, the line below
00695         // is taken from the original paper of Marsaglia, Mathematics of
00696         // Computation, 34 (1980), p 234-256 
00697         return y1/std::sqrt((1.0-2.0/nu)*(1.0-z));
00698       }
00699     }
00700 
00702 
00714     long poisson_dist(double mu=1.0) {
00715       if (mu<=0)
00716         throw error("parameter less than 0 in TRNG::RNG::poisson_dist");
00717       double emu;
00718       double prod=1.0;
00719       long k=0;  
00720       while (mu>10.0) {
00721         long m=static_cast<long>(mu*(7.0/8.0));
00722         double X=Gamma_dist(static_cast<long>(m), 1.0);
00723         if (X>=mu) {
00724           return k+binomial_dist(m-1l, mu/X);
00725         } else {
00726           k+=m;
00727           mu-=X; 
00728         }
00729       }
00730       // This following method works well when mu is small
00731       emu=std::exp(-mu);
00732       do {
00733         prod*=uniformco();
00734         k++;
00735       } while (prod>emu);
00736       return k-1l;
00737     }
00738 
00740 
00752     long geometric_dist(double q) {
00753       if (q<=0.0 ||q>1.0)
00754         throw error("parameter out of range in TRNG::RNG::geometric_dist");
00755       if (q==1.0)
00756         return 1l;
00757       return static_cast<long>
00758         (std::log(uniformoo())/std::log(1.0-p))+1l;
00759     }
00760 
00762 
00788     template<class t_function>
00789       double rejection(t_function p, double a1, double a2, double p_max)  {
00790       double t1, t2;
00791       do {
00792         t1=uniformco(a1, a2);
00793         t2=uniformco(0.0, p_max);
00794       } while (p(t1)<t2);
00795       return t1;
00796     }
00797 
00799 
00811     long discrete_dist(const std::vector<double> p) {
00812       if (p.empty())
00813         throw error("empty vector in TRNG::discrete_dist");
00814       double x=uniformco();
00815       if (x<p[0])
00816         return 0l;
00817       long i1=0l;
00818       long i2=p.size()-1l;
00819       while (i2-i1>1l) {
00820         long i3=(i2+i1)/2;
00821         if (x<=p[i3])
00822           i2=i3;
00823         else
00824           i1=i3;
00825       }
00826       return i2;
00827     }
00828 
00830 
00838     vector2d spherical2d(void) {
00839       double r2, t1, t2, t12, t22;
00840       vector2d vec;
00841       do {
00842         t1=2.0*uniformco()-1.0;
00843         t2=uniformco();
00844         t12=t1*t1;
00845         t22=t2*t2;
00846         r2=t12+t22;
00847       } while (r2>1.0);
00848       vec.x1=2.0*t1*t2/r2;
00849       vec.x2=(t12-t22)/r2;
00850       return vec;
00851     }
00852 
00854 
00862     vector3d spherical3d(void)  {
00863       double q, r2, t1, t2;
00864       vector3d vec;
00865       do {
00866         t1=2.0*uniformco()-1.0;
00867         t2=2.0*uniformco()-1.0;
00868         r2=t1*t1+t2*t2;
00869       } while (r2>1.0);
00870       q=2.0*sqrt(1.0-r2);
00871       vec.x1=t1*q;
00872       vec.x2=t2*q;
00873       vec.x3=1-2*r2;
00874       return vec;
00875     }
00876 
00878 
00886     vector4d spherical4d(void)  {
00887       double q, r21, r22, t1, t2, t3, t4;
00888       vector4d vec;
00889       do {
00890         t1=2.0*uniformco()-1.0;
00891         t2=2.0*uniformco()-1.0;
00892         r21=t1*t1+t2*t2;
00893       } while (r21>1.0);
00894       do {
00895         t3=2.0*uniformco()-1.0;
00896         t4=2.0*uniformco()-1.0;
00897         r22=t3*t3+t4*t4;
00898       } while (r22>1.0);
00899       q=sqrt((1.0-r21)/r22);
00900       vec.x1=t1;
00901       vec.x2=t2;
00902       vec.x3=t3*q;
00903       vec.x4=t4*q;
00904       return(vec);
00905     }
00906 
00908 
00917     void split(long s, long n) {
00918       derived().split(s, n);
00919     }
00920 
00922 
00928     void jump(long long s) {
00929       if (s<0ll)
00930         throw error("invalid argument for TRNG::RNG::jump");
00931       long i=0l;
00932       while (s>0ll) {
00933         if (s%2==1)
00934           jump2(i);
00935         ++i;
00936         s>>=1;
00937       }
00938     }
00939 
00941 
00947     void jump(long long s, long n) {
00948       if (s<0ll || n<0l)
00949         throw error("invalid argument for TRNG::RNG::jump");
00950       while (n>0l) {
00951         jump(s);
00952         --n;
00953       }
00954     }
00955 
00957 
00963     void jump2(long s) {
00964       derived().jump2(s);
00965     }
00966 
00968 
00975     void jump2(long s, long n) {
00976       if (s<0l || n<0l)
00977         throw error("invalid argument for TRNG::RNG::jump2");
00978       while (n>0l) {
00979         if (n%2l==1l)
00980           jump2(s);
00981         s+=1l;
00982         n>>=1;
00983       }
00984     }
00985 
00987 
00992     void save_status(std::vector<long> &s) {
00993       derived().save_status(s);
00994     }
00995 
00997 
01002     void load_status(const std::vector<long> &s) {
01003       derived().load_status(s);
01004     }
01005     
01006   };
01007 
01008   // --------------------------------------------------------------------
01009 
01010   class generic_MLCG : public RNG<generic_MLCG> {
01011     // generic class for multiplicative linear congruential 
01012     // random number generators
01013   private:
01014     long a, a_save;
01015     long modulus, modulus_save;
01016     long r;
01017     void backward(void);
01018   public:
01019     static const RNG_type type=generic_MLCG_t;
01020     const char * name(void);    
01021     void reset(void);
01022     void seed(long s=0l);
01023     long rand(void);
01024     void split(long s, long n);    
01025     void jump2(long s);
01026     void save_status(std::vector<long> &s);
01027     void load_status(const std::vector<long> &s);
01028     generic_MLCG(long a_=16807l, long modulus_=2147483647l, long seed_=0l);
01029   };
01030 
01031   // -------------------------------------------------------------------
01032 
01034 
01049   class ParkMiller : public RNG<ParkMiller> {
01050   private:
01051     generic_MLCG R;
01052   public:
01053     static const RNG_type type=ParkMiller_t;
01054     const char * name(void);    
01055     void reset(void);
01056     void seed(long s=0l);
01057     long rand(void);    
01058     void split(long s, long n);
01059     void jump2(long s);
01060     void save_status(std::vector<long> &s);
01061     void load_status(const std::vector<long> &s);
01063 
01072     ParkMiller(long a_=16807l, long modulus_=2147483647l, long seed_=0l);
01073   };
01074   
01075   // -------------------------------------------------------------------
01076 
01078 
01092   class LCG32 : public RNG<LCG32> {
01093   private:
01094     unsigned long a, a_save;
01095     unsigned long b, b_save;
01096     unsigned long r;
01097     void backward(void);
01098   public:
01099     static const RNG_type type=LCG32_t;
01100     const char * name(void);
01101     void reset(void);
01102     void seed(long s=0l);    
01103     long rand(void);    
01104     void split(long s, long n);    
01105     void jump2(long s);    
01106     void save_status(std::vector<long> &s);    
01107     void load_status(const std::vector<long> &s);
01109 
01118     LCG32(unsigned long a_=69069ul, unsigned long b_=1ul, long seed_=0l);
01119   };
01120 
01121   // -------------------------------------------------------------------
01122 
01124 
01138   class LCG64 : public RNG<LCG64> {
01139   private:
01140     unsigned long long a, a_save;
01141     unsigned long long b, b_save;
01142     unsigned long long r;
01143     void backward(void);
01144   public:
01145     static const RNG_type type=LCG64_t;
01146     const char * name(void);
01147     void reset(void);
01148     void seed(long s=0l);
01149     long rand(void);
01150     void split(long s, long n);
01151     void jump2(long s);    
01152     void save_status(std::vector<long> &s);    
01153     void load_status(const std::vector<long> &s);
01155 
01164     LCG64(unsigned long long a_=18145460002477866997ull, 
01165           unsigned long long b_=1ul, 
01166           long seed_=0ul);    
01167   };
01168   
01169   // -------------------------------------------------------------------
01170 
01172 
01180   class MRG2 : public RNG<MRG2> {
01181   private:
01182     long a0, a1, a0_save, a1_save;
01183     long r0, r1;
01184     long modulus, modulus_save;
01185     void backward(void);
01186   public:
01187     static const RNG_type type=MRG2_t;
01188     const char * name(void);    
01189     void reset(void);
01190     void seed(long s=0l);
01191     long rand(void);    
01192     void split(long s, long n);
01193     void jump2(long s);
01194     void save_status(std::vector<long> &s);
01195     void load_status(const std::vector<long> &s);    
01197 
01209     MRG2(long a0_=1498809829l, long a1_=1160990996l, 
01210          long modulus_=2147483647l, long seed_=0l);
01211   };
01212 
01213   // -------------------------------------------------------------------
01214 
01216 
01224   class MRG3 : public RNG<MRG3> {
01225   private:
01226     long a0, a1, a2, a0_save, a1_save, a2_save;
01227     long r0, r1, r2;
01228     long modulus, modulus_save;
01229     void backward(void);
01230   public:
01231     static const RNG_type type=MRG3_t;
01232     const char * name(void);
01233     void reset(void);    
01234     void seed(long s=0l);
01235     long rand(void);   
01236     void split(long s, long n);
01237     void jump2(long s);    
01238     void save_status(std::vector<long> &s);
01239     void load_status(const std::vector<long> &s);
01241 
01254     MRG3(long a0_=2021422057l, long a1_=1826992351l, 
01255          long a2_=1977753457l, long modulus_=2147483647l, 
01256          long seed_=0l);
01257   };
01258     
01259   // -------------------------------------------------------------------
01260 
01262 
01271   class MRG4 : public RNG<MRG4> {
01272   private:
01273     long a0, a1, a2, a3, a0_save, a1_save, a2_save, a3_save;
01274     long r0, r1, r2, r3;
01275     long modulus, modulus_save;
01276     void backward(void);
01277   public:
01278     static const RNG_type type=MRG4_t;
01279     const char * name(void);
01280     void reset(void);
01281     void seed(long s=0l);
01282     long rand(void);
01283     void split(long s, long n);
01284     void jump2(long s);
01285     void save_status(std::vector<long> &s);
01286     void load_status(const std::vector<long> &s);
01288 
01303     MRG4(long a0_=2001982722l, long a1_=1412284257l, 
01304          long a2_=1155380217l, long a3_=1668339922l,
01305          long modulus_=2147483647l, long seed_=0l);
01306   };
01307 
01308   // -------------------------------------------------------------------
01309 
01311 
01324   class CLCG2 : public RNG<CLCG2> {
01325   private:
01326     generic_MLCG R1;
01327     generic_MLCG R2;
01328     long modulus;
01329   public:
01330     static const RNG_type type=CLCG2_t;
01331     const char * name(void);
01332     void reset(void);
01333     void seed(long s=0l);
01334     long rand(void);    
01335     void split(long s, long n);
01336     void jump2(long s);
01337     void save_status(std::vector<long> &s);    
01338     void load_status(const std::vector<long> &s);    
01340 
01360     CLCG2(long a1= 376555083l, long m1=2147482951l,
01361           long a2=1028879659l, long m2=2147482949l, 
01362           long seed_=0l);    
01363   };
01364 
01365   // -------------------------------------------------------------------
01366 
01368 
01382   class CLCG3 : public RNG<CLCG3> {
01383   private:
01384     generic_MLCG R1;
01385     generic_MLCG R2;
01386     generic_MLCG R3;
01387     long modulus;
01388   public:
01389     static const RNG_type type=CLCG3_t;
01390     const char * name(void);
01391     void reset(void);
01392     void seed(long s=0l);
01393     long rand(void);
01394     void split(long s, long n);
01395     void jump2(long s);
01396     void save_status(std::vector<long> &s);
01397     void load_status(const std::vector<long> &s);
01399 
01423     CLCG3(long a1= 376555083l, long m1=2147482951l,
01424           long a2=1028879659l, long m2=2147482949l,
01425           long a3= 225802979l, long m3=2147482943l,
01426           long seed_=0l);    
01427   };
01428 
01429   // -------------------------------------------------------------------
01430 
01432 
01447   class CLCG4 : public RNG<CLCG4> {
01448   private:
01449     generic_MLCG R1;
01450     generic_MLCG R2;
01451     generic_MLCG R3;
01452     generic_MLCG R4;
01453     long modulus;
01454   public:
01455     static const RNG_type type=CLCG4_t;
01456     const char * name(void);
01457     void reset(void);
01458     void seed(long s=0l);
01459     long rand(void);
01460     void split(long s, long n);
01461     void jump2(long s);
01462     void save_status(std::vector<long> &s);  
01463     void load_status(const std::vector<long> &s);
01465 
01493     CLCG4(long a1= 376555083l, long m1=2147482951l,
01494           long a2=1028879659l, long m2=2147482949l,
01495           long a3= 225802979l, long m3=2147482943l,
01496           long a4=2028073966l, long m4=2147482859l,
01497           long seed_=0l);    
01498   };
01499 
01500   // -------------------------------------------------------------------
01501 
01503 
01516   class EINV : public RNG<EINV> {
01517   private:
01518     long a, i, di, modulus, a_save;
01519     long modulo_invers(const long a);
01520   public:
01521     static const RNG_type type=EINV_t;
01522     const char * name(void);
01523     void reset(void);
01524     void seed(long s=0l);
01525     long rand(void);
01526     void split(long s, long n);
01527     void jump2(long s);
01528     void save_status(std::vector<long> &s);
01529     void load_status(const std::vector<long> &s);
01531 
01536     EINV(long a_=1073741831l, long seed_=0l);
01537     
01538   };
01539 
01540   // -------------------------------------------------------------------
01541 
01543 
01555   class EINVLCG64 : public RNG<EINVLCG64> {
01556   private:
01557     LCG64 R1;
01558     EINV R2;
01559   public:
01560     static const RNG_type type=EINVLCG64_t;
01561     const char * name(void);
01562     void reset(void);
01563     void seed(long s=0l);    
01564     long rand(void);
01565     void split(long s, long n);
01566     void jump2(long s);
01567     void save_status(std::vector<long> &s);
01568     void load_status(const std::vector<long> &s);    
01570 
01573     EINVLCG64(long seed_=0l);    
01574   };
01575 
01576   // -------------------------------------------------------------------
01577   
01579 
01585   template<class RNG_type>
01586     void copy(RNG<RNG_type> &R1, RNG<RNG_type> &R2) {
01587     std::vector<long> s;
01588     R1.save_status(s);
01589     R2.load_status(s);
01590   }
01591 
01592 }
01593 
01594 
01595 #endif

Generated at Tue Apr 30 12:03:09 2002 for Tina's Random Number Generators by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000