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

trng.h

00001 // ---------------------------------------------------------------------
00002 // Time-stamp: <Mittwoch, 26.03.2003, 12:05:43; edited by bauke>
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 "3"
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     MRG5_t,         
00054     YARNLCG64_t,    
00055     YARN2_t,        
00056     YARN3_t,        
00057     YARN4_t,        
00058     YARN5_t,        
00059     CLCG2_t,        
00060     CLCG3_t,        
00061     CLCG4_t,        
00062     EINV_t,         
00063     EINVLCG64_t,    
00064     trng_gsl_t,     
00065     user1_t=1001,   
00066     user2_t=1002,   
00067     user3_t=1003,   
00068     user4_t=1004,   
00069     user5_t=1005    
00070   };   
00071  
00073   struct vector2d_struct {
00075     double x1;
00077     double x2;
00078   };
00079 
00081 
00085   typedef struct vector2d_struct vector2d;
00086   
00088   struct vector3d_struct {
00090     double x1;
00092     double x2;
00094     double x3;
00095   };
00096 
00098 
00102   typedef struct vector3d_struct vector3d;
00103 
00105   struct vector4d_struct {
00107     double x1;
00109     double x2;
00111     double x3;
00113     double x4;
00114   };
00115 
00117 
00121   typedef struct vector4d_struct vector4d;
00122 
00123   // -------------------------------------------------------------------
00124 
00126 
00135   template<class RNG_type> class RNG {
00136   private:
00137     RNG_type & derived(void) {
00138       return static_cast<RNG_type &>(*this);
00139     }
00140     
00141   protected:
00143     long max_val;
00145     long max_val2;
00146   public:
00148 
00151     static const TRNG::RNG_type type=RNG_t;
00152     
00154 
00159     const char * name(void) {
00160       return derived().name(); 
00161     }
00162     
00164 
00168     void reset(void)  { 
00169       derived().reset(); 
00170     }
00171     
00173 
00181     void seed(long s=0l) { 
00182       derived().seed(s);
00183     }
00184     
00186 
00193     long rand(void) { 
00194       return derived().rand(); 
00195     }
00196 
00198 
00201     long max(void) {
00202       return max_val;
00203     };
00204     
00206 
00210     bool boolean(void) {
00211       return (rand()<=max_val2) ? true : false;
00212     }
00213 
00215 
00219     bool boolean(const double p) {
00220       return (rand()<static_cast<long>(p*max())+1.0) ? true : false;
00221     }
00222     
00224 
00227     double uniform(void) {
00228       return uniformco();
00229     }
00230 
00232 
00237     double uniform(const double a, const double b) {
00238       return uniformco(a, b);
00239     }
00240 
00242 
00245     double uniformco(void) {
00246       return static_cast<double>(rand())/
00247         (static_cast<double>(max())+1.0);
00248     }
00249 
00251 
00256     double uniformco(const double a, const double b) {
00257       return a+(b-a)*static_cast<double>(rand())/
00258         (static_cast<double>(max())+1.0);
00259     }
00260 
00262 
00265     double uniformcc(void) {
00266       return static_cast<double>(rand())/
00267         static_cast<double>(max());
00268     }
00269     
00271 
00276     double uniformcc(const double a, const double b) {
00277       return a+(b-a)*static_cast<double>(rand())/
00278         static_cast<double>(max());
00279     }
00280 
00282 
00285     double uniformoc(void) {
00286       return (static_cast<double>(rand())+1.0)/
00287         (static_cast<double>(max())+1.0);
00288     }
00289     
00291 
00296     double uniformoc(const double a, const double b) {
00297       return a+(b-a)*(static_cast<double>(rand())+1.0)/
00298         (static_cast<double>(max())+1.0);
00299     }
00300     
00302 
00305     double uniformoo(void) {
00306       return (static_cast<double>(rand())+1.0)/
00307         (static_cast<double>(max())+2.0);
00308     }
00309 
00311 
00316     double uniformoo(const double a, const double b) {
00317       return a+(b-a)*(static_cast<double>(rand())+1.0)/
00318         (static_cast<double>(max())+2.0);
00319     }
00320     
00322 
00326     long uniforml(const long b) {
00327       return static_cast<long>(uniform(0.0, static_cast<double>(b)));
00328     }
00329     
00331 
00336     long uniforml(const long a, const long b) {
00337       return static_cast<long>(uniform(static_cast<double>(a),
00338                                        static_cast<double>(b)));
00339     }
00340     
00342 
00356     double normal_dist(const double sigma=1.0, const double mu=0.0) {
00357       double s, t1, t2;
00358       if (sigma<=0.0)
00359         throw error("negative or zero standard deviation in TRNG::RNG::normal_dist");
00360       do {
00361         t1=uniformoo(-1.0, 1.0);
00362         t2=uniformoo(-1.0, 1.0);
00363         s=t1*t1+t2*t2;
00364       } while (s>=1.0);
00365       s=std::sqrt(-2.0*std::log(s)/s);
00366       return t1*s*sigma+mu;
00367     }
00368 
00370 
00389     double exp_dist(const double mu=1.0) {
00390       if (mu<=0.0)
00391         throw error("negative or zero parameter in TRNG::RNG::exp_dist");
00392       double t=uniformoc();
00393       return -mu*std::log(t);
00394     }
00395 
00397 
00411     double laplace_dist(const double a=1.0) {
00412       if (a<=0.0)
00413         throw error("parameter less or equal zero in TRNG::RNG::laplace_dist");
00414       double u;
00415       do {
00416         u=uniformoo(-1.0, 1.0);
00417       } while (u==0.0);
00418       return u<0.0 ? a*std::log(-u) : -a*std::log(u);
00419     }
00420 
00422 
00442     double tent_dist(const double a=1.0) {
00443       if (a<=0.0)
00444         throw error("parameter less or equal zero in TRNG::RNG::tent_dist");
00445       double y=uniformoo();
00446       if (y<0.5)
00447         return (-1.0+std::sqrt(2*y))*a;
00448       else
00449         return (1.0-std::sqrt(2.0-2.0*y))*a;
00450     }
00451     
00453 
00472     double Gamma_dist(const double a, const double b) {
00473       if (a<=0.0 || b<=0.0)
00474         throw error("parameter less or equal zero in TRNG::RNG::Gamma_dist");
00475       double a_int=std::floor(a);
00476       if (a_int==a) {
00477         // if a is an integer
00478         if (a<12) {
00479           double prod=1.0;
00480           for (int i=0; i<a; ++i)
00481             prod*=uniformoo();
00482           // Note: for 12 iterations we are safe against underflow, since
00483           // the smallest positive random number is O(2^-32). This means
00484           // the smallest possible product is 2^(-12*32) = 10^-116 which
00485           // is within the range of double precision.
00486           return -b*std::log(prod);
00487         } else {
00488           // Works only if a>1, and is most efficient if a is large
00489           // This algorithm, reported in Knuth, is attributed to Ahrens.  A
00490           // faster one, we are told, can be found in: J. H. Ahrens and
00491           // U. Dieter, Computing 12 (1974) 223-246.
00492           double sqa, x, y, v;
00493           sqa=std::sqrt(2.0*a-1.0);
00494           do {
00495             do {
00496               const double pi=3.14159265358979324;
00497               y=std::tan(pi*uniformco());
00498               x=sqa*y+a-1.0;
00499             }
00500             while (x<=0.0);
00501             v=uniformco();
00502           }
00503           while (v>(1.0+y*y)*std::exp((a-1.0)*log(x/(a-1))-sqa*y));
00504           return b*x;
00505         }
00506       }
00507       if (a_int==0.0) {
00508         // if a<1
00509         // This is exercise 16 from Knuth; see page 135, and the solution is
00510         // on page 551.
00511         const double e=2.71828182844;
00512         double p, q, x, u, v;
00513         p=e/(a+e);
00514         do {
00515           u=uniformco();
00516           v=uniformoo();
00517           if (u<p) {
00518             x=std::exp((1.0/a)*std::log(v));
00519             q=std::exp(-x);
00520           } else {
00521             x=1.0-std::log(v);
00522             q=std::exp((a-1.0)*std::log(x));
00523           }
00524         } while (uniformco()>=q);
00525         return b*x;
00526       }
00527       return Gamma_dist(a_int, b)+Gamma_dist(a-a_int, b); 
00528     }
00529 
00531 
00550     double Beta_dist(const double a, const double b) {
00551       if (a<=0.0 || b<=0.0)
00552         throw error("negative or zero parameter in TRNG::RNG::Beta_dist");
00553       double t1=Gamma_dist(a, 1.0);
00554       double t2=Gamma_dist(b, 1.0);
00555       return t1/(t1+t2);
00556     }
00557 
00559 
00575     double chi_square_dist(const double nu) {
00576       if (nu<1.0)
00577         throw error("parameter less than one in TRNG::RNG::chi_square_dist");
00578       return 2.0*Gamma_dist(0.5*nu, 1.0);
00579     }
00580 
00582 
00597     long binomial_dist(long n, double p=0.5) {
00598       if (p<=0.0 || p>1.0)
00599         throw error("probability <=0.0 or >1.0 in TRNG::RNG::binomial_dist");
00600       if (n<1l)
00601         throw error("less than one trail TRNG::RNG::binomial_dist");
00602       long i, a, b, k=0;
00603       while (n>12l) {  // This parameter is tunable
00604         double X;
00605         a=1l+(n/2l);
00606         b=1l+n-a;
00607         X=Beta_dist(static_cast<double>(a), static_cast<double>(b));
00608         if (X>=p) {
00609           n=a-1l;
00610           p/=X;
00611         } else {
00612           k+=a;
00613           n=b-1l;
00614           p=(p-X)/(1l-X);
00615         }
00616       }
00617       for (i=0l; i<n; i++)
00618         if (uniformco()<p)
00619           k++;
00620       return k;
00621     }
00622 
00624 
00637     long binomial_dist_tab(long n, double p=0.5) {
00638       if (p<=0.0 || p>1.0)
00639         throw error("probability <=0.0 or >1.0 in TRNG::RNG::binomial_dist_tab");
00640       if (n<1l)
00641         throw error("less than one trail TRNG::RNG::binomial_dist_tab");
00642       static long n_=0l;
00643       static double p_=0.0;
00644       static std::vector<double> prob;
00645       if (n!=n_ || p!=p_) {
00646         n_=n;
00647         p_=p;
00648         prob.resize(n_);
00649         // use
00650         // ( n )            (  n  )   n-k ( n )
00651         // (   ) = 1  and   (     ) = --- (   )
00652         // ( 0 )            ( k+1 )   k+1 ( k )
00653         double b=1.0;
00654         for (int k=0l; k<n_; ++k) {
00655           prob[k]=b*std::pow(p_, static_cast<double>(k))*
00656             std::pow(1.0-p_, static_cast<double>(n_-k));
00657           if (k>0l)
00658             prob[k]+=prob[k-1l];
00659           b=std::floor(b*static_cast<double>(n_-k)/
00660                        static_cast<double>(k+1l)+0.5); 
00661         }
00662       }
00663       return find_interval(prob, uniformco());
00664     }
00665 
00667 
00683     double Student_t_dist(const double nu) {
00684       if (nu<=0.0)
00685         throw error("parameter less than or equal zero in TRNG::RNG::Student_t_dist");
00686       if (nu<=2.0) 
00687         return normal_dist()/std::sqrt(chi_square_dist(nu)/nu);
00688       else {
00689         double y1, y2, z;
00690         do {
00691           y1=normal_dist();
00692           y2=exp_dist(1.0/(0.5*nu-1.0));
00693           z=y1*y1/(nu-2.0);
00694         } while (1.0-z<0.0 || std::exp(-y2-z)>(1.0-z));
00695         // Note that there is a typo in Knuth's formula, the line below
00696         // is taken from the original paper of Marsaglia, Mathematics of
00697         // Computation, 34 (1980), p 234-256 
00698         return y1/std::sqrt((1.0-2.0/nu)*(1.0-z));
00699       }
00700     }
00701 
00703 
00715     long poisson_dist(double mu=1.0) {
00716       if (mu<=0)
00717         throw error("parameter less than 0 in TRNG::RNG::poisson_dist");
00718       double emu;
00719       double prod=1.0;
00720       long k=0;  
00721       while (mu>10.0) {
00722         long m=static_cast<long>(mu*(7.0/8.0));
00723         double X=Gamma_dist(static_cast<long>(m), 1.0);
00724         if (X>=mu) {
00725           return k+binomial_dist(m-1l, mu/X);
00726         } else {
00727           k+=m;
00728           mu-=X; 
00729         }
00730       }
00731       // This following method works well when mu is small
00732       emu=std::exp(-mu);
00733       do {
00734         prod*=uniformco();
00735         k++;
00736       } while (prod>emu);
00737       return k-1l;
00738     }
00739 
00741 
00753     long geometric_dist(double q) {
00754       if (q<=0.0 ||q>1.0)
00755         throw error("parameter out of range in TRNG::RNG::geometric_dist");
00756       if (q==1.0)
00757         return 1l;
00758       return static_cast<long>
00759         (std::log(uniformoo())/std::log(1.0-p))+1l;
00760     }
00761 
00763 
00789     template<class t_function>
00790       double rejection(t_function p, double a1, double a2, double p_max)  {
00791       double t1, t2;
00792       do {
00793         t1=uniformco(a1, a2);
00794         t2=uniformco(0.0, p_max);
00795       } while (p(t1)<t2);
00796       return t1;
00797     }
00798 
00800 
00812     long discrete_dist(const std::vector<double> p) {
00813       if (p.empty())
00814         throw error("empty vector in TRNG::discrete_dist");
00815       double x=uniformco();
00816       if (x<p[0])
00817         return 0l;
00818       long i1=0l;
00819       long i2=p.size()-1l;
00820       while (i2-i1>1l) {
00821         long i3=(i2+i1)/2;
00822         if (x<=p[i3])
00823           i2=i3;
00824         else
00825           i1=i3;
00826       }
00827       return i2;
00828     }
00829 
00831 
00839     vector2d spherical2d(void) {
00840       double r2, t1, t2, t12, t22;
00841       vector2d vec;
00842       do {
00843         t1=2.0*uniformco()-1.0;
00844         t2=uniformco();
00845         t12=t1*t1;
00846         t22=t2*t2;
00847         r2=t12+t22;
00848       } while (r2>1.0);
00849       vec.x1=2.0*t1*t2/r2;
00850       vec.x2=(t12-t22)/r2;
00851       return vec;
00852     }
00853 
00855 
00863     vector3d spherical3d(void)  {
00864       double q, r2, t1, t2;
00865       vector3d vec;
00866       do {
00867         t1=2.0*uniformco()-1.0;
00868         t2=2.0*uniformco()-1.0;
00869         r2=t1*t1+t2*t2;
00870       } while (r2>1.0);
00871       q=2.0*sqrt(1.0-r2);
00872       vec.x1=t1*q;
00873       vec.x2=t2*q;
00874       vec.x3=1-2*r2;
00875       return vec;
00876     }
00877 
00879 
00887     vector4d spherical4d(void)  {
00888       double q, r21, r22, t1, t2, t3, t4;
00889       vector4d vec;
00890       do {
00891         t1=2.0*uniformco()-1.0;
00892         t2=2.0*uniformco()-1.0;
00893         r21=t1*t1+t2*t2;
00894       } while (r21>1.0);
00895       do {
00896         t3=2.0*uniformco()-1.0;
00897         t4=2.0*uniformco()-1.0;
00898         r22=t3*t3+t4*t4;
00899       } while (r22>1.0);
00900       q=sqrt((1.0-r21)/r22);
00901       vec.x1=t1;
00902       vec.x2=t2;
00903       vec.x3=t3*q;
00904       vec.x4=t4*q;
00905       return(vec);
00906     }
00907 
00909 
00918     void split(long s, long n) {
00919       derived().split(s, n);
00920     }
00921 
00923 
00929     void jump(long long s) {
00930       if (s<0ll)
00931         throw error("invalid argument for TRNG::RNG::jump");
00932       long i=0l;
00933       while (s>0ll) {
00934         if (s%2==1)
00935           jump2(i);
00936         ++i;
00937         s>>=1;
00938       }
00939     }
00940 
00942 
00950     void jump(long long s, long n) {
00951       if (s<0ll || n<0l)
00952         throw error("invalid argument for TRNG::RNG::jump");
00953       while (n>0l) {
00954         jump(s);
00955         --n;
00956       }
00957     }
00958 
00960 
00966     void jump2(long s) {
00967       derived().jump2(s);
00968     }
00969 
00971 
00978     void jump2(long s, long n) {
00979       if (s<0l || n<0l)
00980         throw error("invalid argument for TRNG::RNG::jump2");
00981       while (n>0l) {
00982         if (n%2l==1l)
00983           jump2(s);
00984         s+=1l;
00985         n>>=1;
00986       }
00987     }
00988 
00990 
00995     void save_status(std::vector<long> &s) {
00996       derived().save_status(s);
00997     }
00998 
01000 
01005     void load_status(const std::vector<long> &s) {
01006       derived().load_status(s);
01007     }
01008 
01009 //     //! generic copy constructor
01010 //     /*!
01011 //       This is the random number generator copy constructor. Useful if
01012 //       some generators with the same sequence of random numbers are needed.
01013 //      */
01014 //     RNG<RNG_type> & RNG<RNG_type>::operator=(RNG<RNG_type> &other) {
01015 //       if (this!=&other) {
01016 //      std::vector<long> s;
01017 //      other.save_status(s);
01018 //      load_status(s);
01019 //       }
01020 //       return *this;
01021 //     }
01022     
01023   };
01024 
01025   // --------------------------------------------------------------------
01026 
01028 
01044   class generic_MLCG : public RNG<generic_MLCG> {
01045     // generic class for multiplicative linear congruential 
01046     // random number generators
01047   private:
01048     long a, a_save;
01049     long modulus, modulus_save;
01050     long r;
01051     void backward(void);
01052   public:
01053     static const RNG_type type=generic_MLCG_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);
01062     generic_MLCG & generic_MLCG::operator=(RNG<generic_MLCG> &other);
01063     generic_MLCG(long a_=16807l, long modulus_=2147483647l, long seed_=0l);
01064   };
01065 
01066   inline long generic_MLCG::rand(void) {
01067     if (modulus==2147483647l) {
01068       unsigned long long t=
01069         static_cast<unsigned long long>(a)*static_cast<unsigned long long>(r);
01070       t=(t&0x7fffffffull)+(t>>31);
01071       r=(t>=2147483647ul) ?  (t-2147483647ul) : t;
01072       return r;
01073     } else {
01074       r=static_cast<long>
01075         ((static_cast<long long>(a)*static_cast<long long>(r))%modulus);
01076       return r;
01077     }
01078   }
01079 
01080   // -------------------------------------------------------------------
01081 
01083 
01091   class ParkMiller_param {
01092   public:
01093     const long a;  
01094     const long modulus;  
01095 
01101     ParkMiller_param(long a_, long modulus_) :
01102       a(a_), modulus(modulus_) { };
01103   };
01104 
01106   namespace ParkMiller_param_sets {
01108     const ParkMiller_param mindstd=ParkMiller_param(16807l, 2147483647l);
01110     const ParkMiller_param Fishman1=ParkMiller_param(742938285l, 2147483647l);
01112     const ParkMiller_param Fishman2=ParkMiller_param(950706376l, 2147483647l);
01114     const ParkMiller_param Fishman3=ParkMiller_param(1226874159l, 2147483647l);
01116     const ParkMiller_param Fishman4=ParkMiller_param(62089911l, 2147483647l);
01118     const ParkMiller_param Fishman5=ParkMiller_param(1343714438l, 2147483647l);
01119   }
01120 
01122 
01137   class ParkMiller : public RNG<ParkMiller> {
01138   private:
01139     generic_MLCG R;
01140   public:
01141     static const RNG_type type=ParkMiller_t;
01142     const char * name(void);    
01143     void reset(void);
01144     void seed(long s=0l);
01145     long rand(void);
01146     void split(long s, long n);
01147     void jump2(long s);
01148     void save_status(std::vector<long> &s);
01149     void load_status(const std::vector<long> &s);
01150     ParkMiller & ParkMiller::operator=(RNG<ParkMiller> &other); 
01152 
01161     ParkMiller(ParkMiller_param param=ParkMiller_param_sets::mindstd,
01162                long seed_=0l);
01163   };
01164 
01165   inline long ParkMiller::rand(void) {
01166     return R.rand()-1l;
01167   }
01168   
01169   // -------------------------------------------------------------------
01170 
01172 
01180   class LCG32_param {
01181   public:
01182     const unsigned long a;  
01183     const unsigned long b;  
01184 
01190     LCG32_param(unsigned long a_, unsigned long b_) :
01191       a(a_), b(b_) { };
01192   };
01193 
01195   namespace LCG32_param_sets {
01197     const LCG32_param VAX=LCG32_param(69069ul, 1ul);
01199     const LCG32_param SuperDuper=LCG32_param(69069ul, 0ul);
01201     const LCG32_param Derive=LCG32_param(3141592653ul, 1ul);
01203     const LCG32_param LEcuyer1=LCG32_param(2891336453ul, 1ul);
01205     const LCG32_param LEcuyer2=LCG32_param(29943829ul, 1ul);
01207     const LCG32_param LEcuyer3=LCG32_param(32310901ul, 1ul);
01208   }
01209 
01211 
01227   class LCG32 : public RNG<LCG32> {
01228   private:
01229     unsigned long a, a_save;
01230     unsigned long b, b_save;
01231     unsigned long r;
01232     void backward(void);
01233   public:
01234     static const RNG_type type=LCG32_t;
01235     const char * name(void);
01236     void reset(void);
01237     void seed(long s=0l);    
01238     long rand(void);    
01239     void split(long s, long n);    
01240     void jump2(long s);    
01241     void save_status(std::vector<long> &s);    
01242     void load_status(const std::vector<long> &s);
01243     LCG32 & LCG32::operator=(RNG<LCG32> &other);
01245 
01253     LCG32(LCG32_param param=LCG32_param_sets::VAX, long seed_=0l);
01254   };
01255 
01256   inline long LCG32::rand(void) {
01257     r=a*r+b;
01258 #if ULONG_MAX == 0xfffffffful
01259 #else
01260     r&=0xfffffffful;
01261 #endif
01262     return static_cast<long>(r>>1);
01263   }
01264 
01265   // -------------------------------------------------------------------
01266 
01268 
01276   class LCG64_param {
01277   public:
01278     const unsigned long long a;  
01279     const unsigned long long b;  
01280 
01286     LCG64_param(unsigned long long a_, unsigned long long b_) :
01287       a(a_), b(b_) { };
01288   };
01289 
01291   namespace LCG64_param_sets {
01293     const LCG64_param TRNG=LCG64_param(18145460002477866997ull, 1ull);
01295     const LCG64_param LEcuyer1=LCG64_param(2862933555777941757ull, 1ull);
01297     const LCG64_param LEcuyer2=LCG64_param(3202034522624059733ull, 1ull);
01299     const LCG64_param LEcuyer3=LCG64_param(3935559000370003845ull, 1ull);
01300   }
01301 
01303 
01317   class LCG64 : public RNG<LCG64> {
01318   private:
01319     unsigned long long a, a_save;
01320     unsigned long long b, b_save;
01321     unsigned long long r;
01322     void backward(void);
01323   public:
01324     static const RNG_type type=LCG64_t;
01325     const char * name(void);
01326     void reset(void);
01327     void seed(long s=0l);
01328     long rand(void);
01329     void split(long s, long n);
01330     void jump2(long s);    
01331     void save_status(std::vector<long> &s);    
01332     void load_status(const std::vector<long> &s);
01333     LCG64 & LCG64::operator=(RNG<LCG64> &other);
01335 
01343     LCG64(LCG64_param param=LCG64_param_sets::TRNG, long seed_=0l);
01344   };
01345   
01346   inline long LCG64::rand(void) {
01347     r=a*r+b;
01348     return static_cast<long>(r>>33);
01349   }
01350 
01351   // -------------------------------------------------------------------
01352 
01354 
01362   class MRG2_param {
01363   public:
01364     const long a1;       
01365     const long a2;       
01366     const long modulus;  
01367 
01374     MRG2_param(long a1_, long a2_, long modulus_) :
01375       a1(a1_), a2(a2_), modulus(modulus_) { };
01376   };
01377 
01379   namespace MRG2_param_sets {
01381     const MRG2_param LEcuyer1=MRG2_param(1498809829l, 1160990996l, 2147483647l);
01383     const MRG2_param LEcuyer2=MRG2_param(46325l, 1084587l, 2147483647l);
01384   }
01385 
01387 
01395   class MRG2 : public RNG<MRG2> {
01396   private:
01397     long a1, a2, a1_save, a2_save;
01398     long r1, r2;
01399     long modulus, modulus_save;
01400     void backward(void);
01401   public:
01402     static const RNG_type type=MRG2_t;
01403     const char * name(void);    
01404     void reset(void);
01405     void seed(long s=0l);
01406     long rand(void);    
01407     void split(long s, long n);
01408     void jump2(long s);
01409     void save_status(std::vector<long> &s);
01410     void load_status(const std::vector<long> &s);    
01411     MRG2 & MRG2::operator=(RNG<MRG2> &other);
01413 
01423     MRG2(MRG2_param param=MRG2_param_sets::LEcuyer1, long seed_=0l);
01424   };
01425 
01426   inline long MRG2::rand(void) {
01427     unsigned long long t=
01428       static_cast<unsigned long long>(a1)*static_cast<unsigned long long>(r1)+
01429       static_cast<unsigned long long>(a2)*static_cast<unsigned long long>(r2);
01430     if (modulus==2147483647l) {
01431       t=(t&0x7fffffffull)+(t>>31);
01432       if (t>=2ull*2147483647ull)
01433         t-=2ull*2147483647ull;
01434       if (t>=2147483647ull)
01435         t-=2147483647ull;
01436     } else
01437       t%=modulus;
01438     r2=r1;  r1=t;
01439     return r1;
01440   }
01441 
01442   // -------------------------------------------------------------------
01443 
01445 
01453   class MRG3_param {
01454   public:
01455     const long a1;       
01456     const long a2;       
01457     const long a3;       
01458     const long modulus;  
01459 
01467     MRG3_param(long a1_, long a2_, long a3_, long modulus_) :
01468       a1(a1_), a2(a2_), a3(a3_), modulus(modulus_) { };
01469   };
01470 
01472   namespace MRG3_param_sets {
01474     const MRG3_param LEcuyer1=MRG3_param(2021422057l, 1826992351l, 1977753457l, 2147483647l);
01476     const MRG3_param LEcuyer2=MRG3_param(1476728729l, 0l, 1155643113l, 2147483647l);
01478     const MRG3_param LEcuyer3=MRG3_param(65338l, 0l, 64636l, 2147483647l);
01479   }
01480 
01482 
01490   class MRG3 : public RNG<MRG3> {
01491   private:
01492     long a1, a2, a3, a1_save, a2_save, a3_save;
01493     long r1, r2, r3;
01494     long modulus, modulus_save;
01495     void backward(void);
01496   public:
01497     static const RNG_type type=MRG3_t;
01498     const char * name(void);
01499     void reset(void);    
01500     void seed(long s=0l);
01501     long rand(void);   
01502     void split(long s, long n);
01503     void jump2(long s);    
01504     void save_status(std::vector<long> &s);
01505     void load_status(const std::vector<long> &s);
01506     MRG3 & MRG3::operator=(RNG<MRG3> &other);
01508 
01518     MRG3(MRG3_param param=MRG3_param_sets::LEcuyer1, long seed_=0l);
01519   };
01520 
01521   inline long MRG3::rand(void) {
01522     unsigned long long t=
01523       static_cast<unsigned long long>(a1)*static_cast<unsigned long long>(r1)+
01524       static_cast<unsigned long long>(a2)*static_cast<unsigned long long>(r2)+
01525       static_cast<unsigned long long>(a3)*static_cast<unsigned long long>(r3);
01526     if (modulus==2147483647l) {
01527       t=(t&0x7fffffffull)+(t>>31);
01528       if (t>=2ull*2147483647ull)
01529         t-=2ull*2147483647ull;
01530       if (t>=2147483647ull)
01531         t-=2147483647ull;
01532     } else
01533       t%=modulus;
01534     r3=r2;  r2=r1;  r1=t;
01535     return r1;
01536   }
01537     
01538   // -------------------------------------------------------------------
01539 
01541 
01549   class MRG4_param {
01550   public:
01551     const long a1;       
01552     const long a2;       
01553     const long a3;       
01554     const long a4;       
01555     const long modulus;  
01556 
01565     MRG4_param(long a1_, long a2_, long a3_, long a4_, long modulus_) :
01566       a1(a1_), a2(a2_), a3(a3_), a4(a4_), modulus(modulus_) { };
01567   };
01568 
01570   namespace MRG4_param_sets {
01572     const MRG4_param LEcuyer1=MRG4_param(2001982722l, 1412284257l, 1155380217l, 1668339922l, 2147483647l);
01574     const MRG4_param LEcuyer2=MRG4_param(64886l, 0l, 0l, 64322l, 2147483647l);
01575   }
01576 
01578 
01587   class MRG4 : public RNG<MRG4> {
01588   private:
01589     long a1, a2, a3, a4, a1_save, a2_save, a3_save, a4_save;
01590     long r1, r2, r3, r4;
01591     long modulus, modulus_save;
01592     void backward(void);
01593   public:
01594     static const RNG_type type=MRG4_t;
01595     const char * name(void);
01596     void reset(void);
01597     void seed(long s=0l);
01598     long rand(void);
01599     void split(long s, long n);
01600     void jump2(long s);
01601     void save_status(std::vector<long> &s);
01602     void load_status(const std::vector<long> &s);
01603     MRG4 & MRG4::operator=(RNG<MRG4> &other);
01605 
01616     MRG4(MRG4_param param=MRG4_param_sets::LEcuyer1, long seed_=0l);
01617   };
01618 
01619   inline long MRG4::rand(void) {
01620     unsigned long long t=
01621       static_cast<unsigned long long>(a1)*static_cast<unsigned long long>(r1)+
01622       static_cast<unsigned long long>(a2)*static_cast<unsigned long long>(r2)+
01623       static_cast<unsigned long long>(a3)*static_cast<unsigned long long>(r3)+
01624       static_cast<unsigned long long>(a4)*static_cast<unsigned long long>(r4);
01625     if (modulus==2147483647l) {
01626       t=(t&0x7fffffffull)+(t>>31);
01627       if (t>=4ull*2147483647ull)
01628         t-=4ull*2147483647ull;
01629       if (t>=2ull*2147483647ull)
01630         t-=2ull*2147483647ull;
01631       if (t>=2147483647ull)
01632         t-=2147483647ull;
01633     } else
01634       t%=modulus;
01635     r4=r3;  r3=r2;  r2=r1;  r1=t;
01636     return r1;
01637   }
01638 
01639   // -------------------------------------------------------------------
01640 
01642 
01651   class MRG5_param {
01652   public:
01653     const long a1;       
01654     const long a2;       
01655     const long a3;       
01656     const long a4;       
01657     const long a5;       
01658     const long modulus;  
01659 
01669     MRG5_param(long a1_, long a2_, long a3_, long a4_, long a5_, long modulus_) :
01670       a1(a1_), a2(a2_), a3(a3_), a4(a4_), a5(a5_), modulus(modulus_) { };
01671   };
01672 
01674   namespace MRG5_param_sets {
01676     const MRG5_param LEcuyer1=MRG5_param(177786l, 0l, 0l, 0l, 64654l, 2147483647l);
01677   }
01678 
01680 
01689   class MRG5 : public RNG<MRG5> {
01690   private:
01691     long a1, a2, a3, a4, a5, a1_save, a2_save, a3_save, a4_save, a5_save;
01692     long r1, r2, r3, r4, r5;
01693     long modulus, modulus_save;
01694     unsigned long long m2_2;
01695     void backward(void);
01696   public:
01697     static const RNG_type type=MRG5_t;
01698     const char * name(void);
01699     void reset(void);
01700     void seed(long s=0l);
01701     long rand(void);
01702     void split(long s, long n);
01703     void jump2(long s);
01704     void save_status(std::vector<long> &s);
01705     void load_status(const std::vector<long> &s);
01706     MRG5 & MRG5::operator=(RNG<MRG5> &other);
01708 
01719     MRG5(MRG5_param param=MRG5_param_sets::LEcuyer1, long seed_=0l);
01720   };
01721 
01722   inline long MRG5::rand(void) {
01723     unsigned long long t=
01724       static_cast<unsigned long long>(a1)*static_cast<unsigned long long>(r1)+
01725       static_cast<unsigned long long>(a2)*static_cast<unsigned long long>(r2)+
01726       static_cast<unsigned long long>(a3)*static_cast<unsigned long long>(r3)+
01727       static_cast<unsigned long long>(a4)*static_cast<unsigned long long>(r4);
01728     if (t>=m2_2)
01729       t-=m2_2;
01730     t+=static_cast<unsigned long long>(a5)*static_cast<unsigned long long>(r5);
01731     if (modulus==2147483647l) {
01732       t=(t&0x7fffffffull)+(t>>31);
01733       if (t>=2ull*2147483647ull)
01734         t-=2ull*2147483647ull;
01735       if (t>=2147483647ull)
01736         t-=2147483647ull;
01737     } else
01738       t%=modulus;
01739     r5=r4;  r4=r3;  r3=r2;  r2=r1;  r1=t;
01740     return r1;
01741   }
01742 
01743   // -------------------------------------------------------------------
01744 
01746 
01754   class YARNLCG64_param {
01755   public:
01756     const unsigned long long a;  
01757     const unsigned long long b;  
01758     const long g;                
01759 
01766     YARNLCG64_param(unsigned long long a_, unsigned long long b_, long g_) :
01767       a(a_), b(b_), g(g_) { };
01768   };
01769 
01771   namespace YARNLCG64_param_sets {
01773     const YARNLCG64_param TRNG=YARNLCG64_param(18145460002477866997ull, 1ull, 123567893l);
01775     const YARNLCG64_param LEcuyer1=YARNLCG64_param(2862933555777941757ull, 1ull, 123567893l);
01777     const YARNLCG64_param LEcuyer2=YARNLCG64_param(3202034522624059733ull, 1ull, 123567893l);
01779     const YARNLCG64_param LEcuyer3=YARNLCG64_param(3935559000370003845ull, 1ull, 123567893l);
01780   }
01781 
01783 
01806   class YARNLCG64 : public RNG<YARNLCG64> {
01807   private:
01808     LCG64 R;
01809     power g;
01810     long g_save;
01811   public:
01812     static const RNG_type type=YARNLCG64_t;
01813     const char * name(void);    
01814     void reset(void);
01815     void seed(long s=0l);
01816     long rand(void);    
01817     void split(long s, long n);
01818     void jump2(long s);
01819     void save_status(std::vector<long> &s);
01820     void load_status(const std::vector<long> &s);
01821     YARNLCG64 & YARNLCG64::operator=(RNG<YARNLCG64> &other); 
01823 
01831     YARNLCG64(YARNLCG64_param param=YARNLCG64_param_sets::TRNG, long seed_=0l);
01832   };
01833 
01834   inline long YARNLCG64::rand(void) {
01835     long t=R.rand();
01836     return (t==0 || t==2147483647l) ? t : g(t);
01837   }
01838 
01839   // -------------------------------------------------------------------
01840 
01842 
01857   class YARN2_param {
01858   public:
01859     const long a1;       
01860     const long a2;       
01861     const long modulus;  
01862     const long g;        
01863 
01871     YARN2_param(long a1_, long a2_, long modulus_, long g_) :
01872       a1(a1_), a2(a2_), modulus(modulus_), g(g_) { };
01873   };
01874 
01876   namespace YARN2_param_sets {
01878     const YARN2_param LEcuyer1=YARN2_param(1498809829l, 1160990996l, 2147483647l, 123567893l);
01880     const YARN2_param LEcuyer2=YARN2_param(46325l, 1084587l, 2147483647l, 123567893l);
01881   }
01882   
01884 
01901   class YARN2 : public RNG<YARN2> {
01902   private:
01903     MRG2 R;
01904     power g;
01905     long g_save;
01906   public:
01907     static const RNG_type type=YARN2_t;
01908     const char * name(void);    
01909     void reset(void);
01910     void seed(long s=0l);
01911     long rand(void);    
01912     void split(long s, long n);
01913     void jump2(long s);
01914     void save_status(std::vector<long> &s);
01915     void load_status(const std::vector<long> &s);
01916     YARN2 & YARN2::operator=(RNG<YARN2> &other); 
01918 
01929     YARN2(YARN2_param param=YARN2_param_sets::LEcuyer1, long seed_=0l);
01930   };
01931 
01932   inline long YARN2::rand(void) {
01933     long t=R.rand();
01934     return (t==0) ? 0 : g(t);
01935   }
01936 
01937   // -------------------------------------------------------------------
01938 
01940 
01955   class YARN3_param {
01956   public:
01957     const long a1;       
01958     const long a2;       
01959     const long a3;       
01960     const long modulus;  
01961     const long g;        
01962 
01971     YARN3_param(long a1_, long a2_, long a3_, long modulus_, long g_) :
01972       a1(a1_), a2(a2_), a3(a3_), modulus(modulus_), g(g_) { };
01973   };
01974 
01976   namespace YARN3_param_sets {
01978     const YARN3_param LEcuyer1=YARN3_param(2021422057l, 1826992351l, 1977753457l, 2147483647l, 123567893l);
01980     const YARN3_param LEcuyer2=YARN3_param(1476728729l, 0l, 1155643113l, 2147483647l, 123567893l);
01982     const YARN3_param LEcuyer3=YARN3_param(65338l, 0l, 64636l, 2147483647l, 123567893l);
01983   }
01984 
01986 
02003   class YARN3 : public RNG<YARN3> {
02004   private:
02005     MRG3 R;
02006     power g;
02007     long g_save;
02008   public:
02009     static const RNG_type type=YARN3_t;
02010     const char * name(void);    
02011     void reset(void);
02012     void seed(long s=0l);
02013     long rand(void);    
02014     void split(long s, long n);
02015     void jump2(long s);
02016     void save_status(std::vector<long> &s);
02017     void load_status(const std::vector<long> &s);
02018     YARN3 & YARN3::operator=(RNG<YARN3> &other); 
02020 
02031     YARN3(YARN3_param param=YARN3_param_sets::LEcuyer1, long seed_=0l);
02032   };
02033 
02034   inline long YARN3::rand(void) {
02035     long t=R.rand();
02036     return (t==0) ? 0 : g(t);
02037   }
02038 
02039   // -------------------------------------------------------------------
02040 
02042 
02058   class YARN4_param {
02059   public:
02060     const long a1;       
02061     const long a2;       
02062     const long a3;       
02063     const long a4;       
02064     const long modulus;  
02065     const long g;        
02066 
02076     YARN4_param(long a1_, long a2_, long a3_, long a4_, long modulus_, long g_) :
02077       a1(a1_), a2(a2_), a3(a3_), a4(a4_), modulus(modulus_), g(g_) { };
02078   };
02079 
02081   namespace YARN4_param_sets {
02083     const YARN4_param LEcuyer1=YARN4_param(2001982722l, 1412284257l, 1155380217l, 1668339922l, 2147483647l, 123567893l);
02085     const YARN4_param LEcuyer2=YARN4_param(64886l, 0l, 0l, 64322l, 2147483647l, 123567893l);
02086   }
02087 
02089 
02107   class YARN4 : public RNG<YARN4> {
02108   private:
02109     MRG4 R;
02110     power g;
02111     long g_save;
02112   public:
02113     static const RNG_type type=YARN4_t;
02114     const char * name(void);    
02115     void reset(void);
02116     void seed(long s=0l);
02117     long rand(void);    
02118     void split(long s, long n);
02119     void jump2(long s);
02120     void save_status(std::vector<long> &s);
02121     void load_status(const std::vector<long> &s);
02122     YARN4 & YARN4::operator=(RNG<YARN4> &other); 
02124 
02136     YARN4(YARN4_param param=YARN4_param_sets::LEcuyer1, long seed_=0l);
02137   };
02138 
02139   inline long YARN4::rand(void) {
02140     long t=R.rand();
02141     return (t==0) ? 0 : g(t);
02142   }
02143 
02144   // -------------------------------------------------------------------
02145 
02147 
02163   class YARN5_param {
02164   public:
02165     const long a1;       
02166     const long a2;       
02167     const long a3;       
02168     const long a4;       
02169     const long a5;       
02170     const long modulus;  
02171     const long g;        
02172 
02183     YARN5_param(long a1_, long a2_, long a3_, long a4_, long a5_, long modulus_, long g_) :
02184       a1(a1_), a2(a2_), a3(a3_), a4(a4_), a5(a5_), modulus(modulus_), g(g_) { };
02185   };
02186 
02188   namespace YARN5_param_sets {
02190     const YARN5_param LEcuyer1=YARN5_param(177786l, 0l, 0l, 0l, 64654l, 2147483647l, 123567893l);
02191   }
02192 
02194 
02212   class YARN5 : public RNG<YARN5> {
02213   private:
02214     MRG5 R;
02215     power g;
02216     long g_save;
02217   public:
02218     static const RNG_type type=YARN4_t;
02219     const char * name(void);    
02220     void reset(void);
02221     void seed(long s=0l);
02222     long rand(void);    
02223     void split(long s, long n);
02224     void jump2(long s);
02225     void save_status(std::vector<long> &s);
02226     void load_status(const std::vector<long> &s);
02227     YARN5 & YARN5::operator=(RNG<YARN5> &other); 
02229 
02241     YARN5(YARN5_param param=YARN5_param_sets::LEcuyer1, long seed_=0l);
02242   };
02243 
02244   inline long YARN5::rand(void) {
02245     long t=R.rand();
02246     return (t==0) ? 0 : g(t);
02247   }
02248 
02249   // -------------------------------------------------------------------
02250 
02252 
02257   class CLCG2_param {
02258   public:
02259     const long a1;        
02260     const long modulus1;  
02261     const long a2;        
02262     const long modulus2;  
02263 
02271     CLCG2_param(long a1_, long modulus1_, long a2_, long modulus2_) :
02272       a1(a1_), modulus1(modulus1_),
02273       a2(a2_), modulus2(modulus2_) { };
02274   };
02275 
02277   namespace CLCG2_param_sets {
02279     const CLCG2_param TRNG=CLCG2_param(376555083l, 2147482951l, 1028879659l, 2147482949l);
02280   }
02281 
02283 
02296   class CLCG2 : public RNG<CLCG2> {
02297   private:
02298     generic_MLCG R1;
02299     generic_MLCG R2;
02300     long modulus;
02301   public:
02302     static const RNG_type type=CLCG2_t;
02303     const char * name(void);
02304     void reset(void);
02305     void seed(long s=0l);
02306     long rand(void);    
02307     void split(long s, long n);
02308     void jump2(long s);
02309     void save_status(std::vector<long> &s);    
02310     void load_status(const std::vector<long> &s);    
02311     CLCG2 & CLCG2::operator=(RNG<CLCG2> &other);
02313 
02330     CLCG2(CLCG2_param param=CLCG2_param_sets::TRNG, long seed_=0l);
02331   };
02332 
02333   inline long CLCG2::rand(void) {
02334     unsigned long t=
02335       static_cast<unsigned long>(R1.rand())+
02336       static_cast<unsigned long>(R2.rand());
02337     return (t>=modulus) ? (t-modulus) : t;
02338   }
02339   
02340   // -------------------------------------------------------------------
02341 
02343 
02348   class CLCG3_param {
02349   public:
02350     const long a1;        
02351     const long modulus1;  
02352     const long a2;        
02353     const long modulus2;  
02354     const long a3;        
02355     const long modulus3;  
02356 
02366     CLCG3_param(long a1_, long modulus1_, long a2_, long modulus2_, long a3_, long modulus3_) :
02367       a1(a1_), modulus1(modulus1_),
02368       a2(a2_), modulus2(modulus2_),
02369       a3(a3_), modulus3(modulus3_) { };
02370   };
02371 
02373   namespace CLCG3_param_sets {
02375     const CLCG3_param TRNG=CLCG3_param(376555083l, 2147482951l,1028879659l, 2147482949l, 225802979l, 2147482943l);
02376   }
02377 
02379 
02393   class CLCG3 : public RNG<CLCG3> {
02394   private:
02395     generic_MLCG R1;
02396     generic_MLCG R2;
02397     generic_MLCG R3;
02398     long modulus;
02399   public:
02400     static const RNG_type type=CLCG3_t;
02401     const char * name(void);
02402     void reset(void);
02403     void seed(long s=0l);
02404     long rand(void);
02405     void split(long s, long n);
02406     void jump2(long s);
02407     void save_status(std::vector<long> &s);
02408     void load_status(const std::vector<long> &s);
02409     CLCG3 & CLCG3::operator=(RNG<CLCG3> &other);
02411 
02430     CLCG3(CLCG3_param param=CLCG3_param_sets::TRNG, long seed_=0l);
02431   };
02432 
02433   inline long CLCG3::rand(void) {
02434     unsigned long t=
02435       static_cast<unsigned long>(R1.rand())+
02436       static_cast<unsigned long>(R2.rand());
02437     if (t>=modulus)
02438       t-=modulus;
02439     t+=static_cast<unsigned long>(R3.rand());
02440     return (t>=modulus) ? (t-modulus) : t;
02441   }
02442   
02443   // -------------------------------------------------------------------
02444 
02446 
02451   class CLCG4_param {
02452   public:
02453     const long a1;        
02454     const long modulus1;  
02455     const long a2;        
02456     const long modulus2;  
02457     const long a3;        
02458     const long modulus3;  
02459     const long a4;        
02460     const long modulus4;  
02461 
02473     CLCG4_param(long a1_, long modulus1_, long a2_, long modulus2_, long a3_, long modulus3_, long a4_, long modulus4_) :
02474       a1(a1_), modulus1(modulus1_),
02475       a2(a2_), modulus2(modulus2_),
02476       a3(a3_), modulus3(modulus3_),
02477       a4(a4_), modulus4(modulus4_) { };
02478   };
02479 
02481   namespace CLCG4_param_sets {
02483     const CLCG4_param TRNG=CLCG4_param(376555083l, 2147482951l, 1028879659l, 2147482949l, 225802979l, 2147482943l,2028073966l, 2147482859l);
02484   }
02485 
02487 
02502   class CLCG4 : public RNG<CLCG4> {
02503   private:
02504     generic_MLCG R1;
02505     generic_MLCG R2;
02506     generic_MLCG R3;
02507     generic_MLCG R4;
02508     long modulus;
02509   public:
02510     static const RNG_type type=CLCG4_t;
02511     const char * name(void);
02512     void reset(void);
02513     void seed(long s=0l);
02514     long rand(void);
02515     void split(long s, long n);
02516     void jump2(long s);
02517     void save_status(std::vector<long> &s);  
02518     void load_status(const std::vector<long> &s);
02519     CLCG4 & CLCG4::operator=(RNG<CLCG4> &other);
02521 
02542     CLCG4(CLCG4_param param=CLCG4_param_sets::TRNG, long seed_=0l);
02543   };
02544 
02545   inline long CLCG4::rand(void) {
02546     unsigned long t=
02547       static_cast<unsigned long>(R1.rand())+
02548       static_cast<unsigned long>(R2.rand());
02549     if (t>=modulus)
02550       t-=modulus;
02551     t+=static_cast<unsigned long>(R3.rand());
02552     if (t>=modulus)
02553       t-=modulus;
02554     t+=static_cast<unsigned long>(R4.rand());
02555     return (t>=modulus) ? (t-modulus) : t;
02556   }
02557     
02558   // -------------------------------------------------------------------
02559 
02561 
02569   class EINV_param {
02570   public:
02571     const long a;  
02572     const long b;  
02573     const long modulus;  
02574 
02581     EINV_param(long a_, long b_, long modulus_) :
02582       a(a_), b(b_), modulus(modulus_) { };
02583   };
02584 
02586   namespace EINV_param_sets {
02588     const EINV_param TRNG=EINV_param(1073741831l, 0l, 1342177283l);
02589   }
02590 
02592 
02604   class EINV : public RNG<EINV> {
02605   private:
02606     long a, b, i, di, modulus, a_save, b_save, modulus_save;
02607   public:
02608     static const RNG_type type=EINV_t;
02609     const char * name(void);
02610     void reset(void);
02611     void seed(long s=0l);
02612     long rand(void);
02613     void split(long s, long n);
02614     void jump2(long s);
02615     void save_status(std::vector<long> &s);
02616     void load_status(const std::vector<long> &s);
02617     EINV & EINV::operator=(RNG<EINV> &other);
02619 
02625     EINV(EINV_param param=EINV_param_sets::TRNG, long seed_=0l);    
02626   };
02627 
02628   inline long EINV::rand(void) {
02629     i-=modulus;
02630     i+=di;
02631     if (i<0)
02632       i+=modulus;
02633     long x=static_cast<long>((static_cast<long long>(a)*
02634                               static_cast<long long>(i))%modulus)-modulus;
02635     x+=b;
02636     if (x<0)
02637       x+=modulus;
02638     // invert x
02639     long temp, q, flast=0, f=1, m=modulus;
02640     while (x>1) {
02641       temp=m%x; 
02642       q=m/x;
02643       m=x;  
02644       x=temp;  
02645       temp=f; 
02646       f=flast-q*f; 
02647       flast=temp;
02648     }
02649     return (a==0) ? 0 : ( (f<0) ? (f+modulus) : f );
02650   }
02651   
02652   // -------------------------------------------------------------------
02653 
02655 
02666   class EINVLCG64_param {
02667   public:
02668     const long a;  
02669     const long b;  
02670     const long modulus;  
02671     const unsigned long long c;  
02672     const unsigned long long d;  
02673     
02685     EINVLCG64_param(long a_, long b_, long modulus_, unsigned long long c_, unsigned long long d_) :
02686       a(a_), b(b_), modulus(modulus_), c(c_), d(d_) { };
02687   };
02688 
02690   namespace EINVLCG64_param_sets {
02692     const EINVLCG64_param TRNG=EINVLCG64_param(1073741831l, 0l, 1342177283l, 18145460002477866997ull, 1ull);
02693   }
02694 
02696 
02707   class EINVLCG64 : public RNG<EINVLCG64> {
02708   private:
02709     LCG64 R1;
02710     EINV R2;
02711   public:
02712     static const RNG_type type=EINVLCG64_t;
02713     const char * name(void);
02714     void reset(void);
02715     void seed(long s=0l);    
02716     long rand(void);
02717     void split(long s, long n);
02718     void jump2(long s);
02719     void save_status(std::vector<long> &s);
02720     void load_status(const std::vector<long> &s);    
02721     EINVLCG64 & EINVLCG64::operator=(RNG<EINVLCG64> &other);
02723 
02736     EINVLCG64(EINVLCG64_param param=EINVLCG64_param_sets::TRNG, long seed_=0l);    
02737   };
02738 
02739   inline long EINVLCG64::rand(void) {
02740     return (R1.rand()+R2.rand())&0x7fffffffl;
02741   }
02742 
02743 }
02744 
02745 
02746 #endif

Generated on Mon Apr 21 16:27:50 2003 for Tina's Random Number Generators by doxygen1.2.15