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

trng.h

00001 // ---------------------------------------------------------------------
00002 // Time-stamp: <Samstag, 25.01.2003, 16:58:12; edited by heiko>
00003 // 
00004 // Tina's random number generators TRNG
00005 //
00006 // Copyright (C) 2001, 2002 Heiko Bauke
00007 //
00008 // heiko.bauke@physik.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 "2"
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     YARNLCG64_t,    
00054     YARN2_t,        
00055     YARN3_t,        
00056     YARN4_t,        
00057     CLCG2_t,        
00058     CLCG3_t,        
00059     CLCG4_t,        
00060     EINV_t,         
00061     EINVLCG64_t,    
00062     trng_gsl_t,     
00063     user1_t=1001,   
00064     user2_t=1002,   
00065     user3_t=1003,   
00066     user4_t=1004,   
00067     user5_t=1005    
00068   };   
00069  
00071   struct vector2d_struct {
00073     double x1;
00075     double x2;
00076   };
00077 
00079 
00083   typedef struct vector2d_struct vector2d;
00084   
00086   struct vector3d_struct {
00088     double x1;
00090     double x2;
00092     double x3;
00093   };
00094 
00096 
00100   typedef struct vector3d_struct vector3d;
00101 
00103   struct vector4d_struct {
00105     double x1;
00107     double x2;
00109     double x3;
00111     double x4;
00112   };
00113 
00115 
00119   typedef struct vector4d_struct vector4d;
00120 
00121   // -------------------------------------------------------------------
00122 
00124 
00133   template<class RNG_type> class RNG {
00134   private:
00135     RNG_type & derived(void) {
00136       return static_cast<RNG_type &>(*this);
00137     }
00138     
00139   protected:
00141     long max_val;
00143     long max_val2;
00144   public:
00146 
00149     static const TRNG::RNG_type type=RNG_t;
00150     
00152 
00157     const char * name(void) {
00158       return derived().name(); 
00159     }
00160     
00162 
00166     void reset(void)  { 
00167       derived().reset(); 
00168     }
00169     
00171 
00179     void seed(long s=0l) { 
00180       derived().seed(s);
00181     }
00182     
00184 
00191     long rand(void) { 
00192       return derived().rand(); 
00193     }
00194 
00196 
00199     long max(void) {
00200       return max_val;
00201     };
00202     
00204 
00208     bool boolean(void) {
00209       return (rand()<=max_val2) ? true : false;
00210     }
00211 
00213 
00217     bool boolean(const double p) {
00218       return (rand()<static_cast<long>(p*max())+1.0) ? true : false;
00219     }
00220     
00222 
00225     double uniform(void) {
00226       return uniformco();
00227     }
00228 
00230 
00235     double uniform(const double a, const double b) {
00236       return uniformco(a, b);
00237     }
00238 
00240 
00243     double uniformco(void) {
00244       return static_cast<double>(rand())/
00245         (static_cast<double>(max())+1.0);
00246     }
00247 
00249 
00254     double uniformco(const double a, const double b) {
00255       return a+(b-a)*static_cast<double>(rand())/
00256         (static_cast<double>(max())+1.0);
00257     }
00258 
00260 
00263     double uniformcc(void) {
00264       return static_cast<double>(rand())/
00265         static_cast<double>(max());
00266     }
00267     
00269 
00274     double uniformcc(const double a, const double b) {
00275       return a+(b-a)*static_cast<double>(rand())/
00276         static_cast<double>(max());
00277     }
00278 
00280 
00283     double uniformoc(void) {
00284       return (static_cast<double>(rand())+1.0)/
00285         (static_cast<double>(max())+1.0);
00286     }
00287     
00289 
00294     double uniformoc(const double a, const double b) {
00295       return a+(b-a)*(static_cast<double>(rand())+1.0)/
00296         (static_cast<double>(max())+1.0);
00297     }
00298     
00300 
00303     double uniformoo(void) {
00304       return (static_cast<double>(rand())+1.0)/
00305         (static_cast<double>(max())+2.0);
00306     }
00307 
00309 
00314     double uniformoo(const double a, const double b) {
00315       return a+(b-a)*(static_cast<double>(rand())+1.0)/
00316         (static_cast<double>(max())+2.0);
00317     }
00318     
00320 
00324     long uniforml(const long b) {
00325       return static_cast<long>(uniform(0.0, static_cast<double>(b)));
00326     }
00327     
00329 
00334     long uniforml(const long a, const long b) {
00335       return static_cast<long>(uniform(static_cast<double>(a),
00336                                        static_cast<double>(b)));
00337     }
00338     
00340 
00354     double normal_dist(const double sigma=1.0, const double mu=0.0) {
00355       // static double s, t1, t2;
00356       double s, t1, t2;
00357       // static bool calc=true;
00358       if (sigma<=0.0)
00359         throw error("negative or zero standard deviation in TRNG::RNG::normal_dist");
00360       // if (calc) {
00361       // calc=false;
00362       do {
00363         t1=uniformoo(-1.0, 1.0);
00364         t2=uniformoo(-1.0, 1.0);
00365         s=t1*t1+t2*t2;
00366       } while (s>=1.0);
00367       s=std::sqrt(-2.0*std::log(s)/s);
00368       return t1*s*sigma+mu;
00369       // } else {
00370       // calc=true;
00371       // return t2*s*sigma+mu;
00372       // }
00373     }
00374 
00376 
00395     double exp_dist(const double mu=1.0) {
00396       if (mu<=0.0)
00397         throw error("negative or zero parameter in TRNG::RNG::exp_dist");
00398       double t=uniformoc();
00399       return -mu*std::log(t);
00400     }
00401 
00403 
00417     double laplace_dist(const double a=1.0) {
00418       if (a<=0.0)
00419         throw error("parameter less or equal zero in TRNG::RNG::laplace_dist");
00420       double u;
00421       do {
00422         u=uniformoo(-1.0, 1.0);
00423       } while (u==0.0);
00424       return u<0.0 ? a*std::log(-u) : -a*std::log(u);
00425     }
00426 
00428 
00448     double tent_dist(const double a=1.0) {
00449       if (a<=0.0)
00450         throw error("parameter less or equal zero in TRNG::RNG::tent_dist");
00451       double y=uniformoo();
00452       if (y<0.5)
00453         return (-1.0+std::sqrt(2*y))*a;
00454       else
00455         return (1.0-std::sqrt(2.0-2.0*y))*a;
00456     }
00457     
00459 
00478     double Gamma_dist(const double a, const double b) {
00479       if (a<=0.0 || b<=0.0)
00480         throw error("parameter less or equal zero in TRNG::RNG::Gamma_dist");
00481       double a_int=std::floor(a);
00482       if (a_int==a) {
00483         // if a is an integer
00484         if (a<12) {
00485           double prod=1.0;
00486           for (int i=0; i<a; ++i)
00487             prod*=uniformoo();
00488           // Note: for 12 iterations we are safe against underflow, since
00489           // the smallest positive random number is O(2^-32). This means
00490           // the smallest possible product is 2^(-12*32) = 10^-116 which
00491           // is within the range of double precision.
00492           return -b*std::log(prod);
00493         } else {
00494           // Works only if a>1, and is most efficient if a is large
00495           // This algorithm, reported in Knuth, is attributed to Ahrens.  A
00496           // faster one, we are told, can be found in: J. H. Ahrens and
00497           // U. Dieter, Computing 12 (1974) 223-246.
00498           double sqa, x, y, v;
00499           sqa=std::sqrt(2.0*a-1.0);
00500           do {
00501             do {
00502               const double pi=3.14159265358979324;
00503               y=std::tan(pi*uniformco());
00504               x=sqa*y+a-1.0;
00505             }
00506             while (x<=0.0);
00507             v=uniformco();
00508           }
00509           while (v>(1.0+y*y)*std::exp((a-1.0)*log(x/(a-1))-sqa*y));
00510           return b*x;
00511         }
00512       }
00513       if (a_int==0.0) {
00514         // if a<1
00515         // This is exercise 16 from Knuth; see page 135, and the solution is
00516         // on page 551.
00517         const double e=2.71828182844;
00518         double p, q, x, u, v;
00519         p=e/(a+e);
00520         do {
00521           u=uniformco();
00522           v=uniformoo();
00523           if (u<p) {
00524             x=std::exp((1.0/a)*std::log(v));
00525             q=std::exp(-x);
00526           } else {
00527             x=1.0-std::log(v);
00528             q=std::exp((a-1.0)*std::log(x));
00529           }
00530         } while (uniformco()>=q);
00531         return b*x;
00532       }
00533       return Gamma_dist(a_int, b)+Gamma_dist(a-a_int, b); 
00534     }
00535 
00537 
00556     double Beta_dist(const double a, const double b) {
00557       if (a<=0.0 || b<=0.0)
00558         throw error("negative or zero parameter in TRNG::RNG::Beta_dist");
00559       double t1=Gamma_dist(a, 1.0);
00560       double t2=Gamma_dist(b, 1.0);
00561       return t1/(t1+t2);
00562     }
00563 
00565 
00581     double chi_square_dist(const double nu) {
00582       if (nu<1.0)
00583         throw error("parameter less than one in TRNG::RNG::chi_square_dist");
00584       return 2.0*Gamma_dist(0.5*nu, 1.0);
00585     }
00586 
00588 
00603     long binomial_dist(long n, double p=0.5) {
00604       if (p<=0.0 || p>1.0)
00605         throw error("probability <=0.0 or >1.0 in TRNG::RNG::binomial_dist");
00606       if (n<1l)
00607         throw error("less than one trail TRNG::RNG::binomial_dist");
00608       long i, a, b, k=0;
00609       while (n>12l) {  // This parameter is tunable
00610         double X;
00611         a=1l+(n/2l);
00612         b=1l+n-a;
00613         X=Beta_dist(static_cast<double>(a), static_cast<double>(b));
00614         if (X>=p) {
00615           n=a-1l;
00616           p/=X;
00617         } else {
00618           k+=a;
00619           n=b-1l;
00620           p=(p-X)/(1l-X);
00621         }
00622       }
00623       for (i=0l; i<n; i++)
00624         if (uniformco()<p)
00625           k++;
00626       return k;
00627     }
00628 
00630 
00643     long binomial_dist_tab(long n, double p=0.5) {
00644       if (p<=0.0 || p>1.0)
00645         throw error("probability <=0.0 or >1.0 in TRNG::RNG::binomial_dist_tab");
00646       if (n<1l)
00647         throw error("less than one trail TRNG::RNG::binomial_dist_tab");
00648       static long n_=0l;
00649       static double p_=0.0;
00650       static std::vector<double> prob;
00651       if (n!=n_ || p!=p_) {
00652         n_=n;
00653         p_=p;
00654         prob.resize(n_);
00655         // use
00656         // ( n )            (  n  )   n-k ( n )
00657         // (   ) = 1  and   (     ) = --- (   )
00658         // ( 0 )            ( k+1 )   k+1 ( k )
00659         double b=1.0;
00660         for (int k=0l; k<n_; ++k) {
00661           prob[k]=b*std::pow(p_, static_cast<double>(k))*
00662             std::pow(1.0-p_, static_cast<double>(n_-k));
00663           if (k>0l)
00664             prob[k]+=prob[k-1l];
00665           b=std::floor(b*static_cast<double>(n_-k)/
00666                        static_cast<double>(k+1l)+0.5); 
00667         }
00668       }
00669       return find_interval(prob, uniformco());
00670     }
00671 
00673 
00689     double Student_t_dist(const double nu) {
00690       if (nu<=0.0)
00691         throw error("parameter less than or equal zero in TRNG::RNG::Student_t_dist");
00692       if (nu<=2.0) 
00693         return normal_dist()/std::sqrt(chi_square_dist(nu)/nu);
00694       else {
00695         double y1, y2, z;
00696         do {
00697           y1=normal_dist();
00698           y2=exp_dist(1.0/(0.5*nu-1.0));
00699           z=y1*y1/(nu-2.0);
00700         } while (1.0-z<0.0 || std::exp(-y2-z)>(1.0-z));
00701         // Note that there is a typo in Knuth's formula, the line below
00702         // is taken from the original paper of Marsaglia, Mathematics of
00703         // Computation, 34 (1980), p 234-256 
00704         return y1/std::sqrt((1.0-2.0/nu)*(1.0-z));
00705       }
00706     }
00707 
00709 
00721     long poisson_dist(double mu=1.0) {
00722       if (mu<=0)
00723         throw error("parameter less than 0 in TRNG::RNG::poisson_dist");
00724       double emu;
00725       double prod=1.0;
00726       long k=0;  
00727       while (mu>10.0) {
00728         long m=static_cast<long>(mu*(7.0/8.0));
00729         double X=Gamma_dist(static_cast<long>(m), 1.0);
00730         if (X>=mu) {
00731           return k+binomial_dist(m-1l, mu/X);
00732         } else {
00733           k+=m;
00734           mu-=X; 
00735         }
00736       }
00737       // This following method works well when mu is small
00738       emu=std::exp(-mu);
00739       do {
00740         prod*=uniformco();
00741         k++;
00742       } while (prod>emu);
00743       return k-1l;
00744     }
00745 
00747 
00759     long geometric_dist(double q) {
00760       if (q<=0.0 ||q>1.0)
00761         throw error("parameter out of range in TRNG::RNG::geometric_dist");
00762       if (q==1.0)
00763         return 1l;
00764       return static_cast<long>
00765         (std::log(uniformoo())/std::log(1.0-p))+1l;
00766     }
00767 
00769 
00795     template<class t_function>
00796       double rejection(t_function p, double a1, double a2, double p_max)  {
00797       double t1, t2;
00798       do {
00799         t1=uniformco(a1, a2);
00800         t2=uniformco(0.0, p_max);
00801       } while (p(t1)<t2);
00802       return t1;
00803     }
00804 
00806 
00818     long discrete_dist(const std::vector<double> p) {
00819       if (p.empty())
00820         throw error("empty vector in TRNG::discrete_dist");
00821       double x=uniformco();
00822       if (x<p[0])
00823         return 0l;
00824       long i1=0l;
00825       long i2=p.size()-1l;
00826       while (i2-i1>1l) {
00827         long i3=(i2+i1)/2;
00828         if (x<=p[i3])
00829           i2=i3;
00830         else
00831           i1=i3;
00832       }
00833       return i2;
00834     }
00835 
00837 
00845     vector2d spherical2d(void) {
00846       double r2, t1, t2, t12, t22;
00847       vector2d vec;
00848       do {
00849         t1=2.0*uniformco()-1.0;
00850         t2=uniformco();
00851         t12=t1*t1;
00852         t22=t2*t2;
00853         r2=t12+t22;
00854       } while (r2>1.0);
00855       vec.x1=2.0*t1*t2/r2;
00856       vec.x2=(t12-t22)/r2;
00857       return vec;
00858     }
00859 
00861 
00869     vector3d spherical3d(void)  {
00870       double q, r2, t1, t2;
00871       vector3d vec;
00872       do {
00873         t1=2.0*uniformco()-1.0;
00874         t2=2.0*uniformco()-1.0;
00875         r2=t1*t1+t2*t2;
00876       } while (r2>1.0);
00877       q=2.0*sqrt(1.0-r2);
00878       vec.x1=t1*q;
00879       vec.x2=t2*q;
00880       vec.x3=1-2*r2;
00881       return vec;
00882     }
00883 
00885 
00893     vector4d spherical4d(void)  {
00894       double q, r21, r22, t1, t2, t3, t4;
00895       vector4d vec;
00896       do {
00897         t1=2.0*uniformco()-1.0;
00898         t2=2.0*uniformco()-1.0;
00899         r21=t1*t1+t2*t2;
00900       } while (r21>1.0);
00901       do {
00902         t3=2.0*uniformco()-1.0;
00903         t4=2.0*uniformco()-1.0;
00904         r22=t3*t3+t4*t4;
00905       } while (r22>1.0);
00906       q=sqrt((1.0-r21)/r22);
00907       vec.x1=t1;
00908       vec.x2=t2;
00909       vec.x3=t3*q;
00910       vec.x4=t4*q;
00911       return(vec);
00912     }
00913 
00915 
00924     void split(long s, long n) {
00925       derived().split(s, n);
00926     }
00927 
00929 
00935     void jump(long long s) {
00936       if (s<0ll)
00937         throw error("invalid argument for TRNG::RNG::jump");
00938       long i=0l;
00939       while (s>0ll) {
00940         if (s%2==1)
00941           jump2(i);
00942         ++i;
00943         s>>=1;
00944       }
00945     }
00946 
00948 
00956     void jump(long long s, long n) {
00957       if (s<0ll || n<0l)
00958         throw error("invalid argument for TRNG::RNG::jump");
00959       while (n>0l) {
00960         jump(s);
00961         --n;
00962       }
00963     }
00964 
00966 
00972     void jump2(long s) {
00973       derived().jump2(s);
00974     }
00975 
00977 
00984     void jump2(long s, long n) {
00985       if (s<0l || n<0l)
00986         throw error("invalid argument for TRNG::RNG::jump2");
00987       while (n>0l) {
00988         if (n%2l==1l)
00989           jump2(s);
00990         s+=1l;
00991         n>>=1;
00992       }
00993     }
00994 
00996 
01001     void save_status(std::vector<long> &s) {
01002       derived().save_status(s);
01003     }
01004 
01006 
01011     void load_status(const std::vector<long> &s) {
01012       derived().load_status(s);
01013     }
01014 
01015 //     //! generic copy constructor
01016 //     /*!
01017 //       This is the random number generator copy constructor. Useful if
01018 //       some generators with the same sequence of random numbers are needed.
01019 //      */
01020 //     RNG<RNG_type> & RNG<RNG_type>::operator=(RNG<RNG_type> &other) {
01021 //       if (this!=&other) {
01022 //      std::vector<long> s;
01023 //      other.save_status(s);
01024 //      load_status(s);
01025 //       }
01026 //       return *this;
01027 //     }
01028     
01029   };
01030 
01031   // --------------------------------------------------------------------
01032 
01034 
01050   class generic_MLCG : public RNG<generic_MLCG> {
01051     // generic class for multiplicative linear congruential 
01052     // random number generators
01053   private:
01054     long a, a_save;
01055     long modulus, modulus_save;
01056     long r;
01057     void backward(void);
01058   public:
01059     static const RNG_type type=generic_MLCG_t;
01060     const char * name(void);    
01061     void reset(void);
01062     void seed(long s=0l);
01063     long rand(void);
01064     void split(long s, long n);    
01065     void jump2(long s);
01066     void save_status(std::vector<long> &s);
01067     void load_status(const std::vector<long> &s);
01068     generic_MLCG & generic_MLCG::operator=(RNG<generic_MLCG> &other);
01069     generic_MLCG(long a_=16807l, long modulus_=2147483647l, long seed_=0l);
01070   };
01071 
01072   inline long generic_MLCG::rand(void) {
01073     r=static_cast<long>
01074       ((static_cast<long long>(a)*static_cast<long long>(r))%modulus);
01075     return r;
01076   }
01077 
01078   // -------------------------------------------------------------------
01079 
01081 
01096   class ParkMiller : public RNG<ParkMiller> {
01097   private:
01098     generic_MLCG R;
01099   public:
01100     static const RNG_type type=ParkMiller_t;
01101     const char * name(void);    
01102     void reset(void);
01103     void seed(long s=0l);
01104     long rand(void);
01105     void split(long s, long n);
01106     void jump2(long s);
01107     void save_status(std::vector<long> &s);
01108     void load_status(const std::vector<long> &s);
01109     ParkMiller & ParkMiller::operator=(RNG<ParkMiller> &other); 
01111 
01120     ParkMiller(long a_=16807l, long modulus_=2147483647l, long seed_=0l);
01121   };
01122 
01123   inline long ParkMiller::rand(void) {
01124     return R.rand()-1l;
01125   }
01126 
01127   
01128   // -------------------------------------------------------------------
01129 
01131 
01145   class LCG32 : public RNG<LCG32> {
01146   private:
01147     unsigned long a, a_save;
01148     unsigned long b, b_save;
01149     unsigned long r;
01150     void backward(void);
01151   public:
01152     static const RNG_type type=LCG32_t;
01153     const char * name(void);
01154     void reset(void);
01155     void seed(long s=0l);    
01156     long rand(void);    
01157     void split(long s, long n);    
01158     void jump2(long s);    
01159     void save_status(std::vector<long> &s);    
01160     void load_status(const std::vector<long> &s);
01161     LCG32 & LCG32::operator=(RNG<LCG32> &other);
01163 
01172     LCG32(unsigned long a_=69069ul, unsigned long b_=1ul, long seed_=0l);
01173   };
01174 
01175   inline long LCG32::rand(void) {
01176     r=a*r+b;
01177 #if ULONG_MAX == 0xfffffffful
01178 #else
01179     r&=0xfffffffful;
01180 #endif
01181     return static_cast<long>(r>>1);
01182   }
01183 
01184   // -------------------------------------------------------------------
01185 
01187 
01201   class LCG64 : public RNG<LCG64> {
01202   private:
01203     unsigned long long a, a_save;
01204     unsigned long long b, b_save;
01205     unsigned long long r;
01206     void backward(void);
01207   public:
01208     static const RNG_type type=LCG64_t;
01209     const char * name(void);
01210     void reset(void);
01211     void seed(long s=0l);
01212     long rand(void);
01213     void split(long s, long n);
01214     void jump2(long s);    
01215     void save_status(std::vector<long> &s);    
01216     void load_status(const std::vector<long> &s);
01217     LCG64 & LCG64::operator=(RNG<LCG64> &other);
01219 
01228     LCG64(unsigned long long a_=18145460002477866997ull, 
01229           unsigned long long b_=1ul, 
01230           long seed_=0ul);    
01231   };
01232   
01233   inline long LCG64::rand(void) {
01234     r=a*r+b;
01235     return static_cast<long>(r>>33);
01236   }
01237 
01238   // -------------------------------------------------------------------
01239 
01241 
01249   class MRG2 : public RNG<MRG2> {
01250   private:
01251     long a0, a1, a0_save, a1_save;
01252     long r0, r1;
01253     long modulus, modulus_save;
01254     void backward(void);
01255   public:
01256     static const RNG_type type=MRG2_t;
01257     const char * name(void);    
01258     void reset(void);
01259     void seed(long s=0l);
01260     long rand(void);    
01261     void split(long s, long n);
01262     void jump2(long s);
01263     void save_status(std::vector<long> &s);
01264     void load_status(const std::vector<long> &s);    
01265     MRG2 & MRG2::operator=(RNG<MRG2> &other);
01267 
01279     MRG2(long a0_=1498809829l, long a1_=1160990996l, 
01280          long modulus_=2147483647l, long seed_=0l);
01281   };
01282 
01283   inline long MRG2::rand(void) {
01284     long t=static_cast<long>((static_cast<long long>(a0)*
01285                               static_cast<long long>(r0)+
01286                               static_cast<long long>(a1)*
01287                               static_cast<long long>(r1))%modulus);
01288     r1=r0;  r0=t;
01289     return r0;
01290   }
01291 
01292   // -------------------------------------------------------------------
01293 
01295 
01303   class MRG3 : public RNG<MRG3> {
01304   private:
01305     long a0, a1, a2, a0_save, a1_save, a2_save;
01306     long r0, r1, r2;
01307     long modulus, modulus_save;
01308     void backward(void);
01309   public:
01310     static const RNG_type type=MRG3_t;
01311     const char * name(void);
01312     void reset(void);    
01313     void seed(long s=0l);
01314     long rand(void);   
01315     void split(long s, long n);
01316     void jump2(long s);    
01317     void save_status(std::vector<long> &s);
01318     void load_status(const std::vector<long> &s);
01319     MRG3 & MRG3::operator=(RNG<MRG3> &other);
01321 
01334     MRG3(long a0_=2021422057l, long a1_=1826992351l, 
01335          long a2_=1977753457l, long modulus_=2147483647l, 
01336          long seed_=0l);
01337   };
01338 
01339   inline long MRG3::rand(void) {
01340     long t=static_cast<long>((static_cast<unsigned long long>(a0)*
01341                               static_cast<unsigned long long>(r0)+
01342                               static_cast<unsigned long long>(a1)*
01343                               static_cast<unsigned long long>(r1)+
01344                               static_cast<unsigned long long>(a2)*
01345                               static_cast<unsigned long long>(r2))%modulus);
01346     r2=r1;  r1=r0;  r0=t;
01347     return r0;
01348   }
01349     
01350   // -------------------------------------------------------------------
01351 
01353 
01362   class MRG4 : public RNG<MRG4> {
01363   private:
01364     long a0, a1, a2, a3, a0_save, a1_save, a2_save, a3_save;
01365     long r0, r1, r2, r3;
01366     long modulus, modulus_save;
01367     void backward(void);
01368   public:
01369     static const RNG_type type=MRG4_t;
01370     const char * name(void);
01371     void reset(void);
01372     void seed(long s=0l);
01373     long rand(void);
01374     void split(long s, long n);
01375     void jump2(long s);
01376     void save_status(std::vector<long> &s);
01377     void load_status(const std::vector<long> &s);
01378     MRG4 & MRG4::operator=(RNG<MRG4> &other);
01380 
01395     MRG4(long a0_=2001982722l, long a1_=1412284257l, 
01396          long a2_=1155380217l, long a3_=1668339922l,
01397          long modulus_=2147483647l, long seed_=0l);
01398   };
01399 
01400   inline long MRG4::rand(void) {
01401     long t=static_cast<long>((static_cast<unsigned long long>(a0)*
01402                               static_cast<unsigned long long>(r0)+
01403                               static_cast<unsigned long long>(a1)*
01404                               static_cast<unsigned long long>(r1)+
01405                               static_cast<unsigned long long>(a2)*
01406                               static_cast<unsigned long long>(r2)+
01407                               static_cast<unsigned long long>(a3)*
01408                               static_cast<unsigned long long>(r3))%modulus);
01409     r3=r2;  r2=r1;  r1=r0;  r0=t;
01410     return r0;
01411   }
01412 
01413   // -------------------------------------------------------------------
01414 
01416 
01439   class YARNLCG64 : public RNG<YARNLCG64> {
01440   private:
01441     LCG64 R;
01442     power b;
01443     long b_save;
01444   public:
01445     static const RNG_type type=YARNLCG64_t;
01446     const char * name(void);    
01447     void reset(void);
01448     void seed(long s=0l);
01449     long rand(void);    
01450     void split(long s, long n);
01451     void jump2(long s);
01452     void save_status(std::vector<long> &s);
01453     void load_status(const std::vector<long> &s);
01454     YARNLCG64 & YARNLCG64::operator=(RNG<YARNLCG64> &other); 
01456 
01465     YARNLCG64(unsigned long long a_=18145460002477866997ull, 
01466               unsigned long long b_=1ul, 
01467               long seed_=0ul, long c_=123567893l);
01468   };
01469 
01470   inline long YARNLCG64::rand(void) {
01471     long t=R.rand();
01472     return (t==0 || t==2147483647l) ? t : b(t);
01473   }
01474 
01475   // -------------------------------------------------------------------
01476 
01478 
01495   class YARN2 : public RNG<YARN2> {
01496   private:
01497     MRG2 R;
01498     power b;
01499     long b_save;
01500   public:
01501     static const RNG_type type=YARN2_t;
01502     const char * name(void);    
01503     void reset(void);
01504     void seed(long s=0l);
01505     long rand(void);    
01506     void split(long s, long n);
01507     void jump2(long s);
01508     void save_status(std::vector<long> &s);
01509     void load_status(const std::vector<long> &s);
01510     YARN2 & YARN2::operator=(RNG<YARN2> &other); 
01512 
01526     YARN2(long a0_=1498809829l, long a1_=1160990996l, 
01527           long modulus_=2147483647l, 
01528           long seed_=0l, long b_=123567893l);
01529   };
01530 
01531   inline long YARN2::rand(void) {
01532     long t=R.rand();
01533     return (t==0) ? 0 : b(t);
01534   }
01535 
01536   // -------------------------------------------------------------------
01537 
01539 
01556   class YARN3 : public RNG<YARN3> {
01557   private:
01558     MRG3 R;
01559     power b;
01560     long b_save;
01561   public:
01562     static const RNG_type type=YARN3_t;
01563     const char * name(void);    
01564     void reset(void);
01565     void seed(long s=0l);
01566     long rand(void);    
01567     void split(long s, long n);
01568     void jump2(long s);
01569     void save_status(std::vector<long> &s);
01570     void load_status(const std::vector<long> &s);
01571     YARN3 & YARN3::operator=(RNG<YARN3> &other); 
01573 
01588     YARN3(long a0_=2021422057l, long a1_=1826992351l, 
01589           long a2_=1977753457l, long modulus_=2147483647l, 
01590           long seed_=0l, long b_=123567893l);
01591   };
01592 
01593   inline long YARN3::rand(void) {
01594     long t=R.rand();
01595     return (t==0) ? 0 : b(t);
01596   }
01597 
01598   // -------------------------------------------------------------------
01599 
01601 
01619   class YARN4 : public RNG<YARN4> {
01620   private:
01621     MRG4 R;
01622     power b;
01623     long b_save;
01624   public:
01625     static const RNG_type type=YARN4_t;
01626     const char * name(void);    
01627     void reset(void);
01628     void seed(long s=0l);
01629     long rand(void);    
01630     void split(long s, long n);
01631     void jump2(long s);
01632     void save_status(std::vector<long> &s);
01633     void load_status(const std::vector<long> &s);
01634     YARN4 & YARN4::operator=(RNG<YARN4> &other); 
01636 
01653     YARN4(long a0_=2001982722l, long a1_=1412284257l, 
01654           long a2_=1155380217l, long a3_=1668339922l,
01655           long modulus_=2147483647l, long seed_=0l, long b_=123567893l);
01656   };
01657 
01658   inline long YARN4::rand(void) {
01659     long t=R.rand();
01660     return (t==0) ? 0 : b(t);
01661   }
01662 
01663   // -------------------------------------------------------------------
01664 
01666 
01679   class CLCG2 : public RNG<CLCG2> {
01680   private:
01681     generic_MLCG R1;
01682     generic_MLCG R2;
01683     long modulus;
01684   public:
01685     static const RNG_type type=CLCG2_t;
01686     const char * name(void);
01687     void reset(void);
01688     void seed(long s=0l);
01689     long rand(void);    
01690     void split(long s, long n);
01691     void jump2(long s);
01692     void save_status(std::vector<long> &s);    
01693     void load_status(const std::vector<long> &s);    
01694     CLCG2 & CLCG2::operator=(RNG<CLCG2> &other);
01696 
01716     CLCG2(long a1= 376555083l, long m1=2147482951l,
01717           long a2=1028879659l, long m2=2147482949l, 
01718           long seed_=0l);    
01719   };
01720 
01721   inline long CLCG2::rand(void) {
01722     return static_cast<long>((static_cast<long long>(R1.rand())+
01723                               static_cast<long long>(R2.rand()))%
01724                              modulus);
01725   }
01726   
01727   // -------------------------------------------------------------------
01728 
01730 
01744   class CLCG3 : public RNG<CLCG3> {
01745   private:
01746     generic_MLCG R1;
01747     generic_MLCG R2;
01748     generic_MLCG R3;
01749     long modulus;
01750   public:
01751     static const RNG_type type=CLCG3_t;
01752     const char * name(void);
01753     void reset(void);
01754     void seed(long s=0l);
01755     long rand(void);
01756     void split(long s, long n);
01757     void jump2(long s);
01758     void save_status(std::vector<long> &s);
01759     void load_status(const std::vector<long> &s);
01760     CLCG3 & CLCG3::operator=(RNG<CLCG3> &other);
01762 
01786     CLCG3(long a1= 376555083l, long m1=2147482951l,
01787           long a2=1028879659l, long m2=2147482949l,
01788           long a3= 225802979l, long m3=2147482943l,
01789           long seed_=0l);    
01790   };
01791 
01792   inline long CLCG3::rand(void) {
01793     return static_cast<long>((static_cast<long long>(R1.rand())+
01794                               static_cast<long long>(R2.rand())+
01795                               static_cast<long long>(R3.rand()))%
01796                            modulus);
01797   }
01798   
01799   // -------------------------------------------------------------------
01800 
01802 
01817   class CLCG4 : public RNG<CLCG4> {
01818   private:
01819     generic_MLCG R1;
01820     generic_MLCG R2;
01821     generic_MLCG R3;
01822     generic_MLCG R4;
01823     long modulus;
01824   public:
01825     static const RNG_type type=CLCG4_t;
01826     const char * name(void);
01827     void reset(void);
01828     void seed(long s=0l);
01829     long rand(void);
01830     void split(long s, long n);
01831     void jump2(long s);
01832     void save_status(std::vector<long> &s);  
01833     void load_status(const std::vector<long> &s);
01834     CLCG4 & CLCG4::operator=(RNG<CLCG4> &other);
01836 
01864     CLCG4(long a1= 376555083l, long m1=2147482951l,
01865           long a2=1028879659l, long m2=2147482949l,
01866           long a3= 225802979l, long m3=2147482943l,
01867           long a4=2028073966l, long m4=2147482859l,
01868           long seed_=0l);    
01869   };
01870 
01871   inline long CLCG4::rand(void) {
01872     return static_cast<long>((static_cast<long long>(R1.rand())+
01873                               static_cast<long long>(R2.rand())+
01874                               static_cast<long long>(R3.rand())+
01875                               static_cast<long long>(R4.rand()))%
01876                              modulus);
01877   }
01878     
01879   // -------------------------------------------------------------------
01880 
01882 
01895   class EINV : public RNG<EINV> {
01896   private:
01897     long a, i, di, modulus, a_save;
01898     long modulo_invers(const long a);
01899   public:
01900     static const RNG_type type=EINV_t;
01901     const char * name(void);
01902     void reset(void);
01903     void seed(long s=0l);
01904     long rand(void);
01905     void split(long s, long n);
01906     void jump2(long s);
01907     void save_status(std::vector<long> &s);
01908     void load_status(const std::vector<long> &s);
01909     EINV & EINV::operator=(RNG<EINV> &other);
01911 
01916     EINV(long a_=1073741831l, long seed_=0l);    
01917   };
01918 
01919   inline long EINV::rand(void) {
01920     i=static_cast<long>
01921       ((static_cast<long long>(i)+
01922         static_cast<long long>(di))%modulus);
01923     long x=static_cast<long>((static_cast<long long>(a)*
01924                               static_cast<long long>(i))%modulus);
01925     // invert x
01926     long temp, q, flast=0, f=1, m=modulus;
01927     while (x>1) {
01928       temp=m%x; 
01929       q=m/x;
01930       m=x;  
01931       x=temp;  
01932       temp=f; 
01933       f=flast-q*f; 
01934       flast=temp;
01935     }
01936     return a==0 ? 0 : f>=0 ? f : f+modulus;
01937   }
01938   
01939   // -------------------------------------------------------------------
01940 
01942 
01954   class EINVLCG64 : public RNG<EINVLCG64> {
01955   private:
01956     LCG64 R1;
01957     EINV R2;
01958   public:
01959     static const RNG_type type=EINVLCG64_t;
01960     const char * name(void);
01961     void reset(void);
01962     void seed(long s=0l);    
01963     long rand(void);
01964     void split(long s, long n);
01965     void jump2(long s);
01966     void save_status(std::vector<long> &s);
01967     void load_status(const std::vector<long> &s);    
01968     EINVLCG64 & EINVLCG64::operator=(RNG<EINVLCG64> &other);
01970 
01973     EINVLCG64(long seed_=0l);    
01974   };
01975 
01976   inline long EINVLCG64::rand(void) {
01977     return (R1.rand()+R2.rand())&0x7fffffffl;
01978   }
01979 
01980 }
01981 
01982 
01983 #endif

Generated on Wed Feb 19 02:00:03 2003 for Tina's Random Number Generators by doxygen1.2.15