00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00349 double s, t1, t2;
00350
00351 if (sigma<=0.0)
00352 throw error("negative or zero standard deviation in TRNG::RNG::normal_dist");
00353
00354
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
00363
00364
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
00477 if (a<12) {
00478 double prod=1.0;
00479 for (int i=0; i<a; ++i)
00480 prod*=uniformoo();
00481
00482
00483
00484
00485 return -b*std::log(prod);
00486 } else {
00487
00488
00489
00490
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
00508
00509
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) {
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
00649
00650
00651
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
00695
00696
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
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
01012
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