37#include "CLHEP/Units/GlobalPhysicalConstants.h"
38#include "CLHEP/Random/Randomize.h"
39#include "CLHEP/Random/RandGaussQ.h"
40#include "CLHEP/Random/RandGaussT.h"
41#include "CLHEP/Random/RandPoissonQ.h"
42#include "CLHEP/Random/RandPoissonT.h"
43#include "CLHEP/Random/RandSkewNormal.h"
44#include "CLHEP/Random/defs.h"
55using std::setprecision;
62static const double REJECT = 4.0;
65static const int GaussBAD = 1 << 0;
66static const int GeneralBAD = 1 << 1;
67static const int PoissonBAD = 1 << 2;
68static const int GaussQBAD = 1 << 3;
69static const int GaussTBAD = 1 << 4;
70static const int PoissonQBAD = 1 << 5;
71static const int PoissonTBAD = 1 << 6;
72static const int SkewNormalBAD = 1 << 7;
96 static const double c[6] = {
101 0.001208650973866179,
102 -0.000005395239384953 };
105 tmp -= (x+.5)*std::log(tmp);
106 ser = 1.000000000190015;
107 for (
int i = 0; i < 6; i++) {
110 double ans = (-tmp + std::log (std::sqrt(CLHEP::twopi)*ser/x));
115double gser(
double a,
double x) {
116 const int ITMAX = 100;
117 const double EPS = 1.0E-8;
121 for (
int n=0;
n < ITMAX;
n++) {
125 if (std::fabs(del) < std::fabs(sum)*EPS) {
126 return sum*std::exp(-x+a*std::log(x)-
gammln(a));
129 cout <<
"Problem - inaccurate gser " << a <<
", " << x <<
"\n";
130 return sum*std::exp(-x+a*std::log(x)-
gammln(a));
134double gcf(
double a,
double x) {
135 const int ITMAX = 100;
136 const double EPS = 1.0E-8;
137 const double VERYSMALL = 1.0E-100;
139 double c = 1/VERYSMALL;
142 for (
int i = 1; i <= ITMAX; i++) {
143 double an = -i*(i-a);
146 if (std::fabs(d) < VERYSMALL) d = VERYSMALL;
148 if (std::fabs(c) < VERYSMALL) c = VERYSMALL;
152 if (std::fabs(del-1.0) < EPS) {
153 return std::exp(-x+a*std::log(x)-
gammln(a))*h;
156 cout <<
"Problem - inaccurate gcf " << a <<
", " << x <<
"\n";
157 return std::exp(-x+a*std::log(x)-
gammln(a))*h;
161double gammp (
double a,
double x) {
181 double sigma,
int nNumbers ) {
184 double worstSigma = 0;
202 for (ciu = 0; ciu < 11; ciu++) {
207 long oldprecision = cout.precision();
212 int ipr = nNumbers / 10 + 1;
213 for (
int ifire = 0; ifire < nNumbers; ifire++) {
216 if( x < mu - 12.0*sigma ) {
217 cout <<
"x = " << x <<
"\n";
219 if ( (ifire % ipr) == 0 ) {
220 cout << ifire << endl;
227 sumx6 += x*x*x*x*x*x;
228 u = (x - mu) / sigma;
231 if (ciu>10) ciu = 10;
235 if (ciu>10) ciu = 10;
240 double mean = sumx / nNumbers;
241 double u2 = sumx2/nNumbers - mean*mean;
242 double u3 = sumx3/nNumbers - 3*sumx2*mean/nNumbers + 2*mean*mean*mean;
243 double u4 = sumx4/nNumbers - 4*sumx3*mean/nNumbers
244 + 6*sumx2*mean*mean/nNumbers - 3*mean*mean*mean*mean;
245 double u5 = sumx5/nNumbers - 5*sumx4*mean/nNumbers
246 + 10*sumx3*mean*mean/nNumbers
247 - 10*sumx2*mean*mean*mean/nNumbers
248 + 4*mean*mean*mean*mean*mean;
249 double u6 = sumx6/nNumbers - 6*sumx5*mean/nNumbers
250 + 15*sumx4*mean*mean/nNumbers
251 - 20*sumx3*mean*mean*mean/nNumbers
252 + 15*sumx2*mean*mean*mean*mean/nNumbers
253 - 5*mean*mean*mean*mean*mean*mean;
255 cout <<
"Mean (should be close to " << mu <<
"): " << mean << endl;
256 cout <<
"Second moment (should be close to " << sigma*sigma <<
258 cout <<
"Third moment (should be close to zero): " << u3 << endl;
259 cout <<
"Fourth moment (should be close to " << 3*sigma*sigma*sigma*sigma <<
261 cout <<
"Fifth moment (should be close to zero): " << u5 << endl;
262 cout <<
"Sixth moment (should be close to "
263 << 15*sigma*sigma*sigma*sigma*sigma*sigma
264 <<
"): " << u6 << endl;
270 double del1 = std::sqrt ( (
double) nNumbers ) * std::abs(mean - mu) / sigma;
271 double del2 = std::sqrt ( nNumbers/2.0 ) * std::abs(u2 - sigma*sigma) / (sigma*sigma);
272 double del3 = std::sqrt ( nNumbers/6.0 ) * std::abs(u3) / (sigma*sigma*sigma);
273 double sigma4 = sigma*sigma*sigma*sigma;
274 double del4 = std::sqrt ( nNumbers/96.0 ) * std::abs(u4 - 3 * sigma4) / sigma4;
275 double del5 = std::sqrt ( nNumbers/720.0 ) * std::abs(u5) / (sigma*sigma4);
276 double del6 = std::sqrt ( nNumbers/10170.0 ) * std::abs(u6 - 15*sigma4*sigma*sigma)
277 / (sigma4*sigma*sigma);
279 cout <<
" These represent " <<
280 del1 <<
", " << del2 <<
", " << del3 <<
", \n"
281 <<
" " << del4 <<
", " << del5 <<
", " << del6
282 <<
"\n standard deviations from expectations\n";
283 if ( del1 > worstSigma ) worstSigma = del1;
284 if ( del2 > worstSigma ) worstSigma = del2;
285 if ( del3 > worstSigma ) worstSigma = del3;
286 if ( del4 > worstSigma ) worstSigma = del4;
287 if ( del5 > worstSigma ) worstSigma = del5;
288 if ( del6 > worstSigma ) worstSigma = del6;
290 if ( del1 > REJECT || del2 > REJECT || del3 > REJECT
291 || del4 > REJECT || del5 > REJECT || del6 > REJECT ) {
292 cout <<
"REJECT hypothesis that this distribution is correct!!\n";
312 for (
int m1 = 0; m1 < 11; m1++) {
313 double expect = table[m1]*nNumbers;
314 double sig = std::sqrt ( table[m1] * (1.0-table[m1]) * nNumbers );
315 cout.precision(oldprecision);
316 cout <<
"Between " << m1/2.0 <<
" sigma and "
317 << m1/2.0+.5 <<
" sigma (should be about " << expect <<
"):\n "
319 << ncounts[m1] <<
" negative and " << counts[m1] <<
" positive " <<
"\n";
321 double negSigs = std::abs ( ncounts[m1] - expect ) / sig;
322 double posSigs = std::abs ( counts[m1] - expect ) / sig;
323 cout <<
" These represent " <<
324 negSigs <<
" and " << posSigs <<
" sigma from expectations\n";
325 if ( negSigs > REJECT || posSigs > REJECT ) {
326 cout <<
"REJECT hypothesis that this distribution is correct!!\n";
329 if ( negSigs > worstSigma ) worstSigma = negSigs;
330 if ( posSigs > worstSigma ) worstSigma = posSigs;
333 cout <<
"\n The worst deviation encountered (out of about 25) was "
334 << worstSigma <<
" sigma \n\n";
336 cout.precision(oldprecision);
351 double worstSigma = 0;
366 long oldprecision = cout.precision();
371 double delta = k / std::sqrt( 1 + k*k );
372 double mu = delta/std::sqrt(CLHEP::halfpi);
374 double mom3 = 3*delta*(1-(delta*delta)/3.)/std::sqrt(CLHEP::halfpi);
376 double mom5 = 15*delta*(1-2.*(delta*delta)/3.+(delta*delta*delta*delta)/5.)/std::sqrt(CLHEP::halfpi);
379 int ipr = nNumbers / 10 + 1;
380 for (
int ifire = 0; ifire < nNumbers; ifire++) {
383 if( x < mu - 12.0 ) {
384 cout <<
"x = " << x <<
"\n";
386 if ( (ifire % ipr) == 0 ) {
387 cout << ifire << endl;
394 sumx6 += x*x*x*x*x*x;
397 double mean = sumx / nNumbers;
398 double u2 = sumx2/nNumbers;
399 double u3 = sumx3/nNumbers;
400 double u4 = sumx4/nNumbers;
401 double u5 = sumx5/nNumbers;
402 double u6 = sumx6/nNumbers;
404 cout <<
"Mean (should be close to " << mu <<
"): " << mean << endl;
405 cout <<
"Second moment (should be close to " << mom2 <<
"): " << u2 << endl;
406 cout <<
"Third moment (should be close to " << mom3 <<
"): " << u3 << endl;
407 cout <<
"Fourth moment (should be close to " << mom4 <<
"): " << u4 << endl;
408 cout <<
"Fifth moment (should be close to " << mom5 <<
"): " << u5 << endl;
409 cout <<
"Sixth moment (should be close to " << mom6 <<
"): " << u6 << endl;
411 double del1 = std::sqrt ( (
double) nNumbers ) * std::abs(mean - mu);
412 double del2 = std::sqrt ( nNumbers/2.0 ) * std::abs(u2 - mom2);
413 double del3 = std::sqrt ( nNumbers/(15.-mom3*mom3) ) * std::abs(u3 - mom3 );
414 double del4 = std::sqrt ( nNumbers/96.0 ) * std::abs(u4 - mom4);
415 double del5 = std::sqrt ( nNumbers/(945.-mom5*mom5) ) * std::abs(u5 - mom5 );
416 double del6 = std::sqrt ( nNumbers/10170.0 ) * std::abs(u6 - mom6);
418 cout <<
" These represent " <<
419 del1 <<
", " << del2 <<
", " << del3 <<
", \n"
420 <<
" " << del4 <<
", " << del5 <<
", " << del6
421 <<
"\n standard deviations from expectations\n";
422 if ( del1 > worstSigma ) worstSigma = del1;
423 if ( del2 > worstSigma ) worstSigma = del2;
424 if ( del3 > worstSigma ) worstSigma = del3;
425 if ( del4 > worstSigma ) worstSigma = del4;
426 if ( del5 > worstSigma ) worstSigma = del5;
427 if ( del6 > worstSigma ) worstSigma = del6;
429 if ( del1 > REJECT || del2 > REJECT || del3 > REJECT ||
430 del4 > REJECT || del5 > REJECT || del6 > REJECT ) {
431 cout <<
"REJECT hypothesis that this distribution is correct!!\n";
435 cout <<
"\n The worst deviation encountered (out of about 25) was "
436 << worstSigma <<
" sigma \n\n";
438 cout.precision(oldprecision);
454 double logAnswer = -mu_ + r*std::log(mu_) -
gammln(r+1);
455 return std::exp(logAnswer);
460 int MINBIN,
int MAXBINS,
int clumping,
461 int& firstBin,
int& lastBin ) {
468 double * refdist =
new double [MAXBINS];
481 while ( c < MAXBINS ) {
482 for ( ic=0, binc=0; ic < clumping; ic++, r++ ) {
483 binc += pdist(r) * N1;
486 if (binc >= MINBIN)
break;
488 if ( c > MAXBINS/3 ) {
489 cout <<
"The number of samples supplied " << N1 <<
490 " is too small to set up a chi^2 to test this distribution.\n";
495 refdist[firstBin] = start;
500 while ( c < MAXBINS ) {
501 for ( ic=0, binc=0; ic < clumping; ic++, r++ ) {
502 binc += pdist(r) * N1;
505 if (next < MINBIN)
break;
512 next += refdist[lastBin];
513 while ( c < MAXBINS ) {
514 for ( ic=0, binc=0; ic < clumping; ic++, r++ ) {
515 binc += pdist(r) * N1;
520 refdist[lastBin] = next;
542 int clumping = int(std::sqrt(mu));
543 if (clumping <= 1) clumping = 2;
544 const int MINBIN = 20;
545 const int MAXBINS = 1000;
554 MINBIN, MAXBINS, 1, firstBin, lastBin);
556 MINBIN, MAXBINS, clumping, firstBin2, lastBin2);
563 double* samples =
new double [MAXBINS];
564 double* samples2 =
new double [MAXBINS];
566 for (r = 0; r < MAXBINS; r++) {
573 for (
int i = 0; i < N2; i++) {
574 r = (int)dist.
fire();
576 moment += (r - mu)*(r - mu);
578 if (r1 < firstBin) r1 = firstBin;
579 if (r1 > lastBin) r1 = lastBin;
582 if (r2 < firstBin2) r2 = firstBin2;
583 if (r2 > lastBin2) r2 = lastBin2;
589 for (k = firstBin; k <= lastBin; k++) {
590 cout << k <<
" " << samples[k] <<
" " << refdist[k] <<
" " <<
591 (samples[k]-refdist[k])*(samples[k]-refdist[k])/refdist[k] <<
"\n";
594 for (k = firstBin2; k <= lastBin2; k++) {
595 cout << k <<
" " << samples2[k] <<
" " << refdist2[k] <<
"\n";
602 for ( r = firstBin; r <= lastBin; r++ ) {
603 double delta = (samples[r] - refdist[r]);
604 chi2 += delta*delta/refdist[r];
606 int degFreedom = (lastBin - firstBin + 1) - 1;
615 pval = 1.0 - gammp ( .5*degFreedom , .5*chi2 );
617 cout <<
"Chi^2 is " << chi2 <<
" on " << degFreedom <<
" degrees of freedom."
618 <<
" p = " << pval <<
"\n";
626 for ( r = firstBin2; r <= lastBin2; r++ ) {
627 double delta = (samples2[r] - refdist2[r]);
628 chi2 += delta*delta/refdist2[r];
630 degFreedom = (lastBin2 - firstBin2 + 1) - 1;
632 pval2 = 1.0 - gammp ( .5*degFreedom , .5*chi2 );
634 cout <<
"Clumps: Chi^2 is " << chi2 <<
" on " << degFreedom <<
635 " degrees of freedom." <<
" p = " << pval2 <<
"\n";
642 double mean = sum / N2;
643 double sigma = std::sqrt( moment / (N2-1) );
645 double deviationMean = std::fabs(mean - mu)/(std::sqrt(mu/N2));
646 double expectedSigma2Variance = (2*N2*mu*mu/(N2-1) + mu) / N2;
647 double deviationSigma = std::fabs(sigma*sigma-mu)/std::sqrt(expectedSigma2Variance);
649 cout <<
"Mean (should be " << mu <<
") is " << mean <<
"\n";
650 cout <<
"Sigma (should be " << std::sqrt(mu) <<
") is " << sigma <<
"\n";
652 cout <<
"These are " << deviationMean <<
" and " << deviationSigma <<
653 " standard deviations from expected values\n\n";
661 if ( (pval < .0001) || (pval2 < .0001) ||
662 (deviationMean > 3.5) || (deviationSigma > 3.5) ) {
664 cout <<
"REJECT this distributon!!!\n";
684 cout <<
"\n--------------------------------------------\n";
685 cout <<
"Test of RandGauss distribution \n\n";
688 cout <<
"Please enter an integer seed: ";
689 cin >> seed; cout << seed <<
"\n";
691 cout <<
"Moving on to next test...\n";
696 cout <<
"How many numbers should we generate: ";
697 cin >> nNumbers; cout << nNumbers <<
"\n";
701 cout <<
"Enter mu: ";
702 cin >> mu; cout << mu <<
"\n";
704 cout <<
"Enter sigma: ";
705 cin >> sigma; cout << sigma <<
"\n";
707 cout <<
"\nInstantiating distribution utilizing TripleRand engine...\n";
711 cout <<
"\n Sample fire(): \n";
717 cout <<
"\n Testing operator() ... \n";
737 cout <<
"\n--------------------------------------------\n";
738 cout <<
"Test of SkewNormal distribution \n\n";
741 cout <<
"Please enter an integer seed: ";
742 cin >> seed; cout << seed <<
"\n";
744 cout <<
"Moving on to next test...\n";
749 cout <<
"How many numbers should we generate: ";
750 cin >> nNumbers; cout << nNumbers <<
"\n";
754 cin >> k; cout << k <<
"\n";
756 cout <<
"\nInstantiating distribution utilizing TripleRand engine...\n";
760 cout <<
"\n Sample fire(): \n";
766 cout <<
"\n Testing operator() ... \n";
773 return SkewNormalBAD;
786 cout <<
"\n--------------------------------------------\n";
787 cout <<
"Test of RandGaussT distribution \n\n";
790 cout <<
"Please enter an integer seed: ";
791 cin >> seed; cout << seed <<
"\n";
793 cout <<
"Moving on to next test...\n";
798 cout <<
"How many numbers should we generate: ";
799 cin >> nNumbers; cout << nNumbers <<
"\n";
803 cout <<
"Enter mu: ";
804 cin >> mu; cout << mu <<
"\n";
806 cout <<
"Enter sigma: ";
807 cin >> sigma; cout << sigma <<
"\n";
809 cout <<
"\nInstantiating distribution utilizing TripleRand engine...\n";
813 cout <<
"\n Sample fire(): \n";
819 cout <<
"\n Testing operator() ... \n";
839 cout <<
"\n--------------------------------------------\n";
840 cout <<
"Test of RandGaussQ distribution \n\n";
843 cout <<
"Please enter an integer seed: ";
844 cin >> seed; cout << seed <<
"\n";
846 cout <<
"Moving on to next test...\n";
851 cout <<
"How many numbers should we generate: ";
852 cin >> nNumbers; cout << nNumbers <<
"\n";
854 if (nNumbers >= 20000000) {
855 cout <<
"With that many samples RandGaussQ need not pass validation...\n";
860 cout <<
"Enter mu: ";
861 cin >> mu; cout << mu <<
"\n";
863 cout <<
"Enter sigma: ";
864 cin >> sigma; cout << sigma <<
"\n";
866 cout <<
"\nInstantiating distribution utilizing DualRand engine...\n";
870 cout <<
"\n Sample fire(): \n";
876 cout <<
"\n Testing operator() ... \n";
895 cout <<
"\n--------------------------------------------\n";
896 cout <<
"Test of RandPoisson distribution \n\n";
899 cout <<
"Please enter an integer seed: ";
900 cin >> seed; cout << seed <<
"\n";
902 cout <<
"Moving on to next test...\n";
906 cout <<
"\nInstantiating distribution utilizing TripleRand engine...\n";
910 cout <<
"How many numbers should we generate for each mu: ";
911 cin >> nNumbers; cout << nNumbers <<
"\n";
917 cout <<
"Enter a value for mu: ";
918 cin >> mu; cout << mu <<
"\n";
923 cout <<
"\n Sample fire(): \n";
929 cout <<
"\n Testing operator() ... \n";
931 bool this_good =
poissonTest ( dist, mu, nNumbers );
933 cout <<
"\n Poisson distribution for mu = " << mu <<
" is incorrect!!!\n";
953 cout <<
"\n--------------------------------------------\n";
954 cout <<
"Test of RandPoissonQ distribution \n\n";
957 cout <<
"Please enter an integer seed: ";
958 cin >> seed; cout << seed <<
"\n";
960 cout <<
"Moving on to next test...\n";
964 cout <<
"\nInstantiating distribution utilizing TripleRand engine...\n";
968 cout <<
"How many numbers should we generate for each mu: ";
969 cin >> nNumbers; cout << nNumbers <<
"\n";
975 cout <<
"Enter a value for mu: ";
976 cin >> mu; cout << mu <<
"\n";
981 cout <<
"\n Sample fire(): \n";
987 cout <<
"\n Testing operator() ... \n";
989 bool this_good =
poissonTest ( dist, mu, nNumbers );
991 cout <<
"\n Poisson distribution for mu = " << mu <<
" is incorrect!!!\n";
1011 cout <<
"\n--------------------------------------------\n";
1012 cout <<
"Test of RandPoissonT distribution \n\n";
1015 cout <<
"Please enter an integer seed: ";
1016 cin >> seed; cout << seed <<
"\n";
1018 cout <<
"Moving on to next test...\n";
1022 cout <<
"\nInstantiating distribution utilizing TripleRand engine...\n";
1026 cout <<
"How many numbers should we generate for each mu: ";
1027 cin >> nNumbers; cout << nNumbers <<
"\n";
1033 cout <<
"Enter a value for mu: ";
1034 cin >> mu; cout << mu <<
"\n";
1039 cout <<
"\n Sample fire(): \n";
1045 cout <<
"\n Testing operator() ... \n";
1047 bool this_good =
poissonTest ( dist, mu, nNumbers );
1049 cout <<
"\n Poisson distribution for mu = " << mu <<
" is incorrect!!!\n";
1069 cout <<
"\n--------------------------------------------\n";
1070 cout <<
"Test of RandGeneral distribution (using a Gaussian shape)\n\n";
1075 cout <<
"Please enter an integer seed: ";
1076 cin >> seed; cout << seed <<
"\n";
1078 cout <<
"Moving on to next test...\n";
1083 cout <<
"How many numbers should we generate: ";
1084 cin >> nNumbers; cout << nNumbers <<
"\n";
1091 cout <<
"Enter sigma: ";
1092 cin >> sigma; cout << sigma <<
"\n";
1101 cout <<
"Enter nBins for stepwise pdf test: ";
1102 cin >> nBins; cout << nBins <<
"\n";
1110 double xBins = nBins;
1111 double* aProbFunc =
new double [nBins];
1113 for (
int iBin = 0; iBin < nBins; iBin++ ) {
1114 x = iBin / (xBins-1);
1115 aProbFunc [iBin] = std::exp ( - (x-mu)*(x-mu) / (2*sigma*sigma) );
1119 cout <<
"\nInstantiating distribution utilizing Ranlux64 engine...\n";
1127 double* garbage =
new double[nBins];
1130 for (
int gBin = 0; gBin < nBins; gBin++ ) {
1134 cout <<
"\n Sample fire(): \n";
1139 cout <<
"\n Testing operator() ... \n";
1149 cout <<
"Enter nBins for linearized pdf test: ";
1150 cin >> nBins; cout << nBins <<
"\n";
1158 aProbFunc =
new double [nBins];
1159 for (
int jBin = 0; jBin < nBins; jBin++ ) {
1160 x = jBin / (xBins-1);
1161 aProbFunc [jBin] = std::exp ( - (x-mu)*(x-mu) / (2*sigma*sigma) );
1167 cout <<
"\n Sample operator(): \n";
1172 cout <<
"\n Testing operator() ... \n";
1174 bool good2 =
gaussianTest ( dist, mu, sigma, nNumbers );
1175 good = good && good2;
1213 return mask > 0 ? -mask : mask;
bool gaussianTest(HepRandom &dist, double mu, double sigma, int nNumbers)
double * createRefDist(poisson pdist, int N1, int MINBIN, int MAXBINS, int clumping, int &firstBin, int &lastBin)
bool poissonTest(RandPoisson &dist, double mu, int N2)
bool skewNormalTest(HepRandom &dist, double k, int nNumbers)