00001
00002
00003
00004
00005 #include "Math/DistFuncMathMore.h"
00006 #ifndef NO_MATHCORE
00007 #include "Math/GSLIntegrator.h"
00008 #include "Math/WrappedFunction.h"
00009 #include "Math/DistFuncMathCore.h"
00010 #endif
00011
00012
00013 #include <iostream>
00014 #include <limits>
00015
00016 using namespace ROOT::Math;
00017
00018 int compare( std::string name, double v1, double v2, double scale = 2.0) {
00019
00020
00021
00022
00023
00024 double eps = scale* std::numeric_limits<double>::epsilon();
00025 int iret = 0;
00026 double delta = v2 - v1;
00027 double d = 0;
00028 if (delta < 0 ) delta = - delta;
00029 if (v1 == 0 || v2 == 0) {
00030 if (delta > eps ) {
00031 iret = 1;
00032 }
00033 }
00034
00035 else {
00036 d = v1;
00037
00038 if ( v1 < 0) d = -d;
00039
00040 if ( delta/d > eps && delta > eps )
00041 iret = 1;
00042 }
00043
00044 if (iret == 0)
00045 std::cout <<".";
00046 else {
00047 int pr = std::cout.precision (18);
00048 std::cout << "\nDiscrepancy in " << name.c_str() << "() :\n " << v1 << " != " << v2 << " discr = " << int(delta/d/eps)
00049 << " (Allowed discrepancy is " << eps << ")\n\n";
00050 std::cout.precision (pr);
00051
00052 }
00053 return iret;
00054 }
00055
00056
00057
00058
00059
00060 struct TestFunc1 {
00061
00062 typedef double ( * Pdf) ( double, double, double);
00063 typedef double ( * Cdf) ( double, double, double);
00064 typedef double ( * Quant) ( double, double);
00065
00066
00067 struct PdfFunction {
00068 PdfFunction( Pdf pdf, double p1 ) : fPdf(pdf), fP1(p1) {}
00069 double operator() ( double x) const { return fPdf(x,fP1,0.0); }
00070
00071 Pdf fPdf;
00072 double fP1;
00073 };
00074
00075
00076 TestFunc1( double p1, double s = 2) :
00077 scale(s)
00078 {
00079 p[0] = p1;
00080 }
00081
00082 #ifndef NO_MATHCORE // skip cdf test when Mathcore is missing
00083
00084 int testCdf( Pdf f_pdf, Cdf f_cdf, bool c = false) {
00085 int iret = 0;
00086 double val = 1.0;
00087 double q1 = f_cdf(val, p[0],0.0);
00088
00089 PdfFunction f(f_pdf,p[0]);
00090 WrappedFunction<PdfFunction> wf(f);
00091 GSLIntegrator ig(1.E-12,1.E-12,100000);
00092 ig.SetFunction(wf);
00093 if (!c) {
00094
00095 double q2 = ig.IntegralLow(val);
00096
00097 iret |= compare("test _cdf", q1, q2, 1.0E6);
00098 }
00099 else {
00100
00101 double q2 = ig.IntegralUp(val);
00102 iret |= compare("test _cdf_c", q1, q2, 1.0E6);
00103 }
00104 return iret;
00105 }
00106
00107 #endif
00108
00109 int testQuantile (Cdf f_cdf, Quant f_quantile, bool c= false) {
00110 int iret = 0;
00111 double z1,z2,q;
00112 z1 = 1.0E-6;
00113 for (int i = 0; i < 10; ++i) {
00114 q = f_quantile(z1,p[0]);
00115 z2 = f_cdf(q, p[0],0.);
00116 if (!c)
00117 iret |= compare("test quantile", z1, z2, scale);
00118 else
00119 iret |= compare("test quantile_c", z1, z2, scale);
00120 z1 += 0.1;
00121 }
00122 return iret;
00123 }
00124
00125 double p[1];
00126 double scale;
00127 };
00128
00129
00130
00131
00132 struct TestFunc2 {
00133
00134 typedef double ( * Pdf) ( double, double, double, double);
00135 typedef double ( * Cdf) ( double, double, double, double);
00136 typedef double ( * Quant) ( double, double, double);
00137
00138
00139 struct PdfFunction {
00140 PdfFunction( Pdf pdf, double p1, double p2 ) : fPdf(pdf), fP1(p1), fP2(p2) {}
00141 double operator() ( double x) const { return fPdf(x,fP1,fP2,0.0); }
00142
00143 Pdf fPdf;
00144 double fP1;
00145 double fP2;
00146 };
00147
00148 TestFunc2( double p1, double p2, double s = 2) :
00149 scale(s)
00150 {
00151 p[0] = p1,
00152 p[1] = p2;
00153 }
00154
00155 #ifndef NO_MATHCORE // skip cdf test when Mathcore is missing
00156
00157 int testCdf( Pdf f_pdf, Cdf f_cdf, bool c = false) {
00158 int iret = 0;
00159 double val = 1.0;
00160 double q1 = f_cdf(val, p[0],p[1],0.0);
00161
00162 PdfFunction f(f_pdf,p[0],p[1]);
00163 WrappedFunction<PdfFunction> wf(f);
00164 GSLIntegrator ig(1.E-12,1.E-12,100000);
00165 ig.SetFunction(wf);
00166 if (!c) {
00167
00168 double q2 = ig.IntegralLow(val);
00169
00170 iret |= compare("test _cdf", q1, q2, 1.0E6);
00171 }
00172 else {
00173
00174 double q2 = ig.IntegralUp(val);
00175 iret |= compare("test _cdf_c", q1, q2, 1.0E6);
00176 }
00177 return iret;
00178 }
00179
00180 #endif
00181
00182 int testQuantile (Cdf f_cdf, Quant f_quantile, bool c=false) {
00183 int iret = 0;
00184 double z1,z2,q;
00185 z1 = 1.0E-6;
00186 for (int i = 0; i < 10; ++i) {
00187 q = f_quantile(z1,p[0],p[1]);
00188 z2 = f_cdf(q, p[0],p[1],0.0);
00189 if (!c)
00190 iret |= compare("test quantile", z1, z2, scale);
00191 else
00192 iret |= compare("test quantile_c", z1, z2, scale);
00193 z1 += 0.1;
00194 }
00195 return iret;
00196 }
00197
00198 double p[2];
00199 double scale;
00200 };
00201
00202 void printStatus(int iret) {
00203 if (iret == 0)
00204 std::cout <<"\t\t\t\t OK" << std::endl;
00205 else
00206 std::cout <<"\t\t\t\t FAILED " << std::endl;
00207 }
00208
00209 #ifndef NO_MATHCORE
00210
00211 #define TESTDIST1(name, p1, s) {\
00212 int ir = 0; \
00213 TestFunc1 t(p1,s);\
00214 ir |= t.testCdf( name ## _pdf , name ## _cdf );\
00215 ir |= t.testCdf( name ##_pdf , name ##_cdf_c,true);\
00216 ir |= t.testQuantile( name ## _cdf, name ##_quantile);\
00217 ir |= t.testQuantile( name ##_cdf_c, name ##_quantile_c,true);\
00218 printStatus(ir);\
00219 iret |= ir; }
00220
00221 #define TESTDIST2(name, p1, p2, s) {\
00222 int ir = 0; \
00223 TestFunc2 t(p1,p2,s);\
00224 ir |= t.testCdf( name ## _pdf , name ## _cdf );\
00225 ir |= t.testCdf( name ##_pdf , name ##_cdf_c,true);\
00226 ir |= t.testQuantile( name ## _cdf, name ##_quantile);\
00227 ir |= t.testQuantile( name ##_cdf_c, name ##_quantile_c,true);\
00228 printStatus(ir);\
00229 iret |= ir; }
00230
00231
00232
00233
00234 #else
00235
00236 #define TESTDIST1(name, p1, s) {\
00237 int ir = 0; \
00238 TestFunc1 t(p1,s);\
00239 ir |= t.testQuantile( name ## _cdf, name ##_quantile);\
00240 ir |= t.testQuantile( name ##_cdf_c, name ##_quantile_c,true);\
00241 printStatus(ir);\
00242 iret |= ir; }
00243
00244 #define TESTDIST2(name, p1, p2, s) {\
00245 int ir = 0; \
00246 TestFunc2 t(p1,p2,s);\
00247 ir |= t.testQuantile( name ## _cdf, name ##_quantile);\
00248 ir |= t.testQuantile( name ##_cdf_c, name ##_quantile_c,true);\
00249 printStatus(ir);\
00250 iret |= ir; }
00251
00252 #endif
00253
00254
00255 double mbeta_pdf(double x, double a, double b, double){
00256 return beta_pdf(x,a,b);
00257 }
00258 double mbeta_cdf(double x, double a, double b, double){
00259 return beta_cdf(x,a,b);
00260 }
00261 double mbeta_cdf_c(double x, double a, double b, double){
00262 return beta_cdf_c(x,a,b);
00263 }
00264 double mbeta_quantile(double x, double a, double b){
00265 return beta_quantile(x,a,b);
00266 }
00267 double mbeta_quantile_c(double x, double a, double b){
00268 return beta_quantile_c(x,a,b);
00269 }
00270
00271
00272 #ifndef NO_MATHCORE
00273
00274 int testPoissonCdf(double mu,double tol) {
00275 int iret = 0;
00276 for (int i = 0; i < 12; ++i) {
00277 double q1 = poisson_cdf(i,mu);
00278 double q1c = 1.- poisson_cdf_c(i,mu);
00279 double q2 = 0;
00280 for (int j = 0; j <= i; ++j) {
00281 q2 += poisson_pdf(j,mu);
00282 }
00283 iret |= compare("test cdf",q1,q2,tol);
00284 iret |= compare("test cdf_c",q1c,q2,tol);
00285 }
00286 printStatus(iret);
00287 return iret;
00288 }
00289
00290 int testBinomialCdf(double p, int n, double tol) {
00291 int iret = 0;
00292 for (int i = 0; i < 12; ++i) {
00293 double q1 = binomial_cdf(i,p,n);
00294 double q1c = 1.- binomial_cdf_c(i,p,n);
00295 double q2 = 0;
00296 for (int j = 0; j <= i; ++j) {
00297 q2 += binomial_pdf(j,p,n);
00298 }
00299 iret |= compare("test cdf",q1,q2,tol);
00300 iret |= compare("test cdf_c",q1c,q2,tol);
00301 }
00302 printStatus(iret);
00303 return iret;
00304 }
00305
00306 #endif
00307
00308 int testStatFunc() {
00309
00310 int iret = 0;
00311 double tol = 2;
00312
00313
00314 #ifndef NO_MATHCORE
00315
00316 tol = 8;
00317 std::cout << "Poisson distrib. \t: ";
00318 double mu = 5;
00319 iret |= testPoissonCdf(mu,tol);
00320
00321 tol = 32;
00322 std::cout << "Binomial distrib. \t: ";
00323 double p = 0.5; int nt = 9;
00324 iret |= testBinomialCdf(p,nt,tol);
00325
00326 tol = 2;
00327 std::cout << "BreitWigner distrib\t: ";
00328 TESTDIST1(breitwigner,1.0,tol);
00329
00330 std::cout << "Cauchy distribution\t: ";
00331 TESTDIST1(cauchy,2.0,tol);
00332
00333 std::cout << "Exponential distrib\t: ";
00334 TESTDIST1(exponential,1.0,tol);
00335
00336 std::cout << "Gaussian distribution\t: ";
00337 TESTDIST1(gaussian,1.0,tol);
00338
00339 std::cout << "Log-normal distribution\t: ";
00340 TESTDIST2(lognormal,1.0,1.0,tol);
00341
00342 std::cout << "Normal distribution\t: ";
00343 TESTDIST1(normal,1.0,tol);
00344
00345 std::cout << "Uniform distribution\t: ";
00346 TESTDIST2(uniform,0.0,10.0,tol);
00347
00348
00349
00350 #endif
00351
00352 std::cout << "Chisquare distribution\t: ";
00353 tol = 8;
00354 TESTDIST1(chisquared,9.,tol);
00355
00356 tol = 2;
00357
00358 std::cout << "F distribution\t\t: ";
00359 double n = 5; double m = 6;
00360 TESTDIST2(fdistribution,n,m,tol);
00361
00362 std::cout << "Gamma distribution\t: ";
00363 double a = 1; double b = 2;
00364 TESTDIST2(gamma,a,b,tol);
00365
00366 std::cout << "t distribution\t\t: ";
00367 double nu = 10;
00368 TESTDIST1(tdistribution,nu,tol);
00369
00370 std::cout << "Beta distribution\t: ";
00371 a = 2; b = 1;
00372 TESTDIST2(mbeta,a,b,tol);
00373
00374
00375
00376 return iret;
00377 }
00378 int main() {
00379
00380 return testStatFunc();
00381 }