📄 newran.cpp
字号:
else if (df==3) { version=4; c1=new Exponential(); c2=new ChiSq1(noncen); } else { version=5; c1=new Gamma2(0.5*(df-1)); c2=new ChiSq1(noncen); } if (!c1 || (version>3 && !c2)) ErrorNoSpace(); mean=df+noncen; var=2*df+4.0*noncen;}ChiSq::~ChiSq() { delete c1; if (version>3) delete c2; }Real ChiSq::Next(){ switch(version) { case 0: return c1->Next(); case 1: case 2: return c1->Next()*2.0; case 3: return c1->Next() + c1->Next(); case 4: case 5: Real s1 = c1->Next()*2.0; Real s2 = c2->Next(); return s1 + s2; // this is to make it work with Microsoft VC5 } return 0;}Pareto::Pareto(Real shape) : Shape(shape){ if (Shape <= 0) Throw(Logic_error("Newran: illegal parameter")); RS = -1.0 / Shape;}Real Pareto::Next(){ return pow(Random::Next(), RS); }ExtReal Pareto::Mean() const{ if (Shape > 1) return Shape/(Shape-1.0); else return PlusInfinity;}ExtReal Pareto::Variance() const{ if (Shape > 2) return Shape/(square(Shape-1.0))/(Shape-2.0); else return PlusInfinity;}Real Cauchy::Density(Real x) const // Cauchy density function{ return (fabs(x)>1.0e15) ? 0 : 0.31830988618 / (1.0+x*x); }Poisson1::Poisson1(Real mux) : AsymGen(mux) // Constructor{ mu=mux; ln_mu=log(mu); }Real Poisson1::Density(Real x) const // Poisson density function{ if (x < 0.0) return 0.0; double ix = floor(x); // use integer part double l = ln_mu * ix - mu - ln_gamma(1.0 + ix); return (l < -40.0) ? 0.0 : exp(l);}Binomial1::Binomial1(int nx, Real px) : AsymGen((nx + 1) * px), p(px), q(1.0 - px), n(nx) { ln_p = log(p); ln_q = log(q); ln_n_fac = ln_gamma(n+1); }Real Binomial1::Density(Real x) const // Binomial density function{ double ix = floor(x); // use integer part if (ix < 0.0 || ix > n) return 0.0; double l = ln_n_fac - ln_gamma(ix+1) - ln_gamma(n-ix+1) + ix * ln_p + (n-ix) * ln_q; return (l < -40.0) ? 0.0 : exp(l);}Poisson2::Poisson2(Real mux){ Real probs[40]; probs[0]=exp(-mux); for (int i=1; i<40; i++) probs[i]=probs[i-1]*mux/i; dg=new DiscreteGen(40,probs); if (!dg) ErrorNoSpace();}Poisson2::~Poisson2() { delete dg; }Binomial2::Binomial2(int nx, Real px){ Real qx = 1.0 - px; Real probs[40]; int k = (int)(nx * px); probs[k] = exp(ln_gamma(nx+1) - ln_gamma(k+1) - ln_gamma(nx-k+1) + k * log(px) + (nx-k) * log(qx)); int i; int m = (nx >= 40) ? 39 : nx; for (i=k+1; i<=m; i++) probs[i]=probs[i-1] * px * (nx-i+1) / qx / i; for (i=k-1; i>=0; i--) probs[i]=probs[i+1] * qx * (i+1) / px / (nx-i); dg = new DiscreteGen(m + 1, probs); if (!dg) ErrorNoSpace();}Binomial2::~Binomial2() { delete dg; }Real Exponential::Density(Real x) const // Negative exponential{ return (x > 40.0 || x < 0.0) ? 0.0 : exp(-x); }Poisson::Poisson(Real mu){ if (mu <= 8.0) method = new Poisson2(mu); else method = new Poisson1(mu); if (!method) ErrorNoSpace();}Binomial::Binomial(int nx, Real px){ if (nx < 40 || nx * px <= 8.0) method = new Binomial2(nx, px); else method = new Binomial1(nx, px); if (!method) ErrorNoSpace();}NegativeBinomial::NegativeBinomial(Real NX, Real PX) : AsymGen(0.0), N(NX), P(PX), Q(1.0 + PX){ p = 1.0 / Q; ln_q = log(1.0 - p); c = N * log(p) - ln_gamma(N); mode = (N - 1) * P; if (mode < 1.0) mode = 0.0;}Real NegativeBinomial::Next() { return floor(AsymGen::Next()); }Real NegativeBinomial::Density(Real x) const{ if (x < 0.0) return 0.0; Real ix = floor(x); Real l = c + ln_gamma(ix + N) - ln_gamma(ix + 1) + ix * ln_q; return (l < -40.0) ? 0.0 : exp(l);}Gamma1::Gamma1(Real alphax) // constructor (Real=shape){ ralpha=1.0/alphax; ln_gam=ln_gamma(alphax+1.0); alpha=alphax; }Real Gamma1::Density(Real x) const // density function for{ // transformed gamma Real l = - pow(x,ralpha) - ln_gam; return (l < -40.0) ? 0.0 : exp(l);}Real Gamma1::Next() // transform variable{ return pow(PosGen::Next(),ralpha); }Gamma2::Gamma2(Real alphax) : AsymGen(alphax-1.0) // constructor (Real=shape){ alpha=alphax; ln_gam=ln_gamma(alpha); }Real Gamma2::Density(Real x) const // gamma density function{ if (x<=0.0) return 0.0; double l = (alpha-1.0)*log(x) - x - ln_gam; return (l < -40.0) ? 0.0 : exp(l);}Gamma::Gamma(Real alpha) // general gamma generator{ if (alpha<1.0) method = new Gamma1(alpha); else if (alpha==1.0) method = new Exponential(); else method = new Gamma2(alpha); if (!method) ErrorNoSpace();}DiscreteGen::DiscreteGen(int n1, Real* prob) // discrete generator // values on 0,...,n1-1{ #ifdef MONITOR cout << "constructing DiscreteGen\n"; #endif Gen(n1, prob); val=0; mean=0.0; var=0.0; { for (int i=0; i<n; i++) mean = mean + i*prob[i]; } { for (int i=0; i<n; i++) var = var + square(i-mean) * prob[i]; }}DiscreteGen::DiscreteGen(int n1, Real* prob, Real* val1) // discrete generator // values on *val{ #ifdef MONITOR cout << "constructing DiscreteGen\n"; #endif Gen(n1, prob); val = new Real[n1]; if (!val) ErrorNoSpace(); for (int i=0; i<n1; i++) val[i]=val1[i]; mean=0.0; var=0.0; { for (int i=0; i<n; i++) mean = mean + val[i]*prob[i]; } { for (int i=0; i<n; i++) var = var + square(val[i]-mean)*prob[i]; }}void DiscreteGen::Gen(int n1, Real* prob){ n=n1; // number of values p=new Real[n]; ialt=new int[n]; if (!p || !ialt) ErrorNoSpace(); Real rn = 1.0/n; Real px = 0; int i; for (i=0; i<n; i++) { p[i]=0.0; ialt[i]=-1; } for (i=0; i<n; i++) { Real pmin=1.0; Real pmax=-1.0; int jmin=-1; int jmax=-1; for (int j=0; j<n; j++) { if (ialt[j]<0) { px=prob[j]-p[j]; if (pmax<=px) { pmax=px; jmax=j; } if (pmin>=px) { pmin=px; jmin=j; } } } if ((jmax<0) || (jmin<0)) Throw(Runtime_error("Newran: method fails")); ialt[jmin]=jmax; px=rn-pmin; p[jmax]+=px; px*=n; p[jmin]=px; if ((px>1.00001)||(px<-.00001)) Throw(Runtime_error("Newran: probs don't add to 1 (a)")); } if (px>0.00001) Throw(Runtime_error("Newran: probs don't add to 1 (b)"));}DiscreteGen::~DiscreteGen(){ delete [] p; delete [] ialt; delete [] val; #ifdef MONITOR cout << "destructing DiscreteGen\n"; #endif}Real DiscreteGen::Next() // Next discrete random variable{ int i = (int)(n*Random::Next()); if (Random::Next()<p[i]) i=ialt[i]; return val ? val[i] : (Real)i;}Real ln_gamma(Real xx){ // log gamma function adapted from numerical recipes in C if (xx<1.0) // Use reflection formula { double piz = 3.14159265359 * (1.0-xx); return log(piz/sin(piz))-ln_gamma(2.0-xx); } else { static double cof[6]={76.18009173,-86.50532033,24.01409822, -1.231739516,0.120858003e-2,-0.536382e-5}; double x=xx-1.0; double tmp=x+5.5; tmp -= (x+0.5)*log(tmp); double ser=1.0; for (int j=0;j<=5;j++) { x += 1.0; ser += cof[j]/x; } return -tmp+log(2.50662827465*ser); }}Real NegatedRandom::Next() { return - rv->Next(); }ExtReal NegatedRandom::Mean() const { return - rv->Mean(); }ExtReal NegatedRandom::Variance() const { return rv->Variance(); }Real ScaledRandom::Next() { return rv->Next() * s; }ExtReal ScaledRandom::Mean() const { return rv->Mean() * s; }ExtReal ScaledRandom::Variance() const { return rv->Variance() * (s*s); }Real ShiftedRandom::Next() { return rv->Next() + s; }ExtReal ShiftedRandom::Mean() const { return rv->Mean() + s; }ExtReal ShiftedRandom::Variance() const { return rv->Variance(); }Real ReverseShiftedRandom::Next() { return s - rv->Next(); }ExtReal ReverseShiftedRandom::Mean() const { return - rv->Mean() + s; }ExtReal ReverseShiftedRandom::Variance() const { return rv->Variance(); }Real ReciprocalRandom::Next() { return s / rv->Next(); }ExtReal RepeatedRandom::Mean() const { return rv->Mean() * (Real)n; }ExtReal RepeatedRandom::Variance() const { return rv->Variance() * (Real)n; }RepeatedRandom& Random::operator()(int n){ RepeatedRandom* r = new RepeatedRandom(*this, n); if (!r) ErrorNoSpace(); return *r;}NegatedRandom& operator-(Random& rv){ NegatedRandom* r = new NegatedRandom(rv); if (!r) ErrorNoSpace(); return *r;}ShiftedRandom& operator+(Random& rv, Real s){ ShiftedRandom* r = new ShiftedRandom(rv, s); if (!r) ErrorNoSpace(); return *r;}ShiftedRandom& operator-(Random& rv, Real s){ ShiftedRandom* r = new ShiftedRandom(rv, -s); if (!r) ErrorNoSpace(); return *r;}ScaledRandom& operator*(Random& rv, Real s){ ScaledRandom* r = new ScaledRandom(rv, s); if (!r) ErrorNoSpace(); return *r;}ShiftedRandom& operator+(Real s, Random& rv){ ShiftedRandom* r = new ShiftedRandom(rv, s); if (!r) ErrorNoSpace(); return *r;}ReverseShiftedRandom& operator-(Real s, Random& rv){ ReverseShiftedRandom* r = new ReverseShiftedRandom(rv, s); if (!r) ErrorNoSpace(); return *r;}ScaledRandom& operator*(Real s, Random& rv){ ScaledRandom* r = new ScaledRandom(rv, s); if (!r) ErrorNoSpace(); return *r;}ScaledRandom& operator/(Random& rv, Real s){ ScaledRandom* r = new ScaledRandom(rv, 1.0/s); if (!r) ErrorNoSpace(); return *r;}ReciprocalRandom& operator/(Real s, Random& rv){ ReciprocalRandom* r = new ReciprocalRandom(rv, s); if (!r) ErrorNoSpace(); return *r;}AddedRandom& operator+(Random& rv1, Random& rv2){ AddedRandom* r = new AddedRandom(rv1, rv2); if (!r) ErrorNoSpace(); return *r;}MultipliedRandom& operator*(Random& rv1, Random& rv2){ MultipliedRandom* r = new MultipliedRandom(rv1, rv2); if (!r) ErrorNoSpace(); return *r;}SubtractedRandom& operator-(Random& rv1, Random& rv2){ SubtractedRandom* r = new SubtractedRandom(rv1, rv2); if (!r) ErrorNoSpace(); return *r;}DividedRandom& operator/(Random& rv1, Random& rv2){ DividedRandom* r = new DividedRandom(rv1, rv2); if (!r) ErrorNoSpace(); return *r;}Real AddedRandom::Next()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -