Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals

newran.cpp

Go to the documentation of this file.
00001 // newran.cpp -----------------------------------------------------------
00002 
00003 // NEWRAN02
00004 #include "SdlArs.h"
00005 
00006 //#define WANT_STREAM
00007 #define WANT_MATH
00008 #include "include.h"
00009 
00010 #include "newran.h"
00011 
00012 #ifdef use_namespace
00013 namespace NEWRAN {
00014 #endif
00015 
00016 //********* classes which are used internally only **********************
00017 
00018 //*********** wlchi-square-1 random number generator **********************
00019 
00020 class ChiSq1 : public Normal              // generate non-central chi-square
00021                                           // rv with 1 degree of freedom
00022 {
00023    Real deltasq;                          // non-centrality parameter
00024    Real delta;
00025 
00026 public:
00027    ChiSq1(Real);                          // non-centrality parameter
00028    ExtReal Mean() const { return 1.0+deltasq; }
00029    ExtReal Variance() const { return 2.0+4.0*deltasq; }
00030    Real Next();
00031 };
00032 
00033 //*********** Poisson random number generator, larger mu ****************
00034 
00035 class Poisson1 : public AsymGen           // generate poisson rv, large mu
00036 {
00037    Real mu, ln_mu;
00038 public:
00039    Poisson1(Real);                        // constructor (Real=mean)
00040    Real Density(Real) const;              // Poisson density function
00041    Real Next() { return floor(AsymGen::Next()); }
00042    ExtReal Mean() const { return mu; }
00043    ExtReal Variance() const { return mu; }
00044 };
00045 
00046 //*********** Poisson random number generator, mu <= 10 ****************
00047 
00048 class Poisson2 : public Random            // generate poisson rv, large mu
00049 {
00050    DiscreteGen* dg;
00051 public:
00052    Poisson2(Real);                        // constructor (Real=mean)
00053    ~Poisson2();
00054    Real Next() { return dg->Next(); }
00055    ExtReal Mean() const { return dg->Mean(); }
00056    ExtReal Variance() const { return dg->Variance(); }
00057 };
00058 
00059 //********** Gamma random number generator, alpha <= 1 *****************
00060 
00061 class Gamma1 : public PosGen              // generate gamma rv
00062                                           // shape parameter <= 1
00063 {
00064    Real ln_gam, ralpha, alpha;
00065 public:
00066    Gamma1(Real);                          // constructor (Real=shape)
00067    Real Density(Real) const;              // gamma density function
00068    Real Next();                           // carries out power transform
00069    ExtReal Mean() const { return alpha; }
00070    ExtReal Variance() const { return alpha; }
00071 };
00072 
00073 //********** Gamma random number generator, alpha > 1 ******************
00074 
00075 class Gamma2 : public AsymGen             // generate gamma rv
00076                                           // shape parameter > 1
00077 {
00078    Real alpha, ln_gam;
00079 public:
00080    Gamma2(Real);                          // constructor (Real=shape)
00081    Real Density(Real) const;              // gamma density function
00082    ExtReal Mean() const { return alpha; }
00083    ExtReal Variance() const { return alpha; }
00084 };
00085 
00086 //*********** Binomial random number generator, n > 40 *****************
00087 
00088 class Binomial1 : public AsymGen           // generate binomial rv, larger n
00089 {
00090    Real p, q, ln_p, ln_q, ln_n_fac; int n;
00091 public:
00092    Binomial1(int nx, Real px);
00093    Real Density(Real) const;
00094    Real Next() { return floor(AsymGen::Next()); }
00095    ExtReal Mean() const { return p * n; }
00096    ExtReal Variance() const { return p * q * n; }
00097 };
00098 
00099 //******* Binomial random number generator, n < 40 or n*p <= 8 *************
00100 
00101 class Binomial2 : public Random            // generate binomial rv, smaller n
00102 {
00103    DiscreteGen* dg;
00104 public:
00105    Binomial2(int nx, Real px);
00106    ~Binomial2();
00107    Real Next() { return dg->Next(); }
00108    ExtReal Mean() const { return dg->Mean(); }
00109    ExtReal Variance() const { return dg->Variance(); }
00110 };
00111 
00112 //************************ static variables ***************************
00113 
00114 double Random::seed;
00115 //unsigned long Random::iseed;                // for Mother
00116 //Real Random::Buffer[128];
00117 Real Normal::Nxi;
00118 Real* Normal::Nsx;
00119 Real* Normal::Nsfx;
00120 long Normal::count=0;
00121 
00122 //**************************** utilities ******************************
00123 
00124 inline Real square(Real x) { return x*x; }
00125 inline ExtReal square(const ExtReal& x) { return x*x; }
00126 
00127 static void ErrorNoSpace() { Throw(Bad_alloc("Newran: out of space")); }
00128 
00129 //************************* end of definitions ************************
00130 
00131 
00132 Real Random::Raw()                           // get new uniform random number
00133 {
00134    // m = 2147483647 = 2^31 - 1; a = 16807;
00135    // 127773 = m div a; 2836 = m mod a
00136    long iseed = (long)seed;
00137    long hi = iseed / 127773L;                 // integer division
00138    long lo = iseed - hi * 127773L;            // modulo
00139    iseed = 16807 * lo - 2836 * hi;
00140    if (iseed <= 0) iseed += 2147483647L;
00141    seed = (double)iseed; return seed*4.656612875e-10;
00142 }
00143 
00144 Real Random::Density(Real) const
00145 { Throw(Logic_error("density function not defined")); return 0.0; }
00146 
00147 #ifdef _MSC_VER
00148 static void DoNothing(int) {}
00149 #endif
00150 
00151 Real Random::Next()                          // get new mixed random number
00152 {
00153    if (!seed)
00154       Throw(Logic_error("Random number generator not initialised"));
00155    int i = (int)(Raw()*128);               // 0 <= i < 128
00156 #ifdef _MSC_VER
00157    DoNothing(i); DoNothing(i);
00158 #endif
00159    Real f = Buffer[i]; Buffer[i] = Raw();  // Microsoft release gets this wrong
00160    return f;
00161 
00162    // return Mother(&iseed);
00163 }
00164 
00165 double Random::Get()                  // get random number seed
00166 { return seed/2147483648L; }
00167 
00168 Random::Random( void )
00169 {
00170    for (int i = 0; i<128; i++) 
00171            Buffer[i] = Raw();
00172 }
00173 
00174 void Random::Set(double s)            // set random number seed
00175                                       // s must be between 0 and 1
00176 {
00177    if (s>=1.0 || s<=0.0)
00178       Throw(Logic_error("Newran: seed out of range"));
00179    //iseed = 2147483648L * s;         // for Mother
00180    seed = (long)(s*2147483648L);
00181 }
00182 
00183 
00184 PosGen::PosGen()                             // Constructor
00185 {
00186    #ifdef MONITOR
00187       tron << "constructing PosGen\n";
00188    #endif
00189    NotReady=true;
00190 }
00191 
00192 PosGen::~PosGen()
00193 {
00194    if (!NotReady)
00195    {
00196       #ifdef MONITOR
00197          tron << "freeing PosGen arrays\n";
00198       #endif
00199       delete [] sx; delete [] sfx;
00200    }
00201    #ifdef MONITOR
00202       tron << "destructing PosGen\n";
00203    #endif
00204 }
00205 
00206 void PosGen::Build(bool sym)                 // set up arrays
00207 {
00208    #ifdef MONITOR
00209       tron << "building PosGen arrays\n";
00210    #endif
00211    int i;
00212    NotReady=false;
00213    sx=new Real[60]; sfx=new Real[60];
00214    if (!sx || !sfx) ErrorNoSpace();
00215    Real sxi=0.0; Real inc = sym ? 0.01 : 0.02;
00216    for (i=0; i<60; i++)
00217    {
00218       sx[i]=sxi; Real f1=Density(sxi); sfx[i]=f1;
00219       if (f1<=0.0) goto L20;
00220       sxi+=inc/f1;
00221    }
00222    Throw(Runtime_error("Newran: area too large"));
00223 L20:
00224    if (i<50) Throw(Runtime_error("Newran: area too small"));
00225    xi = sym ? 2*i : i;
00226    return;
00227 }
00228 
00229 Real PosGen::Next()
00230 {
00231    Real ak,y; int ir;
00232    if (NotReady) Build(false);
00233    do
00234    {
00235       Real r1=Random::Next();
00236       ir = (int)(r1*xi); Real sxi=sx[ir];
00237       ak=sxi+(sx[ir+1]-sxi)*Random::Next();
00238       y=sfx[ir]*Random::Next();
00239    }
00240    while ( y>=sfx[ir+1] && y>=Density(ak) );
00241    return ak;
00242 }
00243 
00244 Real SymGen::Next()
00245 {
00246    Real s,ak,y; int ir;
00247    if (NotReady) Build(true);
00248    do
00249    {
00250       s=1.0;
00251       Real r1=Random::Next();
00252       if (r1>0.5) { s=-1.0; r1=1.0-r1; }
00253       ir = (int)(r1*xi); Real sxi=sx[ir];
00254       ak=sxi+(sx[ir+1]-sxi)*Random::Next();
00255       y=sfx[ir]*Random::Next();
00256    }
00257    while ( y>=sfx[ir+1] && y>=Density(ak) );
00258    return s*ak;
00259 }
00260 
00261 AsymGen::AsymGen(Real modex)                 // Constructor
00262 {
00263    #ifdef MONITOR
00264       tron << "constructing AsymGen\n";
00265    #endif
00266    mode=modex; NotReady=true;
00267 }
00268 
00269 void AsymGen::Build()                        // set up arrays
00270 {
00271    #ifdef MONITOR
00272       tron << "building AsymGen arrays\n";
00273    #endif
00274    int i;
00275    NotReady=false;
00276    sx=new Real[121]; sfx=new Real[121];
00277    if (!sx || !sfx)  ErrorNoSpace();
00278    Real sxi=mode;
00279    for (i=0; i<120; i++)
00280    {
00281       sx[i]=sxi; Real f1=Density(sxi); sfx[i]=f1;
00282       if (f1<=0.0) goto L20;
00283       sxi+=0.01/f1;
00284    }
00285    Throw(Runtime_error("Newran: area too large (a)"));
00286 L20:
00287    ic=i-1; sx[120]=sxi; sfx[120]=0.0;
00288    sxi=mode;
00289    for (; i<120; i++)
00290    {
00291       sx[i]=sxi; Real f1=Density(sxi); sfx[i]=f1;
00292       if (f1<=0.0) goto L30;
00293       sxi-=0.01/f1;
00294    }
00295    Throw(Runtime_error("Newran: area too large (b)"));
00296 L30:
00297    if (i<100)  Throw(Runtime_error("Newran: area too small"));
00298    xi=i;
00299    return;
00300 }
00301 
00302 Real AsymGen::Next()
00303 {
00304    Real ak,y; int ir1;
00305    if (NotReady) Build();
00306    do
00307    {
00308       Real r1=Random::Next();
00309       int ir=(int)(r1*xi); Real sxi=sx[ir];
00310       ir1 = (ir==ic) ? 120 : ir+1;
00311       ak=sxi+(sx[ir1]-sxi)*Random::Next();
00312       y=sfx[ir]*Random::Next();
00313    }
00314    while ( y>=sfx[ir1] && y>=Density(ak) );
00315    return ak;
00316 }
00317 
00318 AsymGen::~AsymGen()
00319 {
00320    if (!NotReady)
00321    {
00322       #ifdef MONITOR
00323          tron << "freeing AsymGen arrays\n";
00324       #endif
00325       delete [] sx; delete [] sfx;
00326    }
00327    #ifdef MONITOR
00328       tron << "destructing AsymGen\n";
00329    #endif
00330 }
00331 
00332 PosGenX::PosGenX(PDF fx) { f=fx; }
00333 
00334 SymGenX::SymGenX(PDF fx) { f=fx; }
00335 
00336 AsymGenX::AsymGenX(PDF fx, Real mx) : AsymGen(mx) { f=fx; }
00337 
00338 
00339 Normal::Normal()
00340 {
00341    if (count) { NotReady=false; xi=Nxi; sx=Nsx; sfx=Nsfx; }
00342    else { Build(true); Nxi=xi; Nsx=sx; Nsfx=sfx; }
00343    count++;
00344 }
00345 
00346 Normal::~Normal()
00347 {
00348    count--;
00349    if (count) NotReady=true;                     // disable freeing arrays
00350 }
00351 
00352 Real Normal::Density(Real x) const               // normal density
00353 { return (fabs(x)>8.0) ? 0 : 0.398942280 * exp(-x*x / 2); }
00354 
00355 ChiSq1::ChiSq1(Real d) : Normal()                // chisquare with 1 df
00356 { deltasq=d; delta=sqrt(d); }
00357 
00358 Real ChiSq1::Next()
00359 { Real z=Normal::Next()+delta; return z*z; }
00360 
00361 ChiSq::ChiSq(int df, Real noncen)
00362 {
00363   if (df<=0 || noncen<0.0) Throw(Logic_error("Newran: illegal parameters"));
00364   else if (df==1) { version=0; c1=new ChiSq1(noncen); }
00365   else if (noncen==0.0)
00366   {
00367      if (df==2) { version=1; c1=new Exponential(); }
00368      else { version=2; c1=new Gamma2(0.5*df); }
00369   }
00370   else if (df==2) { version=3; c1=new ChiSq1(noncen/2.0); }
00371   else if (df==3) { version=4; c1=new Exponential(); c2=new ChiSq1(noncen); }
00372   else { version=5; c1=new Gamma2(0.5*(df-1)); c2=new ChiSq1(noncen); }
00373   if (!c1 || (version>3 && !c2)) ErrorNoSpace();
00374   mean=df+noncen; var=2*df+4.0*noncen;
00375 }
00376 
00377 ChiSq::~ChiSq() { delete c1; if (version>3) delete c2; }
00378 
00379 Real ChiSq::Next()
00380 {
00381    switch(version)
00382    {
00383    case 0: return c1->Next();
00384    case 1: case 2: return c1->Next()*2.0;
00385    case 3: return c1->Next() + c1->Next();
00386    case 4: case 5: Real s1 = c1->Next()*2.0; Real s2 = c2->Next();
00387            return s1 + s2; // this is to make it work with Microsoft VC5
00388    }
00389    return 0;
00390 }
00391 
00392 Pareto::Pareto(Real shape) : Shape(shape)
00393 {
00394    if (Shape <= 0) Throw(Logic_error("Newran: illegal parameter"));
00395    RS = -1.0 / Shape;
00396 }
00397 
00398 Real Pareto::Next()
00399 { return pow(Random::Next(), RS); }
00400 
00401 ExtReal Pareto::Mean() const
00402 {
00403    if (Shape > 1) return Shape/(Shape-1.0);
00404    else return PlusInfinity;
00405 }
00406 
00407 ExtReal Pareto::Variance() const
00408 {
00409    if (Shape > 2) return Shape/(square(Shape-1.0))/(Shape-2.0);
00410    else return PlusInfinity;
00411 }
00412 
00413 Real Cauchy::Density(Real x) const               // Cauchy density function
00414 { return (fabs(x)>1.0e15) ? 0 : 0.31830988618 / (1.0+x*x); }
00415 
00416 Poisson1::Poisson1(Real mux) : AsymGen(mux)      // Constructor
00417 { mu=mux; ln_mu=log(mu); }
00418 
00419 Real Poisson1::Density(Real x) const             // Poisson density function
00420 {
00421    if (x < 0.0) return 0.0;
00422    double ix = floor(x);                         // use integer part
00423    double l = ln_mu * ix - mu - ln_gamma(1.0 + ix);
00424    return  (l < -40.0) ? 0.0 : exp(l);
00425 }
00426 
00427 Binomial1::Binomial1(int nx, Real px)
00428    : AsymGen((nx + 1) * px), p(px), q(1.0 - px), n(nx)
00429       { ln_p = log(p); ln_q = log(q); ln_n_fac = ln_gamma(n+1); }
00430 
00431 Real Binomial1::Density(Real x) const            // Binomial density function
00432 {
00433    double ix = floor(x);                         // use integer part
00434    if (ix < 0.0 || ix > n) return 0.0;
00435    double l = ln_n_fac - ln_gamma(ix+1) - ln_gamma(n-ix+1)
00436       + ix * ln_p + (n-ix) * ln_q;
00437    return  (l < -40.0) ? 0.0 : exp(l);
00438 }
00439 
00440 Poisson2::Poisson2(Real mux)
00441 {
00442    Real probs[40];
00443    probs[0]=exp(-mux);
00444    for (int i=1; i<40; i++) probs[i]=probs[i-1]*mux/i;
00445    dg=new DiscreteGen(40,probs);
00446    if (!dg) ErrorNoSpace();
00447 }
00448 
00449 Poisson2::~Poisson2() { delete dg; }
00450 
00451 Binomial2::Binomial2(int nx, Real px)
00452 {
00453    Real qx = 1.0 - px;
00454    Real probs[40];
00455    int k = (int)(nx * px);
00456    probs[k] = exp(ln_gamma(nx+1) - ln_gamma(k+1) - ln_gamma(nx-k+1)
00457       + k * log(px) + (nx-k) * log(qx));
00458    int i;
00459    int m = (nx >= 40) ? 39 : nx;
00460    for (i=k+1; i<=m; i++) probs[i]=probs[i-1] * px * (nx-i+1) / qx / i;
00461    for (i=k-1; i>=0; i--) probs[i]=probs[i+1] * qx * (i+1) / px / (nx-i);
00462    dg = new DiscreteGen(m + 1, probs);
00463    if (!dg) ErrorNoSpace();
00464 }
00465 
00466 Binomial2::~Binomial2() { delete dg; }
00467 
00468 Real Exponential::Density(Real x) const          // Negative exponential
00469 { return  (x > 40.0 || x < 0.0) ? 0.0 : exp(-x); }
00470 
00471 Poisson::Poisson(Real mu)
00472 {
00473    if (mu <= 8.0) method = new Poisson2(mu);
00474    else method = new Poisson1(mu);
00475    if (!method) ErrorNoSpace();
00476 }
00477 
00478 Binomial::Binomial(int nx, Real px)
00479 {
00480    if (nx < 40 || nx * px <= 8.0) method = new Binomial2(nx, px);
00481    else method = new Binomial1(nx, px);
00482    if (!method) ErrorNoSpace();
00483 }
00484 
00485 NegativeBinomial::NegativeBinomial(Real NX, Real PX)
00486    : AsymGen(0.0), N(NX), P(PX), Q(1.0 + PX)
00487 {
00488    p = 1.0 / Q;  ln_q = log(1.0 - p);
00489    c = N * log(p) - ln_gamma(N);  mode = (N - 1) * P;
00490    if (mode < 1.0) mode = 0.0;
00491 }
00492 
00493 Real NegativeBinomial::Next() { return floor(AsymGen::Next()); }
00494 
00495 Real NegativeBinomial::Density(Real x) const
00496 {
00497    if (x < 0.0) return 0.0;
00498    Real ix = floor(x);
00499    Real l = c + ln_gamma(ix + N) - ln_gamma(ix + 1) + ix * ln_q;
00500    return  (l < -40.0) ? 0.0 : exp(l);
00501 }
00502 
00503 Gamma1::Gamma1(Real alphax)                      // constructor (Real=shape)
00504 { ralpha=1.0/alphax; ln_gam=ln_gamma(alphax+1.0); alpha=alphax; }
00505 
00506 Real Gamma1::Density(Real x) const               // density function for
00507 {                                                // transformed gamma
00508    Real l = - pow(x,ralpha) - ln_gam;
00509    return  (l < -40.0) ? 0.0 : exp(l);
00510 }
00511 
00512 Real Gamma1::Next()                               // transform variable
00513 { return pow(PosGen::Next(),ralpha); }
00514 
00515 Gamma2::Gamma2(Real alphax) : AsymGen(alphax-1.0) // constructor (Real=shape)
00516 { alpha=alphax; ln_gam=ln_gamma(alpha); }
00517 
00518 Real Gamma2::Density(Real x) const                // gamma density function
00519 {
00520    if (x<=0.0) return 0.0;
00521    double l = (alpha-1.0)*log(x) - x - ln_gam;
00522    return  (l < -40.0) ? 0.0 : exp(l);
00523 }
00524 
00525 Gamma::Gamma(Real alpha)                         // general gamma generator
00526 {
00527    if (alpha<1.0) method = new Gamma1(alpha);
00528    else if (alpha==1.0) method = new Exponential();
00529    else method = new Gamma2(alpha);
00530    if (!method)  ErrorNoSpace();
00531 }
00532 
00533 DiscreteGen::DiscreteGen(int n1, Real* prob)     // discrete generator
00534                                                  // values on 0,...,n1-1
00535 {
00536    #ifdef MONITOR
00537       tron << "constructing DiscreteGen\n";
00538    #endif
00539    Gen(n1, prob); val=0;
00540    mean=0.0; var=0.0;
00541    { for (int i=0; i<n; i++) mean = mean + i*prob[i]; }
00542    { for (int i=0; i<n; i++) var = var + square(i-mean) * prob[i]; }
00543 }
00544 
00545 DiscreteGen::DiscreteGen(int n1, Real* prob, Real* val1)
00546                                                  // discrete generator
00547                                                  // values on *val
00548 {
00549    #ifdef MONITOR
00550       tron << "constructing DiscreteGen\n";
00551    #endif
00552    Gen(n1, prob); val = new Real[n1];
00553    if (!val)  ErrorNoSpace();
00554    for (int i=0; i<n1; i++) val[i]=val1[i];
00555    mean=0.0; var=0.0;
00556    { for (int i=0; i<n; i++) mean = mean + val[i]*prob[i]; }
00557    { for (int i=0; i<n; i++) var = var + square(val[i]-mean)*prob[i]; }
00558 }
00559 
00560 
00561 void DiscreteGen::Gen(int n1, Real* prob)
00562 {
00563    n=n1;                                         // number of values
00564    p=new Real[n]; ialt=new int[n];
00565    if (!p || !ialt)  ErrorNoSpace();
00566    Real rn = 1.0/n; Real px = 0; int i;
00567    for (i=0; i<n; i++) { p[i]=0.0; ialt[i]=-1; }
00568    for (i=0; i<n; i++)
00569    {
00570       Real pmin=1.0; Real pmax=-1.0; int jmin=-1; int jmax=-1;
00571       for (int j=0; j<n; j++)
00572       {
00573          if (ialt[j]<0)
00574          {
00575             px=prob[j]-p[j];
00576             if (pmax<=px) { pmax=px; jmax=j; }
00577             if (pmin>=px) { pmin=px; jmin=j; }
00578          }
00579       }
00580       if ((jmax<0) || (jmin<0)) Throw(Runtime_error("Newran: method fails"));
00581       ialt[jmin]=jmax; 
00582                 px=rn-pmin; 
00583                 p[jmax]+=px; 
00584                 px*=n; 
00585                 p[jmin]=px;
00586       if ((px>1.00001)||(px<-.00001))
00587          Throw(Runtime_error("Newran: probs don't add to 1 (a)"));
00588    }
00589    if (px>0.00001) Throw(Runtime_error("Newran: probs don't add to 1 (b)"));
00590 }
00591 
00592 DiscreteGen::~DiscreteGen()
00593 {
00594    delete [] p; delete [] ialt; delete [] val;
00595    #ifdef MONITOR
00596       tron << "destructing DiscreteGen\n";
00597    #endif
00598 }
00599 
00600 Real DiscreteGen::Next()                  // Next discrete random variable
00601 {
00602    int i = (int)(n * Random::Next()); 
00603         Real    t = Random::Next();
00604         if( t < p[i] )
00605                 i = ialt[i];
00606    return val ? val[i] : (Real)i;
00607 }
00608 
00609 Real ln_gamma(Real xx)
00610 {
00611    // log gamma function adapted from numerical recipes in C
00612 
00613    if (xx<1.0)                           // Use reflection formula
00614    {
00615       double piz = 3.14159265359 * (1.0-xx);
00616       return log(piz/sin(piz))-ln_gamma(2.0-xx);
00617    }
00618    else
00619    {
00620       static double cof[6]={76.18009173,-86.50532033,24.01409822,
00621          -1.231739516,0.120858003e-2,-0.536382e-5};
00622 
00623       double x=xx-1.0; double tmp=x+5.5;
00624       tmp -= (x+0.5)*log(tmp); double ser=1.0;
00625       for (int j=0;j<=5;j++) { x += 1.0; ser += cof[j]/x; }
00626       return -tmp+log(2.50662827465*ser);
00627    }
00628 }
00629 
00630 
00631 Real NegatedRandom::Next() { return - rv->Next(); }
00632 
00633 ExtReal NegatedRandom::Mean() const { return - rv->Mean(); }
00634 
00635 ExtReal NegatedRandom::Variance() const { return rv->Variance(); }
00636 
00637 Real ScaledRandom::Next() { return rv->Next() * s; }
00638 
00639 ExtReal ScaledRandom::Mean() const { return rv->Mean() * s; }
00640 
00641 ExtReal ScaledRandom::Variance() const { return rv->Variance() * (s*s); }
00642 
00643 Real ShiftedRandom::Next() { return rv->Next() + s; }
00644 
00645 ExtReal ShiftedRandom::Mean() const { return rv->Mean() + s; }
00646 
00647 ExtReal ShiftedRandom::Variance() const { return rv->Variance(); }
00648 
00649 Real ReverseShiftedRandom::Next() { return s - rv->Next(); }
00650 
00651 ExtReal ReverseShiftedRandom::Mean() const { return - rv->Mean() + s; }
00652 
00653 ExtReal ReverseShiftedRandom::Variance() const { return rv->Variance(); }
00654 
00655 Real ReciprocalRandom::Next() { return s / rv->Next(); }
00656 
00657 ExtReal RepeatedRandom::Mean() const { return rv->Mean() * (Real)n; }
00658 
00659 ExtReal RepeatedRandom::Variance() const { return rv->Variance() * (Real)n; }
00660 
00661 RepeatedRandom& Random::operator()(int n)
00662 {
00663    RepeatedRandom* r = new RepeatedRandom(*this, n);
00664    if (!r) ErrorNoSpace(); return *r;
00665 }
00666 
00667 NegatedRandom& operator-(Random& rv)
00668 {
00669    NegatedRandom* r = new NegatedRandom(rv);
00670    if (!r) ErrorNoSpace(); return *r;
00671 }
00672 
00673 ShiftedRandom& operator+(Random& rv, Real s)
00674 {
00675    ShiftedRandom* r = new ShiftedRandom(rv, s);
00676    if (!r) ErrorNoSpace(); return *r;
00677 }
00678 
00679 ShiftedRandom& operator-(Random& rv, Real s)
00680 {
00681    ShiftedRandom* r = new ShiftedRandom(rv, -s);
00682    if (!r) ErrorNoSpace(); return *r;
00683 }
00684 
00685 ScaledRandom& operator*(Random& rv, Real s)
00686 {
00687    ScaledRandom* r = new ScaledRandom(rv, s);
00688    if (!r) ErrorNoSpace(); return *r;
00689 }
00690 
00691 ShiftedRandom& operator+(Real s, Random& rv)
00692 {
00693    ShiftedRandom* r = new ShiftedRandom(rv, s);
00694    if (!r) ErrorNoSpace(); return *r;
00695 }
00696 
00697 ReverseShiftedRandom& operator-(Real s, Random& rv)
00698 {
00699    ReverseShiftedRandom* r = new ReverseShiftedRandom(rv, s);
00700    if (!r) ErrorNoSpace(); return *r;
00701 }
00702 
00703 ScaledRandom& operator*(Real s, Random& rv)
00704 {
00705    ScaledRandom* r = new ScaledRandom(rv, s);
00706    if (!r) ErrorNoSpace(); return *r;
00707 }
00708 
00709 ScaledRandom& operator/(Random& rv, Real s)
00710 {
00711    ScaledRandom* r = new ScaledRandom(rv, 1.0/s);
00712    if (!r) ErrorNoSpace(); return *r;
00713 }
00714 
00715 ReciprocalRandom& operator/(Real s, Random& rv)
00716 {
00717    ReciprocalRandom* r = new ReciprocalRandom(rv, s);
00718    if (!r) ErrorNoSpace(); return *r;
00719 }
00720 
00721 AddedRandom& operator+(Random& rv1, Random& rv2)
00722 {
00723    AddedRandom* r = new AddedRandom(rv1, rv2);
00724    if (!r) ErrorNoSpace(); return *r;
00725 }
00726 
00727 OredRandom& operator|(Random& rv1, Random& rv2)
00728 {
00729    OredRandom* r = new OredRandom(rv1, rv2);
00730    if (!r) ErrorNoSpace(); return *r;
00731 }
00732 
00733 MultipliedRandom& operator*(Random& rv1, Random& rv2)
00734 {
00735    MultipliedRandom* r = new MultipliedRandom(rv1, rv2);
00736    if (!r) ErrorNoSpace(); return *r;
00737 }
00738 
00739 SubtractedRandom& operator-(Random& rv1, Random& rv2)
00740 {
00741    SubtractedRandom* r = new SubtractedRandom(rv1, rv2);
00742    if (!r) ErrorNoSpace(); return *r;
00743 }
00744 
00745 DividedRandom& operator/(Random& rv1, Random& rv2)
00746 {
00747    DividedRandom* r = new DividedRandom(rv1, rv2);
00748    if (!r) ErrorNoSpace(); return *r;
00749 }
00750 
00751 Real AddedRandom::Next() { return rv1->Next() + rv2->Next() ; }
00752 
00753 ExtReal AddedRandom::Mean() const { return rv1->Mean() + rv2->Mean() ; }
00754 
00755 ExtReal AddedRandom::Variance() const
00756    { return rv1->Variance() + rv2->Variance() ; }
00757 
00758 Real OredRandom::Next() 
00759 { 
00760         i = (i + 1) % 2;
00761         if( i )
00762                 return rv1->Next();
00763         else
00764                 return rv2->Next();
00765 }
00766 
00767 ExtReal OredRandom::Mean() const { return rv1->Mean() + rv2->Mean() ; }
00768 
00769 ExtReal OredRandom::Variance() const
00770    { return rv1->Variance() + rv2->Variance() ; }
00771 
00772 Real SubtractedRandom::Next() { return rv1->Next() - rv2->Next() ; }
00773 
00774 ExtReal SubtractedRandom::Mean() const { return rv1->Mean() - rv2->Mean() ; }
00775 
00776 ExtReal SubtractedRandom::Variance() const
00777    { return rv1->Variance() + rv2->Variance() ; }
00778 
00779 Real MultipliedRandom::Next() 
00780 { return rv1->Next() * rv2->Next() ; }
00781 
00782 ExtReal MultipliedRandom::Mean() const { return rv1->Mean() * rv2->Mean() ; }
00783 
00784 ExtReal MultipliedRandom::Variance() const
00785 {
00786    ExtReal e1 = square(rv1->Mean()); ExtReal e2 = square(rv2->Mean());
00787    ExtReal v1 = rv1->Variance(); ExtReal v2 = rv2->Variance();
00788    ExtReal r=v1*v2+v1*e2+e1*v2;
00789    return r;
00790 }
00791 
00792 Real DividedRandom::Next() { return rv1->Next() / rv2->Next() ; }
00793 
00794 void Random::load(int*,Real*,Random**)
00795    { Throw(Logic_error("Newran: illegal combination")); }
00796 
00797 void SelectedRandom::load(int* i, Real* probs, Random** rvx)
00798 {
00799    probs[*i]=p; rvx[*i]=rv; (*i)++;
00800    delete this;
00801 }
00802 
00803 Real SelectedRandom::Next()
00804    { Throw(Logic_error("Newran: Next not defined")); return 0.0; }
00805 
00806 Real AddedSelectedRandom::Next()
00807    { Throw(Logic_error("Newran: Next not defined")); return 0.0; }
00808 
00809 Real RepeatedRandom::Next()
00810    { Real sum=0.0; for (int i=0; i<n; i++) sum+=rv->Next(); return sum; }
00811 
00812 MixedRandom::MixedRandom(int nx, Real* probs, Random** rvx)
00813 {
00814    n = nx;
00815    rv = new Random*[n]; if (!rv) ErrorNoSpace();
00816    for (int i=0; i<n; i++) rv[i]=rvx[i];
00817    Build(probs);
00818 }
00819 
00820 MixedRandom::MixedRandom(AddedSelectedRandom& sr)
00821 {
00822    n = sr.nelems();                       // number of terms;
00823    Real* probs = new Real[n]; rv = new Random*[n];
00824    if (!probs || !rv) ErrorNoSpace();
00825    int i=0; sr.load(&i,probs,rv);
00826    Build(probs); delete [] probs;
00827 }
00828 
00829 void MixedRandom::Build(Real* probs)
00830 {
00831    int i;
00832    dg=new DiscreteGen(n,probs);
00833    if (!dg) ErrorNoSpace();
00834    mean=0.0; var=0.0;
00835    for (i=0; i<n; i++) mean = mean + (rv[i])->Mean()*probs[i];
00836    for (i=0; i<n; i++)
00837    {
00838       ExtReal sigsq=(rv[i])->Variance();
00839       ExtReal mudif=(rv[i])->Mean()-mean;
00840       var = var + (sigsq+square(mudif))*probs[i];
00841    }
00842 
00843 }
00844 
00845 MixedRandom::~MixedRandom()
00846 {
00847    for (int i=0; i<n; i++) rv[i]->tDelete();
00848    delete [] rv; delete dg;
00849 }
00850 
00851 Real MixedRandom::Next()
00852    { int i = (int)(dg->Next()); return (rv[i])->Next(); }
00853 
00854 int AddedSelectedRandom::nelems() const
00855    { return rv1->nelems() + rv2->nelems(); }
00856 
00857 void AddedSelectedRandom::load(int* i, Real* probs, Random** rvx)
00858 {
00859    rv1->load(i, probs, rvx); rv2->load(i, probs, rvx);
00860    delete this;
00861 }
00862 
00863 AddedSelectedRandom& operator+(SelectedRandom& rv1,
00864    SelectedRandom& rv2)
00865 {
00866    AddedSelectedRandom* r = new AddedSelectedRandom(rv1, rv2);
00867    if (!r) ErrorNoSpace(); return *r;
00868 }
00869 
00870 AddedSelectedRandom& operator+(AddedSelectedRandom& rv1,
00871    SelectedRandom& rv2)
00872 {
00873    AddedSelectedRandom* r = new AddedSelectedRandom(rv1, rv2);
00874    if (!r) ErrorNoSpace(); return *r;
00875 }
00876 
00877 AddedSelectedRandom& operator+(SelectedRandom& rv1,
00878    AddedSelectedRandom& rv2)
00879 {
00880    AddedSelectedRandom* r = new AddedSelectedRandom(rv1, rv2);
00881    if (!r) ErrorNoSpace(); return *r;
00882 }
00883 
00884 AddedSelectedRandom& operator+(AddedSelectedRandom& rv1,
00885    AddedSelectedRandom& rv2)
00886 {
00887    AddedSelectedRandom* r = new AddedSelectedRandom(rv1, rv2);
00888    if (!r) ErrorNoSpace(); return *r;
00889 }
00890 
00891 SelectedRandom& Random::operator()(double p)
00892 {
00893    SelectedRandom* r = new SelectedRandom(*this, p);
00894    if (!r) ErrorNoSpace(); return *r;
00895 }
00896 
00897 
00898 
00899 
00900 // Identification routines for each class - may not work on all compilers?
00901 
00902 char* Random::Name()            { return "Random";           }
00903 char* Uniform::Name()           { return "Uniform";          }
00904 char* Constant::Name()          { return "Constant";         }
00905 char* PosGen::Name()            { return "PosGen";           }
00906 char* SymGen::Name()            { return "SymGen";           }
00907 char* AsymGen::Name()           { return "AsymGen";          }
00908 char* PosGenX::Name()           { return "PosGenX";          }
00909 char* SymGenX::Name()           { return "SymGenX";          }
00910 char* AsymGenX::Name()          { return "AsymGenX";         }
00911 char* Normal::Name()            { return "Normal";           }
00912 char* ChiSq::Name()             { return "ChiSq";            }
00913 char* Cauchy::Name()            { return "Cauchy";           }
00914 char* Exponential::Name()       { return "Exponential";      }
00915 char* Poisson::Name()           { return "Poisson";          }
00916 char* Binomial::Name()          { return "Binomial";         }
00917 char* NegativeBinomial::Name()  { return "NegativeBinomial"; }
00918 char* Gamma::Name()             { return "Gamma";            }
00919 char* Pareto::Name()            { return "Pareto";           }
00920 char* DiscreteGen::Name()       { return "DiscreteGen";      }
00921 char* SumRandom::Name()         { return "SumRandom";        }
00922 char* MixedRandom::Name()       { return "MixedRandom";      }
00923 
00924 
00925 // ********************** permutation generator ***************************
00926 
00927 void RandomPermutation::Next(int N, int M, int p[], int start)
00928 {
00929    // N = size of urn; M = number of draws
00930    if (N < M) Throw(Logic_error("Newran: N < M in RandomPermutation"));
00931    int i;
00932    int* q = new int [N];
00933    if (!q) ErrorNoSpace();
00934    for (i = 0; i < N; i++) q[i] = start + i;
00935    for (i = 0; i < M; i++)
00936    {
00937       int k = i + (int)(U.Next() * (N - i));       // uniform on i ... N-1
00938       p[i] = q[k]; q[k] = q[i];                    // swap i and k terms
00939                                                    // but put i-th term into p
00940    }
00941    delete [] q;
00942 }
00943 
00944 void RandomCombination::SortAscending(int n, int gm[])
00945 {
00946    // from numerical recipies in C - Shell sort
00947 
00948    const double aln2i = 1.442695022; const double tiny = 1.0e-5;
00949    int m = n; int lognb2 = (int)(aln2i * log((double)n) + tiny);
00950    while (lognb2--)
00951    {
00952       m >>= 1;
00953       for (int j = m; j<n; j++)
00954       {
00955          int* gmj = gm+j; int i = j-m; int* gmi = gmj-m; int t = *gmj;
00956          while (i>=0 && *gmi>t)  { *gmj = *gmi; gmj = gmi; gmi -= m; i -= m; }
00957          *gmj = t;
00958       }
00959    }
00960 }
00961 
00962 #ifdef use_namespace
00963 }
00964 #endif
00965 
00966 

Generated on Fri Dec 5 04:06:00 2003 for Borqueror by doxygen 1.3.3