stressHistogram.cxx

Go to the documentation of this file.
00001 // @(#)root/test:$name:  $:$id: stressHistogram.cxx,v 1.15 2002/10/25 10:47:51 rdm exp $
00002 // Authors: David Gonzalez Maline November 2008
00003 
00004 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*//
00005 //                                                                               //
00006 //                                                                               //
00007 // Here there is a set of tests for the histogram classes (including             //
00008 // histograms and profiles). The methods tested work on:                         //
00009 //                                                                               //
00010 // 1. Projection testing (with and without weights)                              //
00011 // 2. Rebinning                                                                  //
00012 // 3. Addition, multiplication an division operations.                           //
00013 // 4. Building and copying instances.                                            //
00014 // 5. I/O functionality (including reference with older versions).               //
00015 // 6. Labeling.                                                                  //
00016 // 7. Interpolation                                                              //
00017 //                                                                               //
00018 // To see the tests individually, at the bottom of the file the tests            //
00019 // are exectued using the structure TTestSuite, that defines the                 //
00020 // subset, the number of routines to be tested as well as the pointes            //
00021 // for these. Every tests is mean to be simple enough to be understood           //
00022 // without much comments.                                                        //
00023 //                                                                               //
00024 // Finally, for debugging reasons, the struct compareOptions can be              //
00025 // used to define the level of output of the tests, beging set                   //
00026 // generally for the whole suit in defaultEqualOptions.                          //
00027 // >> stressHistogram 1      : to print result for all tests                     //
00028 // >> stressHistogram 2      : ro print each comparison, done for each bin       //
00029 //                                                                               //
00030 // An example of output when all the tests run OK is shown below:                //
00031 // ****************************************************************************  //
00032 // *  Starting  stress  H I S T O G R A M                                     *  //
00033 // ****************************************************************************  //
00034 // Test  1: Testing Projections without weights..............................OK  //
00035 // Test  2: Testing Projections with weights.................................OK  //
00036 // Test  3: Projection with Range for Histograms and Profiles................OK  //
00037 // Test  4: Histogram Rebinning..............................................OK  //
00038 // Test  5: Add tests for 1D, 2D and 3D Histograms and Profiles..............OK  //
00039 // Test  6: Multiply tests for 1D, 2D and 3D Histograms......................OK  //
00040 // Test  7: Divide tests for 1D, 2D and 3D Histograms........................OK  //
00041 // Test  8: Copy tests for 1D, 2D and 3D Histograms and Profiles.............OK  //
00042 // Test  9: Read/Write tests for 1D, 2D and 3D Histograms and Profiles.......OK  //
00043 // Test 10: Merge tests for 1D, 2D and 3D Histograms and Profiles............OK  //
00044 // Test 11: Label tests for 1D Histograms (TAxis)............................OK  //
00045 // Test 12: Interpolation tests for Histograms...............................OK  //
00046 // Test 13: Scale tests for Profiles.........................................OK  //
00047 // Test 14: Integral tests for Histograms....................................OK  //
00048 // Test 15: TH1-THnSparse Conversion tests...................................OK  //
00049 // Test 16: Filldata tests for Histograms and Sparses........................OK  //
00050 // Test 17: Reference File Read for Histograms and Profiles..................OK  //
00051 // ****************************************************************************  //
00052 // stressHistogram: Real Time =  64.01 seconds Cpu Time =  63.89 seconds         //
00053 //  ROOTMARKS = 430.74 ROOT version: 5.25/01 branches/dev/mathDev@29787       //
00054 // ****************************************************************************  //
00055 //                                                                               //
00056 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*//
00057 
00058 
00059 #include <sstream>
00060 #include <cmath>
00061 
00062 #include "TH2.h"
00063 #include "TH3.h"
00064 #include "TH2.h"
00065 #include "THnSparse.h"
00066 
00067 #include "TProfile.h"
00068 #include "TProfile2D.h"
00069 #include "TProfile3D.h"
00070 
00071 #include "TF1.h"
00072 #include "TF2.h"
00073 #include "TF3.h"
00074 
00075 #include "Fit/SparseData.h"
00076 #include "HFitInterface.h"
00077 
00078 #include "TApplication.h"
00079 #include "TBenchmark.h"
00080 #include "Riostream.h"
00081 #include "TMath.h"
00082 #include "TRandom2.h"
00083 #include "TFile.h"
00084 #include "TClass.h"
00085 
00086 #include "TROOT.h"
00087 #include <algorithm>
00088 #include <cassert>
00089 
00090 const unsigned int __DRAW__ = 0;
00091 
00092 const Double_t minRange = 1;
00093 const Double_t maxRange = 5;
00094 
00095 const Double_t minRebin = 3;
00096 const Double_t maxRebin = 7;
00097 
00098 const int minBinValue = 1;
00099 const int maxBinValue = 10;
00100 
00101 const int nEvents = 1000;
00102 const int numberOfBins = 10;
00103 
00104 enum compareOptions {
00105    cmpOptNone=0,
00106    cmpOptPrint=1,
00107    cmpOptDebug=2,
00108    cmpOptNoError=4,
00109    cmpOptStats=8
00110 };
00111 
00112 int defaultEqualOptions = 0; //cmpOptPrint;
00113 //int defaultEqualOptions = cmpOptPrint;
00114 
00115 const double defaultErrorLimit = 1.E-10;
00116 
00117 enum RefFileEnum {
00118    refFileRead = 1,
00119    refFileWrite = 2
00120 };
00121 
00122 const int refFileOption = 1;
00123 TFile * refFile = 0;
00124 const char* refFileName = "http://root.cern.ch/files/stressHistogram.5.18.00.root";
00125 
00126 TRandom2 r;
00127 // set to zero if want to run different every time
00128 const int initialSeed = 0;   
00129 
00130 
00131 
00132 typedef bool ( * pointer2Test) ();
00133 
00134 struct TTestSuite {
00135    unsigned int nTests;
00136    char suiteName[75];
00137    pointer2Test* tests;
00138 };
00139 
00140 // Methods for histogram comparisions (later implemented)
00141 void printResult(const char* msg, bool status);
00142 void FillVariableRange(Double_t v[numberOfBins+1]);
00143 void FillHistograms(TH1D* h1, TH1D* h2, Double_t c1 = 1.0, Double_t c2 = 1.0);
00144 void FillProfiles(TProfile* p1, TProfile* p2, Double_t c1 = 1.0, Double_t c2 = 1.0);
00145 int equals(const char* msg, TH1D* h1, TH1D* h2, int options = 0, double ERRORLIMIT = defaultErrorLimit);
00146 int equals(const char* msg, TH2D* h1, TH2D* h2, int options = 0, double ERRORLIMIT = defaultErrorLimit);
00147 int equals(const char* msg, TH3D* h1, TH3D* h2, int options = 0, double ERRORLIMIT = defaultErrorLimit);
00148 int equals(const char* msg, THnSparse* h1, THnSparse* h2, int options = 0, double ERRORLIMIT = defaultErrorLimit);
00149 int equals(const char* msg, THnSparse* h1, TH1* h2, int options = 0, double ERRORLIMIT = defaultErrorLimit);
00150 int equals(Double_t n1, Double_t n2, double ERRORLIMIT = defaultErrorLimit);
00151 int compareStatistics( TH1* h1, TH1* h2, bool debug, double ERRORLIMIT = defaultErrorLimit);
00152 ostream& operator<<(ostream& out, TH1D* h);
00153 // old stresHistOpts.cxx file
00154 
00155 bool testAdd1() 
00156 {
00157    // Tests the first Add method for 1D Histograms
00158 
00159    Double_t c1 = r.Rndm();
00160    Double_t c2 = r.Rndm();
00161 
00162    TH1D* h1 = new TH1D("t1D1-h1", "h1-Title", numberOfBins, minRange, maxRange);
00163    TH1D* h2 = new TH1D("t1D1-h2", "h2-Title", numberOfBins, minRange, maxRange);
00164    TH1D* h3 = new TH1D("t1D1-h3", "h3=c1*h1+c2*h2", numberOfBins, minRange, maxRange);
00165 
00166    h1->Sumw2();h2->Sumw2();h3->Sumw2();
00167 
00168    FillHistograms(h1, h3, 1.0, c1);
00169    FillHistograms(h2, h3, 1.0, c2);
00170 
00171    TH1D* h4 = new TH1D("t1D1-h4", "h4=c1*h1+h2*c2", numberOfBins, minRange, maxRange);
00172    h4->Add(h1, h2, c1, c2);
00173 
00174    bool ret = equals("Add1D1", h3, h4, cmpOptStats, 1E-13);
00175    delete h1;
00176    delete h2;
00177    delete h3;
00178    return ret;
00179 }
00180 
00181 bool testAddProfile1() 
00182 {
00183    // Tests the first Add method for 1D Profiles
00184 
00185    Double_t c1 = r.Rndm();
00186    Double_t c2 = r.Rndm();
00187 
00188    TProfile* p1 = new TProfile("t1D1-p1", "p1-Title", numberOfBins, minRange, maxRange);
00189    TProfile* p2 = new TProfile("t1D1-p2", "p2-Title", numberOfBins, minRange, maxRange);
00190    TProfile* p3 = new TProfile("t1D1-p3", "p3=c1*p1+c2*p2", numberOfBins, minRange, maxRange);
00191 
00192    for ( Int_t e = 0; e < nEvents; ++e ) {
00193       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00194       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00195       p1->Fill(x, y, 1.0);
00196       p3->Fill(x, y,  c1);
00197    }
00198 
00199    for ( Int_t e = 0; e < nEvents; ++e ) {
00200       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00201       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00202       p2->Fill(x, y, 1.0);
00203       p3->Fill(x, y,  c2);
00204    }
00205 
00206    TProfile* p4 = new TProfile("t1D1-p4", "p4=c1*p1+p2*c2", numberOfBins, minRange, maxRange);
00207    p4->Add(p1, p2, c1, c2);
00208 
00209    bool ret = equals("Add1DProfile1", p3, p4, cmpOptStats, 1E-13);
00210    delete p1;
00211    delete p2;
00212    delete p3;
00213    return ret;
00214 }
00215 
00216 bool testAdd2() 
00217 {
00218    // Tests the second Add method for 1D Histograms
00219 
00220    Double_t c2 = r.Rndm();
00221 
00222    TH1D* h5 = new TH1D("t1D2-h5", "h5=   h6+c2*h7", numberOfBins, minRange, maxRange);
00223    TH1D* h6 = new TH1D("t1D2-h6", "h6-Title", numberOfBins, minRange, maxRange);
00224    TH1D* h7 = new TH1D("t1D2-h7", "h7-Title", numberOfBins, minRange, maxRange);
00225 
00226    h5->Sumw2();h6->Sumw2();h7->Sumw2();
00227 
00228    FillHistograms(h6, h5, 1.0, 1.0);
00229    FillHistograms(h7, h5, 1.0, c2);
00230 
00231    h6->Add(h7, c2);
00232    
00233    bool ret = equals("Add1D2", h5, h6, cmpOptStats, 1E-13);
00234    delete h5;
00235    delete h7;
00236    return ret;
00237 }
00238 
00239 bool testAddProfile2() 
00240 {
00241    // Tests the second Add method for 1D Profiles
00242 
00243    Double_t c2 = r.Rndm();
00244 
00245    TProfile* p5 = new TProfile("t1D2-p5", "p5=   p6+c2*p7", numberOfBins, minRange, maxRange);
00246    TProfile* p6 = new TProfile("t1D2-p6", "p6-Title", numberOfBins, minRange, maxRange);
00247    TProfile* p7 = new TProfile("t1D2-p7", "p7-Title", numberOfBins, minRange, maxRange);
00248 
00249    for ( Int_t e = 0; e < nEvents; ++e ) {
00250       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00251       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00252       p6->Fill(x, y, 1.0);
00253       p5->Fill(x, y, 1.0);
00254    }
00255 
00256    for ( Int_t e = 0; e < nEvents; ++e ) {
00257       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00258       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00259       p7->Fill(x, y, 1.0);
00260       p5->Fill(x, y,  c2);
00261    }
00262 
00263    p6->Add(p7, c2);
00264    
00265    bool ret = equals("Add1DProfile2", p5, p6, cmpOptStats, 1E-13);
00266    delete p5;
00267    delete p7;
00268    return ret;
00269 }
00270 
00271 bool testAdd3() 
00272 {
00273    // Tests the first add method to do scalation of 1D Histograms
00274 
00275    Double_t c1 = r.Rndm();
00276 
00277    TH1D* h1 = new TH1D("t1D1-h1", "h1-Title", numberOfBins, minRange, maxRange);
00278    TH1D* h2 = new TH1D("t1D1-h2", "h2=c1*h1+c2*h2", numberOfBins, minRange, maxRange);
00279 
00280    h1->Sumw2();h2->Sumw2();
00281 
00282    for ( Int_t e = 0; e < nEvents; ++e ) {
00283       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00284       h1->Fill(value,  1.0);
00285       h2->Fill(value, c1 / h1->GetBinWidth( h1->FindBin(value) ) );
00286    }
00287 
00288    TH1D* h3 = new TH1D("t1D1-h3", "h3=c1*h1", numberOfBins, minRange, maxRange);
00289    h3->Add(h1, h1, c1, -1);
00290 
00291    bool ret = equals("Add1D3", h2, h3, cmpOptStats, 1E-13);
00292    delete h1;
00293    delete h2;
00294    return ret;
00295 }
00296 
00297 bool testAddVar1()
00298 {
00299    // Tests the second Add method for 1D Histograms with variable bin size
00300 
00301    Double_t v[numberOfBins+1];
00302    FillVariableRange(v);
00303 
00304    Double_t c1 = r.Rndm();
00305    Double_t c2 = r.Rndm();
00306 
00307    TH1D* h1 = new TH1D("h1", "h1-Title", numberOfBins, v);
00308    TH1D* h2 = new TH1D("h2", "h2-Title", numberOfBins, v);
00309    TH1D* h3 = new TH1D("h3", "h3=c1*h1+c2*h2", numberOfBins, v);
00310 
00311    h1->Sumw2();h2->Sumw2();h3->Sumw2();
00312 
00313    FillHistograms(h1, h3, 1.0, c1);
00314    FillHistograms(h2, h3, 1.0, c2);
00315 
00316    TH1D* h4 = new TH1D("t1D1-h4", "h4=c1*h1+h2*c2", numberOfBins, v);
00317    h4->Add(h1, h2, c1, c2);
00318 
00319    bool ret = equals("AddVar1D1", h3, h4, cmpOptStats, 1E-13);
00320    delete h1;
00321    delete h2;
00322    delete h3;
00323    return ret;
00324 }
00325 
00326 bool testAddVarProf1()
00327 {
00328 
00329    // Tests the first Add method for 1D Profiles with variable bin size
00330 
00331    Double_t v[numberOfBins+1];
00332    FillVariableRange(v);
00333 
00334    Double_t c1 = r.Rndm();
00335    Double_t c2 = r.Rndm();
00336 
00337    TProfile* p1 = new TProfile("t1D1-p1", "p1-Title", numberOfBins, v);
00338    TProfile* p2 = new TProfile("t1D1-p2", "p2-Title", numberOfBins, v);
00339    TProfile* p3 = new TProfile("t1D1-p3", "p3=c1*p1+c2*p2", numberOfBins, v);
00340 
00341    FillProfiles(p1, p3, 1.0, c1);
00342    FillProfiles(p2, p3, 1.0, c2);
00343 
00344    TProfile* p4 = new TProfile("t1D1-p4", "p4=c1*p1+p2*c2", numberOfBins, v);
00345    p4->Add(p1, p2, c1, c2);
00346 
00347    bool ret = equals("AddVar1DProf1", p3, p4, cmpOptStats, 1E-13);
00348    delete p1;
00349    delete p2;
00350    delete p3;
00351 
00352    return ret;
00353 }
00354 
00355 bool testAddVar2()
00356 {
00357    // Tests the second Add method for 1D Histograms with variable bin size
00358 
00359    Double_t v[numberOfBins+1];
00360    FillVariableRange(v);
00361 
00362    Double_t c2 = r.Rndm();
00363 
00364    TH1D* h5 = new TH1D("t1D2-h5", "h5=   h6+c2*h7", numberOfBins, v);
00365    TH1D* h6 = new TH1D("t1D2-h6", "h6-Title", numberOfBins, v);
00366    TH1D* h7 = new TH1D("t1D2-h7", "h7-Title", numberOfBins, v);
00367 
00368    h5->Sumw2();h6->Sumw2();h7->Sumw2();
00369 
00370    FillHistograms(h6, h5, 1.0, 1.0);
00371    FillHistograms(h7, h5, 1.0, c2);
00372 
00373    h6->Add(h7, c2);
00374    
00375    bool ret = equals("AddVar1D2", h5, h6, cmpOptStats, 1E-13);
00376    delete h5;
00377    delete h7;
00378    return ret;
00379 }
00380 
00381 bool testAddVarProf2()
00382 {
00383    // Tests the second Add method for 1D Profiles with variable bin size
00384 
00385    Double_t v[numberOfBins+1];
00386    FillVariableRange(v);
00387 
00388    Double_t c2 = r.Rndm();
00389 
00390    TProfile* p5 = new TProfile("t1D2-p5", "p5=   p6+c2*p7", numberOfBins, v);
00391    TProfile* p6 = new TProfile("t1D2-p6", "p6-Title", numberOfBins, v);
00392    TProfile* p7 = new TProfile("t1D2-p7", "p7-Title", numberOfBins, v);
00393 
00394    p5->Sumw2();p6->Sumw2();p7->Sumw2();
00395 
00396    FillProfiles(p6, p5, 1.0, 1.0);
00397    FillProfiles(p7, p5, 1.0, c2);
00398 
00399    p6->Add(p7, c2);
00400    
00401    bool ret = equals("AddVar1D2", p5, p6, cmpOptStats, 1E-13);
00402    delete p5;
00403    delete p7;
00404    return ret;
00405 }
00406 
00407 bool testAdd2D3()
00408 {
00409    // Tests the first add method to do scalation of 2D Histograms
00410 
00411    Double_t c1 = r.Rndm();
00412 
00413    TH2D* h1 = new TH2D("t1D1-h1", "h1-Title", 
00414                        numberOfBins, minRange, maxRange,
00415                        numberOfBins+2, minRange, maxRange);
00416    TH2D* h2 = new TH2D("t1D1-h2", "h2=c1*h1+c2*h2", 
00417                        numberOfBins, minRange, maxRange,
00418                        numberOfBins+2, minRange, maxRange);
00419 
00420    h1->Sumw2();h2->Sumw2();
00421 
00422    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00423       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00424       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00425       h1->Fill(x, y, 1.0);
00426       Int_t binx = h1->GetXaxis()->FindBin(x);
00427       Int_t biny = h1->GetYaxis()->FindBin(y);
00428       Double_t area = h1->GetXaxis()->GetBinWidth( binx ) * h1->GetYaxis()->GetBinWidth( biny );
00429       h2->Fill(x, y, c1 / area);
00430    }
00431 
00432    TH2D* h3 = new TH2D("t1D1-h3", "h3=c1*h1", 
00433                        numberOfBins, minRange, maxRange,
00434                        numberOfBins+2, minRange, maxRange);
00435    h3->Add(h1, h1, c1, -1);
00436 
00437    bool ret = equals("Add1D2", h2, h3, cmpOptStats, 1E-10);
00438    delete h1;
00439    delete h2;
00440    return ret;
00441 }
00442 
00443 bool testAdd3D3()
00444 {
00445    // Tests the first add method to do scalation of 3D Histograms
00446 
00447    Double_t c1 = r.Rndm();
00448 
00449    TH3D* h1 = new TH3D("t1D1-h1", "h1-Title", 
00450                        numberOfBins, minRange, maxRange,
00451                        numberOfBins+1, minRange, maxRange,
00452                        numberOfBins+2, minRange, maxRange);
00453    TH3D* h2 = new TH3D("t1D1-h2", "h2=c1*h1+c2*h2", 
00454                        numberOfBins, minRange, maxRange,
00455                        numberOfBins+1, minRange, maxRange,
00456                        numberOfBins+2, minRange, maxRange);
00457 
00458    h1->Sumw2();h2->Sumw2();
00459 
00460    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00461       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00462       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00463       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00464       h1->Fill(x, y, z, 1.0);
00465       Int_t binx = h1->GetXaxis()->FindBin(x);
00466       Int_t biny = h1->GetYaxis()->FindBin(y);
00467       Int_t binz = h1->GetZaxis()->FindBin(z);
00468       Double_t area = h1->GetXaxis()->GetBinWidth( binx ) * 
00469                       h1->GetYaxis()->GetBinWidth( biny ) * 
00470                       h1->GetZaxis()->GetBinWidth( binz );
00471       h2->Fill(x, y, z, c1 / area);
00472    }
00473 
00474    TH3D* h3 = new TH3D("t1D1-h3", "h3=c1*h1", 
00475                        numberOfBins, minRange, maxRange,
00476                        numberOfBins+1, minRange, maxRange,
00477                        numberOfBins+2, minRange, maxRange);
00478    h3->Add(h1, h1, c1, -1);
00479 
00480    bool ret = equals("Add2D3", h2, h3, cmpOptStats, 1E-10);
00481    delete h1;
00482    delete h2;
00483    return ret;
00484 }
00485 
00486 bool testAdd2D1() 
00487 {
00488    // Tests the first Add method for 2D Histograms
00489 
00490    Double_t c1 = r.Rndm();
00491    Double_t c2 = r.Rndm();
00492 
00493    TH2D* h1 = new TH2D("t2D1-h1", "h1", 
00494                        numberOfBins, minRange, maxRange,
00495                        numberOfBins + 2, minRange, maxRange);
00496 
00497    TH2D* h2 = new TH2D("t2D1-h2", "h2", 
00498                        numberOfBins, minRange, maxRange,
00499                        numberOfBins + 2, minRange, maxRange);
00500 
00501    TH2D* h3 = new TH2D("t2D1-h3", "h3=c1*h1+c2*h2", 
00502                        numberOfBins, minRange, maxRange,
00503                        numberOfBins + 2, minRange, maxRange);
00504 
00505    h1->Sumw2();h2->Sumw2();h3->Sumw2();
00506 
00507    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00508       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00509       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00510       h1->Fill(x, y,  1.0);
00511       h3->Fill(x, y, c1);
00512    }
00513 
00514    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00515       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00516       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00517       h2->Fill(x, y,  1.0);
00518       h3->Fill(x, y, c2);
00519    }
00520 
00521    TH2D* h4 = new TH2D("t2D1-h4", "h4=c1*h1+c2*h2", 
00522                        numberOfBins, minRange, maxRange,
00523                        numberOfBins + 2, minRange, maxRange);
00524    h4->Add(h1, h2, c1, c2);
00525    bool ret = equals("Add2D1", h3, h4, cmpOptStats , 1E-10);
00526    delete h1;
00527    delete h2;
00528    delete h3;
00529    return ret;
00530 }
00531 
00532 bool testAdd2DProfile1() 
00533 {
00534    // Tests the first Add method for 1D Profiles
00535 
00536    Double_t c1 = r.Rndm();
00537    Double_t c2 = r.Rndm();
00538 
00539    TProfile2D* p1 = new TProfile2D("t2D1-p1", "p1", 
00540                                    numberOfBins, minRange, maxRange,
00541                                    numberOfBins + 2, minRange, maxRange);
00542 
00543    TProfile2D* p2 = new TProfile2D("t2D1-p2", "p2", 
00544                                    numberOfBins, minRange, maxRange,
00545                                    numberOfBins + 2, minRange, maxRange);
00546 
00547    TProfile2D* p3 = new TProfile2D("t2D1-p3", "p3=c1*p1+c2*p2", 
00548                                    numberOfBins, minRange, maxRange,
00549                                    numberOfBins + 2, minRange, maxRange);
00550 
00551    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00552       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00553       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00554       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00555       p1->Fill(x, y, z, 1.0);
00556       p3->Fill(x, y, z, c1);
00557    }
00558 
00559    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00560       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00561       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00562       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00563       p2->Fill(x, y, z, 1.0);
00564       p3->Fill(x, y, z, c2);
00565    }
00566 
00567    TProfile2D* p4 = new TProfile2D("t2D1-p4", "p4=c1*p1+c2*p2", 
00568                        numberOfBins, minRange, maxRange,
00569                        numberOfBins + 2, minRange, maxRange);
00570    p4->Add(p1, p2, c1, c2);
00571    bool ret = equals("Add2DProfile1", p3, p4, cmpOptStats , 1E-10);
00572    delete p1;
00573    delete p2;
00574    delete p3;
00575    return ret;
00576 }
00577 
00578 bool testAdd2D2() 
00579 {
00580    // Tests the second Add method for 2D Histograms
00581 
00582    Double_t c2 = r.Rndm();
00583 
00584    TH2D* h1 = new TH2D("t2D2-h1", "h1", 
00585                        numberOfBins, minRange, maxRange,
00586                        numberOfBins + 2, minRange, maxRange);
00587 
00588    TH2D* h2 = new TH2D("t2D2-h2", "h2", 
00589                        numberOfBins, minRange, maxRange,
00590                        numberOfBins + 2, minRange, maxRange);
00591 
00592    TH2D* h3 = new TH2D("t2D2-h3", "h3=h1+c2*h2", 
00593                        numberOfBins, minRange, maxRange,
00594                        numberOfBins + 2, minRange, maxRange);
00595 
00596    h1->Sumw2();h2->Sumw2();h3->Sumw2();
00597 
00598    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00599       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00600       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00601       h1->Fill(x, y,  1.0);
00602       h3->Fill(x, y,  1.0);
00603    }
00604 
00605    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00606       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00607       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00608       h2->Fill(x, y,  1.0);
00609       h3->Fill(x, y, c2);
00610    }
00611 
00612    h1->Add(h2, c2);
00613    bool ret = equals("Add2D2", h3, h1, cmpOptStats, 1E-10);
00614    delete h2;
00615    delete h3;
00616    return ret;
00617 }
00618 
00619 bool testAdd2DProfile2() 
00620 {
00621    // Tests the second Add method for 2D Profiles
00622 
00623    Double_t c2 = r.Rndm();
00624 
00625    TProfile2D* p1 = new TProfile2D("t2D2-p1", "p1", 
00626                                    numberOfBins, minRange, maxRange,
00627                                    numberOfBins + 2, minRange, maxRange);
00628 
00629    TProfile2D* p2 = new TProfile2D("t2D2-p2", "p2", 
00630                                    numberOfBins, minRange, maxRange,
00631                                    numberOfBins + 2, minRange, maxRange);
00632 
00633    TProfile2D* p3 = new TProfile2D("t2D2-p3", "p3=p1+c2*p2", 
00634                                    numberOfBins, minRange, maxRange,
00635                                    numberOfBins + 2, minRange, maxRange);
00636 
00637    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00638       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00639       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00640       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00641       p1->Fill(x, y, z, 1.0);
00642       p3->Fill(x, y, z, 1.0);
00643    }
00644 
00645    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00646       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00647       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00648       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00649       p2->Fill(x, y, z, 1.0);
00650       p3->Fill(x, y, z,  c2);
00651    }
00652 
00653    p1->Add(p2, c2);
00654    bool ret = equals("Add2DProfile2", p3, p1, cmpOptStats, 1E-10);
00655    delete p2;
00656    delete p3;
00657    return ret;
00658 }
00659 
00660 bool testAdd3D1() 
00661 {
00662    // Tests the first Add method for 3D Histograms
00663 
00664    Double_t c1 = r.Rndm();
00665    Double_t c2 = r.Rndm();
00666 
00667    TH3D* h1 = new TH3D("t3D1-h1", "h1", 
00668                        numberOfBins, minRange, maxRange,
00669                        numberOfBins + 1, minRange, maxRange,
00670                        numberOfBins + 2, minRange, maxRange);
00671 
00672    TH3D* h2 = new TH3D("t3D1-h2", "h2", 
00673                        numberOfBins, minRange, maxRange,
00674                        numberOfBins + 1, minRange, maxRange,
00675                        numberOfBins + 2, minRange, maxRange);
00676 
00677    TH3D* h3 = new TH3D("t3D1-h3", "h3=c1*h1+c2*h2", 
00678                        numberOfBins, minRange, maxRange,
00679                        numberOfBins + 1, minRange, maxRange,
00680                        numberOfBins + 2, minRange, maxRange);
00681 
00682    h1->Sumw2();h2->Sumw2();h3->Sumw2();
00683 
00684    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00685       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00686       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00687       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00688       h1->Fill(x, y, z,  1.0);
00689       h3->Fill(x, y, z, c1);
00690    }
00691 
00692    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00693       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00694       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00695       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00696       h2->Fill(x, y, z,  1.0);
00697       h3->Fill(x, y, z, c2);
00698    }
00699 
00700    TH3D* h4 = new TH3D("t3D1-h4", "h4=c1*h1+c2*h2", 
00701                        numberOfBins, minRange, maxRange,
00702                        numberOfBins + 1, minRange, maxRange,
00703                        numberOfBins + 2, minRange, maxRange);
00704    h4->Add(h1, h2, c1, c2);
00705    bool ret = equals("Add3D1", h3, h4, cmpOptStats, 1E-10);
00706    delete h1;
00707    delete h2;
00708    delete h3;
00709    return ret;
00710 }
00711 
00712 bool testAdd3DProfile1() 
00713 {
00714    // Tests the second Add method for 3D Profiles
00715 
00716    Double_t c1 = r.Rndm();
00717    Double_t c2 = r.Rndm();
00718 
00719    TProfile3D* p1 = new TProfile3D("t3D1-p1", "p1", 
00720                                    numberOfBins, minRange, maxRange,
00721                                    numberOfBins + 1, minRange, maxRange,
00722                                    numberOfBins + 2, minRange, maxRange);
00723 
00724    TProfile3D* p2 = new TProfile3D("t3D1-p2", "p2", 
00725                                    numberOfBins, minRange, maxRange,
00726                                    numberOfBins + 1, minRange, maxRange,
00727                                    numberOfBins + 2, minRange, maxRange);
00728 
00729    TProfile3D* p3 = new TProfile3D("t3D1-p3", "p3=c1*p1+c2*p2", 
00730                                    numberOfBins, minRange, maxRange,
00731                                    numberOfBins + 1, minRange, maxRange,
00732                                    numberOfBins + 2, minRange, maxRange);
00733 
00734    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00735       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00736       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00737       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00738       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00739       p1->Fill(x, y, z, t, 1.0);
00740       p3->Fill(x, y, z, t,  c1);
00741    }
00742 
00743    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00744       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00745       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00746       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00747       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00748       p2->Fill(x, y, z, t, 1.0);
00749       p3->Fill(x, y, z, t,  c2);
00750    }
00751 
00752    TProfile3D* p4 = new TProfile3D("t3D1-p4", "p4=c1*p1+c2*p2", 
00753                                    numberOfBins, minRange, maxRange,
00754                                    numberOfBins + 1, minRange, maxRange,
00755                                    numberOfBins + 2, minRange, maxRange);
00756    p4->Add(p1, p2, c1, c2);
00757    bool ret = equals("Add3DProfile1", p3, p4, cmpOptStats, 1E-10);
00758    delete p1;
00759    delete p2;
00760    delete p3;
00761    return ret;
00762 }
00763 
00764 bool testAdd3D2() 
00765 {
00766    // Tests the second Add method for 3D Histograms
00767 
00768    Double_t c2 = r.Rndm();
00769 
00770    TH3D* h1 = new TH3D("t3D2-h1", "h1", 
00771                        numberOfBins, minRange, maxRange,
00772                        numberOfBins + 1, minRange, maxRange,
00773                        numberOfBins + 2, minRange, maxRange);
00774 
00775    TH3D* h2 = new TH3D("t3D2-h2", "h2", 
00776                        numberOfBins, minRange, maxRange,
00777                        numberOfBins + 1, minRange, maxRange,
00778                        numberOfBins + 2, minRange, maxRange);
00779 
00780    TH3D* h3 = new TH3D("t3D2-h3", "h3=h1+c2*h2", 
00781                        numberOfBins, minRange, maxRange,
00782                        numberOfBins + 1, minRange, maxRange,
00783                        numberOfBins + 2, minRange, maxRange);
00784 
00785    h1->Sumw2();h2->Sumw2();h3->Sumw2();
00786 
00787    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00788       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00789       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00790       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00791       h1->Fill(x, y, z,  1.0);
00792       h3->Fill(x, y, z,  1.0);
00793    }
00794 
00795    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00796       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00797       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00798       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00799       h2->Fill(x, y, z,  1.0);
00800       h3->Fill(x, y, z, c2);
00801    }
00802 
00803    h1->Add(h2, c2);
00804    bool ret = equals("Add3D2", h3, h1, cmpOptStats, 1E-10);
00805    delete h2;
00806    delete h3;
00807    return ret;
00808 }
00809 
00810 bool testAdd3DProfile2() 
00811 {
00812    // Tests the second Add method for 3D Profiles
00813 
00814    Double_t c2 = r.Rndm();
00815 
00816    TProfile3D* p1 = new TProfile3D("t3D2-p1", "p1", 
00817                                    numberOfBins, minRange, maxRange,
00818                                    numberOfBins + 1, minRange, maxRange,
00819                                    numberOfBins + 2, minRange, maxRange);
00820    
00821    TProfile3D* p2 = new TProfile3D("t3D2-p2", "p2", 
00822                                    numberOfBins, minRange, maxRange,
00823                                    numberOfBins + 1, minRange, maxRange,
00824                                    numberOfBins + 2, minRange, maxRange);
00825    
00826    TProfile3D* p3 = new TProfile3D("t3D2-p3", "p3=p1+c2*p2", 
00827                                    numberOfBins, minRange, maxRange,
00828                                    numberOfBins + 1, minRange, maxRange,
00829                                    numberOfBins + 2, minRange, maxRange);
00830    
00831    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00832       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00833       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00834       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00835       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00836       p1->Fill(x, y, z, t, 1.0);
00837       p3->Fill(x, y, z, t, 1.0);
00838    }
00839 
00840    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00841       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00842       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00843       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00844       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00845       p2->Fill(x, y, z, t, 1.0);
00846       p3->Fill(x, y, z, t,  c2);
00847    }
00848 
00849    p1->Add(p2, c2);
00850    bool ret = equals("Add3DProfile2", p3, p1, cmpOptStats, 1E-10);
00851    delete p2;
00852    delete p3;
00853    return ret;
00854 }
00855 
00856 bool testAddSparse()
00857 {
00858    // Tests the Add method for Sparse Histograms
00859 
00860    Double_t c = r.Rndm();
00861 
00862    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
00863                           TMath::Nint( r.Uniform(1, 5) ),
00864                           TMath::Nint( r.Uniform(1, 5) )};
00865    Double_t xmin[] = {minRange, minRange, minRange};
00866    Double_t xmax[] = {maxRange, maxRange, maxRange};
00867 
00868    THnSparseD* s1 = new THnSparseD("tS-s1", "s1", 3, bsize, xmin, xmax);
00869    THnSparseD* s2 = new THnSparseD("tS-s2", "s2", 3, bsize, xmin, xmax);
00870    THnSparseD* s3 = new THnSparseD("tS-s3", "s3=s1+c*s2", 3, bsize, xmin, xmax);
00871 
00872    s1->Sumw2();s2->Sumw2();s3->Sumw2();
00873 
00874    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00875       Double_t points[3];
00876       points[0] = r.Uniform( minRange * .9 , maxRange * 1.1 );
00877       points[1] = r.Uniform( minRange * .9 , maxRange * 1.1 );
00878       points[2] = r.Uniform( minRange * .9 , maxRange * 1.1 );
00879       s1->Fill(points);
00880       s3->Fill(points);
00881    }
00882 
00883    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
00884       Double_t points[3];
00885       points[0] = r.Uniform( minRange * .9 , maxRange * 1.1 );
00886       points[1] = r.Uniform( minRange * .9 , maxRange * 1.1 );
00887       points[2] = r.Uniform( minRange * .9 , maxRange * 1.1 );
00888       s2->Fill(points);
00889       s3->Fill(points, c);
00890    }
00891 
00892    s1->Add(s2, c);
00893    bool ret = equals("AddSparse", s3, s1, cmpOptStats , 1E-10);
00894    delete s2;
00895    delete s3;
00896    return ret;
00897 }
00898 
00899 bool testMul1() 
00900 {
00901    // Tests the first Multiply method for 1D Histograms
00902 
00903    Double_t c1 = r.Rndm();
00904    Double_t c2 = r.Rndm();
00905 
00906    TH1D* h1 = new TH1D("m1D1-h1", "h1-Title", numberOfBins, minRange, maxRange);
00907    TH1D* h2 = new TH1D("m1D1-h2", "h2-Title", numberOfBins, minRange, maxRange);
00908    TH1D* h3 = new TH1D("m1D1-h3", "h3=c1*h1*c2*h2", numberOfBins, minRange, maxRange);
00909 
00910    h1->Sumw2();h2->Sumw2();h3->Sumw2();
00911 
00912    UInt_t seed = r.GetSeed();
00913    // For possible problems
00914    r.SetSeed(seed);
00915    for ( Int_t e = 0; e < nEvents; ++e ) {
00916       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00917       h1->Fill(value, 1.0);
00918    }
00919 
00920    for ( Int_t e = 0; e < nEvents; ++e ) {
00921       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00922       h2->Fill(value,  1.0);
00923       h3->Fill(value,  c1*c2*h1->GetBinContent( h1->GetXaxis()->FindBin(value) ) );
00924    }
00925 
00926    // h3 has to be filled again so that the erros are properly calculated
00927    r.SetSeed(seed);
00928    for ( Int_t e = 0; e < nEvents; ++e ) {
00929       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00930       h3->Fill(value,  c1*c2*h2->GetBinContent( h2->GetXaxis()->FindBin(value) ) );
00931    }
00932 
00933    // No the bin contents has to be reduced, as it was filled twice!
00934    for ( Int_t bin = 0; bin <= h3->GetNbinsX() + 1; ++bin ) {
00935       h3->SetBinContent(bin, h3->GetBinContent(bin) / 2 );
00936    }
00937 
00938    TH1D* h4 = new TH1D("m1D1-h4", "h4=h1*h2", numberOfBins, minRange, maxRange);
00939    h4->Multiply(h1, h2, c1, c2);
00940 
00941    bool ret = equals("Multiply1D1", h3, h4, cmpOptStats  , 1E-14);
00942    delete h1;
00943    delete h2;
00944    delete h3;
00945    return ret;
00946 }
00947 
00948 bool testMulVar1() 
00949 {
00950    // Tests the first Multiply method for 1D Histograms with variable bin size
00951 
00952    Double_t v[numberOfBins+1];
00953    FillVariableRange(v);
00954 
00955    Double_t c1 = r.Rndm();
00956    Double_t c2 = r.Rndm();
00957 
00958    TH1D* h1 = new TH1D("m1D1-h1", "h1-Title", numberOfBins, v);
00959    TH1D* h2 = new TH1D("m1D1-h2", "h2-Title", numberOfBins, v);
00960    TH1D* h3 = new TH1D("m1D1-h3", "h3=c1*h1*c2*h2", numberOfBins, v);
00961 
00962    h1->Sumw2();h2->Sumw2();h3->Sumw2();
00963 
00964    UInt_t seed = r.GetSeed();
00965    // For possible problems
00966    r.SetSeed(seed);
00967    for ( Int_t e = 0; e < nEvents; ++e ) {
00968       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00969       h1->Fill(value, 1.0);
00970    }
00971 
00972    for ( Int_t e = 0; e < nEvents; ++e ) {
00973       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00974       h2->Fill(value,  1.0);
00975       h3->Fill(value,  c1*c2*h1->GetBinContent( h1->GetXaxis()->FindBin(value) ) );
00976    }
00977 
00978    // h3 has to be filled again so that the erros are properly calculated
00979    r.SetSeed(seed);
00980    for ( Int_t e = 0; e < nEvents; ++e ) {
00981       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
00982       h3->Fill(value,  c1*c2*h2->GetBinContent( h2->GetXaxis()->FindBin(value) ) );
00983    }
00984 
00985    // No the bin contents has to be reduced, as it was filled twice!
00986    for ( Int_t bin = 0; bin <= h3->GetNbinsX() + 1; ++bin ) {
00987       h3->SetBinContent(bin, h3->GetBinContent(bin) / 2 );
00988    }
00989 
00990    TH1D* h4 = new TH1D("m1D1-h4", "h4=h1*h2", numberOfBins, v);
00991    h4->Multiply(h1, h2, c1, c2);
00992 
00993    bool ret = equals("MultiVar1D1", h3, h4, cmpOptStats, 1E-14);
00994    delete h1;
00995    delete h2;
00996    delete h3;
00997    return ret;
00998 }
00999 
01000 bool testMul2() 
01001 {
01002    // Tests the second Multiply method for 1D Histograms
01003 
01004    TH1D* h1 = new TH1D("m1D2-h1", "h1-Title", numberOfBins, minRange, maxRange);
01005    TH1D* h2 = new TH1D("m1D2-h2", "h2-Title", numberOfBins, minRange, maxRange);
01006    TH1D* h3 = new TH1D("m1D2-h3", "h3=h1*h2", numberOfBins, minRange, maxRange);
01007 
01008    h1->Sumw2();h2->Sumw2();h3->Sumw2();
01009 
01010    UInt_t seed = r.GetSeed();
01011    // For possible problems
01012    r.SetSeed(seed);
01013    for ( Int_t e = 0; e < nEvents; ++e ) {
01014       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01015       h1->Fill(value, 1.0);
01016    }
01017 
01018    for ( Int_t e = 0; e < nEvents; ++e ) {
01019       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01020       h2->Fill(value,  1.0);
01021       h3->Fill(value,  h1->GetBinContent( h1->GetXaxis()->FindBin(value) ) );
01022    }
01023 
01024    r.SetSeed(seed);
01025    for ( Int_t e = 0; e < nEvents; ++e ) {
01026       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01027       h3->Fill(value,  h2->GetBinContent( h2->GetXaxis()->FindBin(value) ) );
01028    }
01029 
01030    for ( Int_t bin = 0; bin <= h3->GetNbinsX() + 1; ++bin ) {
01031       h3->SetBinContent(bin, h3->GetBinContent(bin) / 2 );
01032    }
01033 
01034    h1->Multiply(h2);
01035 
01036    bool ret = equals("Multiply1D2", h3, h1, cmpOptStats, 1E-14);
01037    delete h2;
01038    delete h3;
01039    return ret;
01040 }
01041 
01042 bool testMulVar2() 
01043 {
01044    // Tests the second Multiply method for 1D Histograms with variable bin size
01045 
01046    Double_t v[numberOfBins+1];
01047    FillVariableRange(v);
01048 
01049    TH1D* h1 = new TH1D("m1D2-h1", "h1-Title", numberOfBins, v);
01050    TH1D* h2 = new TH1D("m1D2-h2", "h2-Title", numberOfBins, v);
01051    TH1D* h3 = new TH1D("m1D2-h3", "h3=h1*h2", numberOfBins, v);
01052 
01053    h1->Sumw2();h2->Sumw2();h3->Sumw2();
01054 
01055    UInt_t seed = r.GetSeed();
01056    // For possible problems
01057    r.SetSeed(seed);
01058    for ( Int_t e = 0; e < nEvents; ++e ) {
01059       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01060       h1->Fill(value, 1.0);
01061    }
01062 
01063    for ( Int_t e = 0; e < nEvents; ++e ) {
01064       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01065       h2->Fill(value,  1.0);
01066       h3->Fill(value,  h1->GetBinContent( h1->GetXaxis()->FindBin(value) ) );
01067    }
01068 
01069    r.SetSeed(seed);
01070    for ( Int_t e = 0; e < nEvents; ++e ) {
01071       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01072       h3->Fill(value,  h2->GetBinContent( h2->GetXaxis()->FindBin(value) ) );
01073    }
01074 
01075    for ( Int_t bin = 0; bin <= h3->GetNbinsX() + 1; ++bin ) {
01076       h3->SetBinContent(bin, h3->GetBinContent(bin) / 2 );
01077    }
01078 
01079    h1->Multiply(h2);
01080 
01081    bool ret = equals("MultiVar1D2", h3, h1, cmpOptStats, 1E-14);
01082    delete h2;
01083    delete h3;
01084    return ret;
01085 }
01086 
01087 bool testMul2D1() 
01088 {
01089    // Tests the first Multiply method for 2D Histograms
01090 
01091    Double_t c1 = r.Rndm();
01092    Double_t c2 = r.Rndm();
01093 
01094    TH2D* h1 = new TH2D("m2D1-h1", "h1-Title", 
01095                        numberOfBins, minRange, maxRange,
01096                        numberOfBins + 2, minRange, maxRange);
01097    TH2D* h2 = new TH2D("m2D1-h2", "h2-Title", 
01098                        numberOfBins, minRange, maxRange,
01099                        numberOfBins + 2, minRange, maxRange);
01100    TH2D* h3 = new TH2D("m2D1-h3", "h3=c1*h1*c2*h2",
01101                        numberOfBins, minRange, maxRange,
01102                        numberOfBins + 2, minRange, maxRange);
01103 
01104    h1->Sumw2();h2->Sumw2();h3->Sumw2();
01105 
01106    UInt_t seed = r.GetSeed();
01107    // For possible problems
01108    r.SetSeed(seed);
01109    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01110       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01111       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01112       h1->Fill(x, y, 1.0);
01113    }
01114 
01115    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01116       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01117       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01118       h2->Fill(x, y,  1.0);
01119       h3->Fill(x, y,  c1*c2*h1->GetBinContent( h1->GetXaxis()->FindBin(x),
01120                                                h1->GetYaxis()->FindBin(y) ) );
01121    }
01122 
01123    // h3 has to be filled again so that the erros are properly calculated
01124    r.SetSeed(seed);
01125    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01126       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01127       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01128       h3->Fill(x, y,  c1*c2*h2->GetBinContent( h2->GetXaxis()->FindBin(x),
01129                                                h2->GetYaxis()->FindBin(y) ) );
01130    }
01131 
01132    // No the bin contents has to be reduced, as it was filled twice!
01133    for ( Int_t i = 0; i <= h3->GetNbinsX() + 1; ++i ) {
01134       for ( Int_t j = 0; j <= h3->GetNbinsY() + 1; ++j ) {
01135          h3->SetBinContent(i, j, h3->GetBinContent(i, j) / 2 );
01136       }
01137    }
01138 
01139    TH2D* h4 = new TH2D("m2D1-h4", "h4=h1*h2", 
01140                        numberOfBins, minRange, maxRange,
01141                        numberOfBins + 2, minRange, maxRange);
01142    h4->Multiply(h1, h2, c1, c2);
01143 
01144    bool ret = equals("Multiply2D1", h3, h4, cmpOptStats, 1E-12);
01145    delete h1;
01146    delete h2;
01147    delete h3;
01148    return ret;
01149 }
01150 
01151 bool testMul2D2() 
01152 {
01153    // Tests the second Multiply method for 2D Histograms
01154 
01155    TH2D* h1 = new TH2D("m2D2-h1", "h1-Title", 
01156                        numberOfBins, minRange, maxRange,
01157                        numberOfBins + 2, minRange, maxRange);
01158    TH2D* h2 = new TH2D("m2D2-h2", "h2-Title", 
01159                        numberOfBins, minRange, maxRange,
01160                        numberOfBins + 2, minRange, maxRange);
01161    TH2D* h3 = new TH2D("m2D2-h3", "h3=h1*h2",
01162                        numberOfBins, minRange, maxRange,
01163                        numberOfBins + 2, minRange, maxRange);
01164 
01165    h1->Sumw2();h2->Sumw2();h3->Sumw2();
01166 
01167    UInt_t seed = r.GetSeed();
01168    // For possible problems
01169    r.SetSeed(seed);
01170    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01171       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01172       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01173       h1->Fill(x, y, 1.0);
01174    }
01175 
01176    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01177       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01178       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01179       h2->Fill(x, y,  1.0);
01180       h3->Fill(x, y,  h1->GetBinContent( h1->GetXaxis()->FindBin(x),
01181                                          h1->GetYaxis()->FindBin(y) ) );
01182    }
01183 
01184    // h3 has to be filled again so that the erros are properly calculated
01185    r.SetSeed(seed);
01186    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01187       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01188       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01189       h3->Fill(x, y,  h2->GetBinContent( h2->GetXaxis()->FindBin(x),
01190                                          h2->GetYaxis()->FindBin(y) ) );
01191    }
01192 
01193    // No the bin contents has to be reduced, as it was filled twice!
01194    for ( Int_t i = 0; i <= h3->GetNbinsX() + 1; ++i ) {
01195       for ( Int_t j = 0; j <= h3->GetNbinsY() + 1; ++j ) {
01196          h3->SetBinContent(i, j, h3->GetBinContent(i, j) / 2 );
01197       }
01198    }
01199 
01200    h1->Multiply(h2);
01201 
01202    bool ret = equals("Multiply2D2", h3, h1, cmpOptStats, 1E-12);
01203    delete h2;
01204    delete h3;
01205    return ret;
01206 }
01207 
01208 bool testMul3D1() 
01209 {
01210    // Tests the first Multiply method for 3D Histograms
01211 
01212    Double_t c1 = r.Rndm();
01213    Double_t c2 = r.Rndm();
01214 
01215    TH3D* h1 = new TH3D("m3D1-h1", "h1-Title", 
01216                        numberOfBins, minRange, maxRange,
01217                        numberOfBins + 1, minRange, maxRange,
01218                        numberOfBins + 2, minRange, maxRange);
01219    TH3D* h2 = new TH3D("m3D1-h2", "h2-Title", 
01220                        numberOfBins, minRange, maxRange,
01221                        numberOfBins + 1, minRange, maxRange,
01222                        numberOfBins + 2, minRange, maxRange);
01223    TH3D* h3 = new TH3D("m3D1-h3", "h3=c1*h1*c2*h2",
01224                        numberOfBins, minRange, maxRange,
01225                        numberOfBins + 1, minRange, maxRange,
01226                        numberOfBins + 2, minRange, maxRange);
01227 
01228    h1->Sumw2();h2->Sumw2();h3->Sumw2();
01229 
01230    UInt_t seed = r.GetSeed();
01231    // For possible problems
01232    r.SetSeed(seed);
01233    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01234       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01235       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01236       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01237       h1->Fill(x, y, z, 1.0);
01238    }
01239 
01240    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01241       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01242       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01243       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01244       h2->Fill(x, y, z,  1.0);
01245       h3->Fill(x, y, z,  c1*c2*h1->GetBinContent( h1->GetXaxis()->FindBin(x),
01246                                                   h1->GetYaxis()->FindBin(y),
01247                                                   h1->GetZaxis()->FindBin(z) ) );
01248    }
01249 
01250    // h3 has to be filled again so that the erros are properly calculated
01251    r.SetSeed(seed);
01252    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01253       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01254       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01255       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01256       h3->Fill(x, y, z,  c1*c2*h2->GetBinContent( h2->GetXaxis()->FindBin(x),
01257                                                   h2->GetYaxis()->FindBin(y),
01258                                                   h2->GetZaxis()->FindBin(z) ) );
01259    }
01260 
01261    // No the bin contents has to be reduced, as it was filled twice!
01262    for ( Int_t i = 0; i <= h3->GetNbinsX() + 1; ++i ) {
01263       for ( Int_t j = 0; j <= h3->GetNbinsY() + 1; ++j ) {
01264          for ( Int_t h = 0; h <= h3->GetNbinsZ() + 1; ++h ) {
01265             h3->SetBinContent(i, j, h, h3->GetBinContent(i, j, h) / 2 );
01266          }
01267       }
01268    }
01269 
01270    TH3D* h4 = new TH3D("m3D1-h4", "h4=h1*h2", 
01271                        numberOfBins, minRange, maxRange,
01272                        numberOfBins + 1, minRange, maxRange,
01273                        numberOfBins + 2, minRange, maxRange);
01274    h4->Multiply(h1, h2, c1, c2);
01275 
01276    bool ret = equals("Multiply3D1", h3, h4, cmpOptStats, 1E-13);
01277    delete h1;
01278    delete h2;
01279    delete h3;
01280    return ret;
01281 }
01282 
01283 bool testMul3D2() 
01284 {
01285    // Tests the second Multiply method for 3D Histograms
01286 
01287    TH3D* h1 = new TH3D("m3D2-h1", "h1-Title", 
01288                        numberOfBins, minRange, maxRange,
01289                        numberOfBins + 1, minRange, maxRange,
01290                        numberOfBins + 2, minRange, maxRange);
01291    TH3D* h2 = new TH3D("m3D2-h2", "h2-Title", 
01292                        numberOfBins, minRange, maxRange,
01293                        numberOfBins + 1, minRange, maxRange,
01294                        numberOfBins + 2, minRange, maxRange);
01295    TH3D* h3 = new TH3D("m3D2-h3", "h3=h1*h2",
01296                        numberOfBins, minRange, maxRange,
01297                        numberOfBins + 1, minRange, maxRange,
01298                        numberOfBins + 2, minRange, maxRange);
01299 
01300    h1->Sumw2();h2->Sumw2();h3->Sumw2();
01301 
01302    UInt_t seed = r.GetSeed();
01303    // For possible problems
01304    r.SetSeed(seed);
01305    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01306       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01307       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01308       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01309       h1->Fill(x, y, z, 1.0);
01310    }
01311 
01312    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01313       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01314       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01315       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01316       h2->Fill(x, y, z,  1.0);
01317       h3->Fill(x, y, z, h1->GetBinContent( h1->GetXaxis()->FindBin(x),
01318                                            h1->GetYaxis()->FindBin(y),
01319                                            h1->GetZaxis()->FindBin(z) ) );
01320    }
01321 
01322    // h3 has to be filled again so that the errors are properly calculated
01323    r.SetSeed(seed);
01324    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01325       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01326       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01327       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01328       h3->Fill(x, y, z, h2->GetBinContent( h2->GetXaxis()->FindBin(x),
01329                                            h2->GetYaxis()->FindBin(y),
01330                                            h2->GetZaxis()->FindBin(z) ) );
01331    }
01332 
01333    // No the bin contents has to be reduced, as it was filled twice!
01334    for ( Int_t i = 0; i <= h3->GetNbinsX() + 1; ++i ) {
01335       for ( Int_t j = 0; j <= h3->GetNbinsY() + 1; ++j ) {
01336          for ( Int_t h = 0; h <= h3->GetNbinsZ() + 1; ++h ) {
01337             h3->SetBinContent(i, j, h, h3->GetBinContent(i, j, h) / 2 );
01338          }
01339       }
01340    }
01341 
01342    h1->Multiply(h2);
01343 
01344    bool ret = equals("Multiply3D2", h3, h1, cmpOptStats, 1E-13);
01345    delete h2;
01346    delete h3;
01347    return ret;
01348 }
01349 
01350 bool testMulSparse()
01351 {
01352   // Tests the Multiply method for Sparse Histograms
01353 
01354    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
01355                      TMath::Nint( r.Uniform(1, 5) ),
01356                      TMath::Nint( r.Uniform(1, 5) )};
01357    Double_t xmin[] = {minRange, minRange, minRange};
01358    Double_t xmax[] = {maxRange, maxRange, maxRange};
01359 
01360    THnSparseD* s1 = new THnSparseD("m3D2-s1", "s1-Title", 3, bsize, xmin, xmax);
01361    THnSparseD* s2 = new THnSparseD("m3D2-s2", "s2-Title", 3, bsize, xmin, xmax);
01362    THnSparseD* s3 = new THnSparseD("m3D2-s3", "s3=s1*s2", 3, bsize, xmin, xmax);
01363 
01364    s1->Sumw2();s2->Sumw2();s3->Sumw2();
01365 
01366    UInt_t seed = r.GetSeed();
01367    // For possible problems
01368    r.SetSeed(seed);
01369    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01370       Double_t points[3];
01371       points[0] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01372       points[1] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01373       points[2] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01374       s1->Fill(points, 1.0);
01375    }
01376 
01377    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01378       Double_t points[3];
01379       points[0] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01380       points[1] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01381       points[2] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01382       s2->Fill(points, 1.0);
01383       Int_t points_s1[3];
01384       points_s1[0] = s1->GetAxis(0)->FindBin( points[0] );
01385       points_s1[1] = s1->GetAxis(1)->FindBin( points[1] );
01386       points_s1[2] = s1->GetAxis(2)->FindBin( points[2] );
01387       s3->Fill(points, s1->GetBinContent( points_s1 ) );
01388    }
01389 
01390    // s3 has to be filled again so that the errors are properly calculated
01391    r.SetSeed(seed);
01392    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01393       Double_t points[3];
01394       points[0] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01395       points[1] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01396       points[2] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01397       Int_t points_s2[3];
01398       points_s2[0] = s2->GetAxis(0)->FindBin( points[0] );
01399       points_s2[1] = s2->GetAxis(1)->FindBin( points[1] );
01400       points_s2[2] = s2->GetAxis(2)->FindBin( points[2] );
01401       s3->Fill(points, s2->GetBinContent( points_s2 ) );
01402    }
01403 
01404    // No the bin contents has to be reduced, as it was filled twice!
01405    for ( Long64_t i = 0; i < s3->GetNbins(); ++i ) {
01406       Int_t bin[3];
01407       Double_t v = s3->GetBinContent(i, bin);
01408       s3->SetBinContent( bin, v / 2 );
01409    }
01410 
01411    s1->Multiply(s2);
01412 
01413    bool ret = equals("MultSparse", s3, s1, cmpOptNone, 1E-10);
01414    delete s2;
01415    delete s3;
01416    return ret;
01417 }
01418 
01419 bool testMulF1D()
01420 {
01421    Double_t c1 = r.Rndm();
01422 
01423    TH1D* h1 = new TH1D("mf1D-h1", "h1-Title", numberOfBins, minRange, maxRange);
01424    TH1D* h2 = new TH1D("mf1D-h2", "h2=h1*c1*f1", numberOfBins, minRange, maxRange);
01425 
01426    TF1* f = new TF1("sin", "sin(x)", minRange - 2, maxRange + 2);
01427 
01428    h1->Sumw2();h2->Sumw2();
01429 
01430    UInt_t seed = r.GetSeed();
01431    // For possible problems
01432    r.SetSeed(seed);
01433    for ( Int_t e = 0; e < nEvents; ++e ) {
01434       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01435       h1->Fill(value, 1.0);
01436       h2->Fill(value, f->Eval( h2->GetBinCenter( h2->FindBin(value) ) ) * c1 );
01437    }
01438 
01439    h1->Multiply(f, c1);
01440 
01441    // stats fails because of the error precision
01442    int status = equals("MULF H1D", h1, h2); //,cmpOptStats | cmpOptDebug);
01443    delete h1;
01444    delete f;
01445    return status;
01446 }
01447 
01448 bool testMulF1D2()
01449 {
01450    Double_t c1 = r.Rndm();
01451 
01452    TH1D* h1 = new TH1D("mf1D2-h1", "h1-Title", numberOfBins, minRange, maxRange);
01453    TH1D* h2 = new TH1D("mf1D2-h2", "h2=h1*c1*f1", numberOfBins, minRange, maxRange);
01454 
01455    TF2* f = new TF2("sin2", "sin(x)*cos(y)", 
01456                     minRange - 2, maxRange + 2,
01457                     minRange - 2, maxRange + 2);
01458    h1->Sumw2();h2->Sumw2();
01459 
01460    UInt_t seed = r.GetSeed();
01461    // For possible problems
01462    r.SetSeed(seed);
01463    for ( Int_t e = 0; e < nEvents; ++e ) {
01464       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01465       h1->Fill(value, 1.0);
01466       h2->Fill(value, f->Eval( h2->GetXaxis()->GetBinCenter( h2->GetXaxis()->FindBin(value) ),
01467                                h2->GetYaxis()->GetBinCenter( h2->GetYaxis()->FindBin(double(0)) ) )
01468                * c1 );
01469    }
01470 
01471    h1->Multiply(f, c1);
01472 
01473    // stats fails because of the error precision
01474    int status = equals("MULF H1D2", h1, h2); //,cmpOptStats | cmpOptDebug);
01475    delete h1;
01476    delete f;
01477    return status;
01478 }
01479 
01480 bool testMulF2D()
01481 {
01482    Double_t c1 = r.Rndm();
01483 
01484    TH2D* h1 = new TH2D("mf2D-h1", "h1-Title", 
01485                        numberOfBins, minRange, maxRange,
01486                        numberOfBins, minRange, maxRange);
01487    TH2D* h2 = new TH2D("mf2D-h2", "h2=h1*c1*f1", 
01488                        numberOfBins, minRange, maxRange,
01489                        numberOfBins, minRange, maxRange);
01490 
01491    TF1* f = new TF1("sin", "sin(x)", minRange - 2, maxRange + 2);
01492    
01493    h1->Sumw2();h2->Sumw2();
01494 
01495    UInt_t seed = r.GetSeed();
01496    // For possible problems
01497    r.SetSeed(seed);
01498    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01499       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01500       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01501       h1->Fill(x, y, 1.0);
01502       h2->Fill(x, y, f->Eval( h2->GetXaxis()->GetBinCenter( h2->GetXaxis()->FindBin(x) ) ) * c1 );
01503    }
01504 
01505    h1->Multiply(f, c1);
01506 
01507    // stats fails because of the error precision
01508    int status = equals("MULF H2D", h1, h2); //, cmpOptStats | cmpOptDebug);
01509    delete h1;
01510    delete f;
01511    return status;
01512 }
01513 
01514 bool testMulF2D2()
01515 {
01516    Double_t c1 = r.Rndm();
01517 
01518    TH2D* h1 = new TH2D("mf2D2-h1", "h1-Title", 
01519                        numberOfBins, minRange, maxRange,
01520                        numberOfBins, minRange, maxRange);
01521    TH2D* h2 = new TH2D("mf2D2-h2", "h2=h1*c1*f1", 
01522                        numberOfBins, minRange, maxRange,
01523                        numberOfBins, minRange, maxRange);
01524 
01525    TF2* f = new TF2("sin2", "sin(x)*cos(y)", 
01526                     minRange - 2, maxRange + 2,
01527                     minRange - 2, maxRange + 2);
01528    
01529    h1->Sumw2();h2->Sumw2();
01530 
01531    UInt_t seed = r.GetSeed();
01532    // For possible problems
01533    r.SetSeed(seed);
01534    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01535       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01536       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01537       h1->Fill(x, y, 1.0);
01538       h2->Fill(x, y, f->Eval( h2->GetXaxis()->GetBinCenter( h2->GetXaxis()->FindBin(x) ),
01539                               h2->GetYaxis()->GetBinCenter( h2->GetYaxis()->FindBin(y) ) )
01540                * c1 );
01541    }
01542 
01543    h1->Multiply(f, c1);
01544 
01545    // stats fails because of the error precision
01546    int status = equals("MULF H2D2", h1, h2); //, cmpOptStats | cmpOptDebug);
01547    delete h1;
01548    delete f;
01549    return status;
01550 }
01551 
01552 bool testMulF3D()
01553 {
01554    Double_t c1 = r.Rndm();
01555 
01556    TH3D* h1 = new TH3D("mf3D-h1", "h1-Title", 
01557                        numberOfBins, minRange, maxRange,
01558                        numberOfBins, minRange, maxRange,
01559                        numberOfBins, minRange, maxRange);
01560    TH3D* h2 = new TH3D("mf3D-h2", "h2=h1*c1*f1", 
01561                        numberOfBins, minRange, maxRange,
01562                        numberOfBins, minRange, maxRange,
01563                        numberOfBins, minRange, maxRange);
01564 
01565    TF1* f = new TF1("sin", "sin(x)", minRange - 2, maxRange + 2);
01566    
01567    h1->Sumw2();h2->Sumw2();
01568 
01569    UInt_t seed = r.GetSeed();
01570    // For possible problems
01571    r.SetSeed(seed);
01572    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01573       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01574       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01575       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01576       h1->Fill(x, y, z, 1.0);
01577       h2->Fill(x, y, z, f->Eval( h2->GetXaxis()->GetBinCenter( h2->GetXaxis()->FindBin(x) ) ) * c1 );
01578    }
01579 
01580    h1->Multiply(f, c1);
01581 
01582    // stats fails because of the error precision
01583    int status = equals("MULF H3D", h1, h2); //, cmpOptStats | cmpOptDebug);
01584    delete h1;
01585    delete f;
01586    return status;
01587 }
01588 
01589 bool testMulF3D2()
01590 {
01591    Double_t c1 = r.Rndm();
01592 
01593    TH3D* h1 = new TH3D("mf3D2-h1", "h1-Title", 
01594                        numberOfBins, minRange, maxRange,
01595                        numberOfBins, minRange, maxRange,
01596                        numberOfBins, minRange, maxRange);
01597    TH3D* h2 = new TH3D("mf3D2-h2", "h2=h1*c1*f1", 
01598                        numberOfBins, minRange, maxRange,
01599                        numberOfBins, minRange, maxRange,
01600                        numberOfBins, minRange, maxRange);
01601 
01602    TF2* f = new TF2("sin2", "sin(x)*cos(y)", 
01603                     minRange - 2, maxRange + 2,
01604                     minRange - 2, maxRange + 2);
01605    
01606    h1->Sumw2();h2->Sumw2();
01607 
01608    UInt_t seed = r.GetSeed();
01609    // For possible problems
01610    r.SetSeed(seed);
01611    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01612       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01613       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01614       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01615       h1->Fill(x, y, z, 1.0);
01616       h2->Fill(x, y, z, f->Eval( h2->GetXaxis()->GetBinCenter( h2->GetXaxis()->FindBin(x) ),
01617                                  h2->GetYaxis()->GetBinCenter( h2->GetYaxis()->FindBin(y) ) )
01618                * c1 );
01619    }
01620 
01621    h1->Multiply(f, c1);
01622 
01623    // stats fails because of the error precision
01624    int status = equals("MULF H3D2", h1, h2); //, cmpOptStats | cmpOptDebug);
01625    delete h1;
01626    delete f;
01627    return status;
01628 }
01629 
01630 bool testMulFND()
01631 {
01632    const UInt_t nDims = 3;
01633    Double_t c1 = r.Rndm();
01634 
01635    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
01636                      TMath::Nint( r.Uniform(1, 5) ),
01637                      TMath::Nint( r.Uniform(1, 5) )};
01638    Double_t xmin[] = {minRange, minRange, minRange};
01639    Double_t xmax[] = {maxRange, maxRange, maxRange};
01640 
01641    THnSparseD* s1 = new THnSparseD("mfND-s1", "s1-Title", nDims, bsize, xmin, xmax);
01642    THnSparseD* s2 = new THnSparseD("mfND-s2", "s2=f*s2",  nDims, bsize, xmin, xmax);
01643 
01644    TF1* f = new TF1("sin", "sin(x)", minRange - 2, maxRange + 2);
01645    
01646    s1->Sumw2();s2->Sumw2();
01647 
01648    UInt_t seed = r.GetSeed();
01649    // For possible problems
01650    r.SetSeed(seed);
01651    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01652       Double_t points[nDims];
01653       for ( UInt_t i = 0; i < nDims; ++ i )
01654          points[i] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01655       s1->Fill(points, 1.0);
01656       s2->Fill(points, f->Eval( s2->GetAxis(0)->GetBinCenter( s2->GetAxis(0)->FindBin(points[0]) ) ) * c1);
01657    }
01658 
01659    s1->Multiply(f, c1);
01660 
01661    int status = equals("MULF HND", s1, s2);
01662    delete s1;
01663    delete f;
01664    return status;
01665 }
01666 
01667 bool testMulFND2()
01668 {
01669    const UInt_t nDims = 3;
01670    Double_t c1 = r.Rndm();
01671 
01672    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
01673                      TMath::Nint( r.Uniform(1, 5) ),
01674                      TMath::Nint( r.Uniform(1, 5) )};
01675    Double_t xmin[] = {minRange, minRange, minRange};
01676    Double_t xmax[] = {maxRange, maxRange, maxRange};
01677 
01678    THnSparseD* s1 = new THnSparseD("mfND-s1", "s1-Title", nDims, bsize, xmin, xmax);
01679    THnSparseD* s2 = new THnSparseD("mfND-s2", "s2=f*s2",  nDims, bsize, xmin, xmax);
01680 
01681    TF2* f = new TF2("sin2", "sin(x)*cos(y)", 
01682                     minRange - 2, maxRange + 2,
01683                     minRange - 2, maxRange + 2);
01684    
01685    s1->Sumw2();s2->Sumw2();
01686 
01687    UInt_t seed = r.GetSeed();
01688    // For possible problems
01689    r.SetSeed(seed);
01690    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
01691       Double_t points[nDims];
01692       for ( UInt_t i = 0; i < nDims; ++ i )
01693          points[i] = r.Uniform( minRange * .9 , maxRange * 1.1 );
01694       s1->Fill(points, 1.0);
01695       s2->Fill(points, f->Eval( s2->GetAxis(0)->GetBinCenter( s2->GetAxis(0)->FindBin(points[0]) ),
01696                                 s2->GetAxis(1)->GetBinCenter( s2->GetAxis(1)->FindBin(points[1]) ) )
01697                                 * c1);
01698    }
01699 
01700    s1->Multiply(f, c1);
01701 
01702    int status = equals("MULF HND2", s1, s2);
01703    delete s1;
01704    delete f;
01705    return status;
01706 }
01707 
01708 bool testDivide1() 
01709 {
01710    // Tests the first Divide method for 1D Histograms
01711 
01712    Double_t c1 = r.Rndm() + 1;
01713    Double_t c2 = r.Rndm() + 1;
01714 
01715    TH1D* h1 = new TH1D("d1D1-h1", "h1-Title", numberOfBins, minRange, maxRange);
01716    TH1D* h2 = new TH1D("d1D1-h2", "h2-Title", numberOfBins, minRange, maxRange);
01717 
01718    h1->Sumw2();h2->Sumw2();
01719 
01720    UInt_t seed = r.GetSeed();
01721    // For possible problems
01722    r.SetSeed(seed);
01723    for ( Int_t e = 0; e < nEvents; ++e ) {
01724       Double_t value;
01725       value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01726       h1->Fill(value, 1.0);
01727       value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01728       h2->Fill(value,  1.0);
01729    }
01730    // avoid bins in h2 with zero content
01731    for (int i = 0; i < h2->GetSize(); ++i) 
01732       if (h2->GetBinContent(i) == 0) h2->SetBinContent(i,1);
01733 
01734 
01735    TH1D* h3 = new TH1D("d1D1-h3", "h3=(c1*h1)/(c2*h2)", numberOfBins, minRange, maxRange);
01736    h3->Divide(h1, h2, c1, c2);
01737       
01738    TH1D* h4 = new TH1D("d1D1-h4", "h4=h3*h2)", numberOfBins, minRange, maxRange);
01739    h4->Multiply(h2, h3, c2/c1, 1);
01740    for ( Int_t bin = 0; bin <= h4->GetNbinsX() + 1; ++bin ) {
01741       Double_t error = h4->GetBinError(bin) * h4->GetBinError(bin);
01742       error -= (2*(c2*c2)/(c1*c1)) * h3->GetBinContent(bin)*h3->GetBinContent(bin)*h2->GetBinError(bin)*h2->GetBinError(bin); 
01743       h4->SetBinError( bin, sqrt(error) );
01744    }
01745    h4->ResetStats();
01746    h1->ResetStats(); 
01747 
01748    bool ret = equals("Divide1D1", h1, h4, cmpOptStats );
01749    delete h1;
01750    delete h2;
01751    delete h3;
01752    return ret;
01753 }
01754 
01755 bool testDivideVar1() 
01756 {
01757    // Tests the first Divide method for 1D Histograms with variable bin size
01758 
01759    Double_t v[numberOfBins+1];
01760    FillVariableRange(v);
01761 
01762    Double_t c1 = r.Rndm() + 1;
01763    Double_t c2 = r.Rndm() + 1;
01764 
01765    TH1D* h1 = new TH1D("d1D1-h1", "h1-Title", numberOfBins, v);
01766    TH1D* h2 = new TH1D("d1D1-h2", "h2-Title", numberOfBins, v);
01767 
01768    h1->Sumw2();h2->Sumw2();
01769 
01770    UInt_t seed = r.GetSeed();
01771    // For possible problems
01772    r.SetSeed(seed);
01773    for ( Int_t e = 0; e < nEvents; ++e ) {
01774       Double_t value;
01775       value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01776       h1->Fill(value, 1.0);
01777       value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01778       h2->Fill(value,  1.0);
01779    }
01780    // avoid bins in h2 with zero content
01781    for (int i = 0; i < h2->GetSize(); ++i) 
01782       if (h2->GetBinContent(i) == 0) h2->SetBinContent(i,1);
01783 
01784 
01785    TH1D* h3 = new TH1D("d1D1-h3", "h3=(c1*h1)/(c2*h2)", numberOfBins, v);
01786    h3->Divide(h1, h2, c1, c2);
01787       
01788    TH1D* h4 = new TH1D("d1D1-h4", "h4=h3*h2)", numberOfBins, v);
01789    h4->Multiply(h2, h3, c2/c1, 1);
01790    for ( Int_t bin = 0; bin <= h4->GetNbinsX() + 1; ++bin ) {
01791       Double_t error = h4->GetBinError(bin) * h4->GetBinError(bin);
01792       error -= (2*(c2*c2)/(c1*c1)) * h3->GetBinContent(bin)*h3->GetBinContent(bin)*h2->GetBinError(bin)*h2->GetBinError(bin); 
01793       h4->SetBinError( bin, sqrt(error) );
01794    }
01795    h4->ResetStats();
01796    h1->ResetStats(); 
01797 
01798    bool ret = equals("DivideVar1D1", h1, h4, cmpOptStats);
01799    delete h1;
01800    delete h2;
01801    delete h3;
01802    return ret;
01803 }
01804 
01805 
01806 bool testDivideProf1() 
01807 {
01808    // Tests the first Divide method for 1D Profiles
01809 
01810    Double_t c1 = 1;//r.Rndm();
01811    Double_t c2 = 1;//r.Rndm();
01812 
01813    TProfile* p1 = new TProfile("d1D1-p1", "p1-Title", numberOfBins, minRange, maxRange);
01814    TProfile* p2 = new TProfile("d1D1-p2", "p2-Title", numberOfBins, minRange, maxRange);
01815 
01816    p1->Sumw2();p2->Sumw2();
01817 
01818    UInt_t seed = r.GetSeed();
01819    // For possible problems
01820    r.SetSeed(seed);
01821    for ( Int_t e = 0; e < nEvents; ++e ) {
01822       Double_t x, y;
01823       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01824       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01825       p1->Fill(x, y, 1.0);
01826       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01827       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01828       p2->Fill(x, y, 1.0);
01829    }
01830 
01831 
01832    TProfile* p3 = new TProfile("d1D1-p3", "p3=(c1*p1)/(c2*p2)", numberOfBins, minRange, maxRange);
01833    p3->Divide(p1, p2, c1, c2);
01834 
01835    // There is no Multiply method to tests. And the errors are wrongly
01836    // calculated in the TProfile::Division method, so there is no
01837    // point to make the tests. Once the method is fixed, the tests
01838    // will be finished.
01839 
01840    return 0;
01841 }
01842 
01843 bool testDivide2() 
01844 {
01845    // Tests the second Divide method for 1D Histograms
01846 
01847    TH1D* h1 = new TH1D("d1D2-h1", "h1-Title", numberOfBins, minRange, maxRange);
01848    TH1D* h2 = new TH1D("d1D2-h2", "h2-Title", numberOfBins, minRange, maxRange);
01849 
01850    h1->Sumw2();h2->Sumw2();
01851 
01852    UInt_t seed = r.GetSeed();
01853    // For possible problems
01854    r.SetSeed(seed);
01855    for ( Int_t e = 0; e < nEvents; ++e ) {
01856       Double_t value;
01857       value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01858       h1->Fill(value, 1.0);
01859       value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01860       h2->Fill(value,  1.0);
01861    }
01862    // avoid bins in h2 with zero content
01863    for (int i = 0; i < h2->GetSize(); ++i) 
01864       if (h2->GetBinContent(i) == 0) h2->SetBinContent(i,1);
01865 
01866    TH1D* h3 = static_cast<TH1D*>( h1->Clone() );
01867    h3->Divide(h2);
01868       
01869    TH1D* h4 = new TH1D("d1D2-h4", "h4=h3*h2)", numberOfBins, minRange, maxRange);
01870    h4->Multiply(h2, h3, 1.0, 1.0);
01871    for ( Int_t bin = 0; bin <= h4->GetNbinsX() + 1; ++bin ) {
01872       Double_t error = h4->GetBinError(bin) * h4->GetBinError(bin);
01873       error -= 2 * h3->GetBinContent(bin)*h3->GetBinContent(bin)*h2->GetBinError(bin)*h2->GetBinError(bin); 
01874       h4->SetBinError( bin, sqrt(error) );
01875    }
01876 
01877    h4->ResetStats(); 
01878    h1->ResetStats(); 
01879 
01880    bool ret = equals("Divide1D2", h1, h4, cmpOptStats);
01881    delete h1;
01882    delete h2;
01883    delete h3;
01884    return ret;
01885 }
01886 
01887 bool testDivideVar2() 
01888 {
01889    // Tests the second Divide method for 1D Histograms with variable bin size
01890 
01891    Double_t v[numberOfBins+1];
01892    FillVariableRange(v);
01893 
01894    TH1D* h1 = new TH1D("d1D2-h1", "h1-Title", numberOfBins, v);
01895    TH1D* h2 = new TH1D("d1D2-h2", "h2-Title", numberOfBins, v);
01896 
01897    h1->Sumw2();h2->Sumw2();
01898 
01899    UInt_t seed = r.GetSeed();
01900    // For possible problems
01901    r.SetSeed(seed);
01902    for ( Int_t e = 0; e < nEvents; ++e ) {
01903       Double_t value;
01904       value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01905       h1->Fill(value, 1.0);
01906       value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01907       h2->Fill(value,  1.0);
01908    }
01909    // avoid bins in h2 with zero content
01910    for (int i = 0; i < h2->GetSize(); ++i) 
01911       if (h2->GetBinContent(i) == 0) h2->SetBinContent(i,1);
01912 
01913    TH1D* h3 = static_cast<TH1D*>( h1->Clone() );
01914    h3->Divide(h2);
01915       
01916    TH1D* h4 = new TH1D("d1D2-h4", "h4=h3*h2)", numberOfBins, v);
01917    h4->Multiply(h2, h3, 1.0, 1.0);
01918    for ( Int_t bin = 0; bin <= h4->GetNbinsX() + 1; ++bin ) {
01919       Double_t error = h4->GetBinError(bin) * h4->GetBinError(bin);
01920       error -= 2 * h3->GetBinContent(bin)*h3->GetBinContent(bin)*h2->GetBinError(bin)*h2->GetBinError(bin); 
01921       h4->SetBinError( bin, sqrt(error) );
01922    }
01923 
01924    h4->ResetStats(); 
01925    h1->ResetStats(); 
01926 
01927    bool ret = equals("DivideVar1D2", h1, h4, cmpOptStats);
01928    delete h1;
01929    delete h2;
01930    delete h3;
01931    return ret;
01932 }
01933 
01934 bool testDivide2D1() 
01935 {
01936    // Tests the first Divide method for 2D Histograms
01937 
01938    Double_t c1 = r.Rndm() + 1;
01939    Double_t c2 = r.Rndm() + 1;
01940 
01941    TH2D* h1 = new TH2D("d2D1-h1", "h1-Title", 
01942                        numberOfBins, minRange, maxRange,
01943                        numberOfBins + 2, minRange, maxRange);
01944    TH2D* h2 = new TH2D("d2D1-h2", "h2-Title", 
01945                        numberOfBins, minRange, maxRange,
01946                        numberOfBins + 2, minRange, maxRange);
01947 
01948    h1->Sumw2();h2->Sumw2();
01949 
01950    UInt_t seed = r.GetSeed();
01951    // For possible problems
01952    r.SetSeed(seed);
01953    for ( Int_t e = 0; e < nEvents*nEvents; ++e ) {
01954       Double_t x,y;
01955       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01956       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01957       h1->Fill(x, y, 1.0);
01958       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01959       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
01960       h2->Fill(x, y, 1.0);
01961    }
01962    // avoid bins in h2 with zero content
01963    for (int i = 0; i < h2->GetSize(); ++i) 
01964       if (h2->GetBinContent(i) == 0) h2->SetBinContent(i,1);
01965 
01966    TH2D* h3 = new TH2D("d2D1-h3", "h3=(c1*h1)/(c2*h2)", 
01967                        numberOfBins, minRange, maxRange,
01968                        numberOfBins + 2, minRange, maxRange);
01969    h3->Divide(h1, h2, c1, c2);
01970       
01971    TH2D* h4 = new TH2D("d2D1-h4", "h4=h3*h2)", 
01972                        numberOfBins, minRange, maxRange,
01973                        numberOfBins + 2, minRange, maxRange);
01974    h4->Multiply(h2, h3, c2/c1, 1);
01975    for ( Int_t i = 0; i <= h4->GetNbinsX() + 1; ++i ) {
01976       for ( Int_t j = 0; j <= h4->GetNbinsY() + 1; ++j ) {
01977          Double_t error = h4->GetBinError(i,j) * h4->GetBinError(i,j);
01978          error -= (2*(c2*c2)/(c1*c1)) * h3->GetBinContent(i,j)*h3->GetBinContent(i,j)*h2->GetBinError(i,j)*h2->GetBinError(i,j); 
01979          h4->SetBinError( i, j, sqrt(error) );
01980       }
01981    }
01982 
01983    h4->ResetStats(); 
01984    h1->ResetStats(); 
01985 
01986    bool ret = equals("Divide2D1", h1, h4, cmpOptStats );
01987    delete h1;
01988    delete h2;
01989    delete h3;
01990    return ret;
01991 }
01992 
01993 bool testDivide2D2() 
01994 {
01995    // Tests the second Divide method for 2D Histograms
01996 
01997    TH2D* h1 = new TH2D("d2D2-h1", "h1-Title", 
01998                        numberOfBins, minRange, maxRange,
01999                        numberOfBins + 2, minRange, maxRange);
02000    TH2D* h2 = new TH2D("d2D2-h2", "h2-Title", 
02001                        numberOfBins, minRange, maxRange,
02002                        numberOfBins + 2, minRange, maxRange);
02003 
02004    h1->Sumw2();h2->Sumw2();
02005 
02006    UInt_t seed = r.GetSeed();
02007    // For possible problems
02008    r.SetSeed(seed);
02009    for ( Int_t e = 0; e < nEvents*nEvents; ++e ) {
02010       Double_t x,y;
02011       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02012       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02013       h1->Fill(x, y, 1.0);
02014       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02015       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02016       h2->Fill(x, y, 1.0);
02017    }
02018    // avoid bins in h2 with zero content
02019    for (int i = 0; i < h2->GetSize(); ++i) 
02020       if (h2->GetBinContent(i) == 0) h2->SetBinContent(i,1);
02021 
02022    TH2D* h3 = static_cast<TH2D*>( h1->Clone() );
02023    h3->Divide(h2);
02024       
02025    TH2D* h4 = new TH2D("d2D2-h4", "h4=h3*h2)", 
02026                        numberOfBins, minRange, maxRange,
02027                        numberOfBins + 2, minRange, maxRange);
02028    h4->Multiply(h2, h3, 1.0, 1.0);
02029    for ( Int_t i = 0; i <= h4->GetNbinsX() + 1; ++i ) {
02030       for ( Int_t j = 0; j <= h4->GetNbinsY() + 1; ++j ) {
02031           Double_t error = h4->GetBinError(i,j) * h4->GetBinError(i,j);
02032          error -= 2 * h3->GetBinContent(i,j)*h3->GetBinContent(i,j)*h2->GetBinError(i,j)*h2->GetBinError(i,j); 
02033          h4->SetBinError( i, j, sqrt(error) );
02034       }
02035    }
02036 
02037    h4->ResetStats(); 
02038    h1->ResetStats(); 
02039 
02040    bool ret = equals("Divide2D2", h1, h4, cmpOptStats);
02041    delete h1;
02042    delete h2;
02043    delete h3;
02044    return ret;
02045 }
02046 
02047 bool testDivide3D1() 
02048 {
02049    // Tests the first Divide method for 3D Histograms
02050 
02051    Double_t c1 = r.Rndm() + 1;
02052    Double_t c2 = r.Rndm() + 1;
02053 
02054    TH3D* h1 = new TH3D("d3D1-h1", "h1-Title", 
02055                        numberOfBins, minRange, maxRange,
02056                        numberOfBins + 1, minRange, maxRange,
02057                        numberOfBins + 2, minRange, maxRange);
02058    TH3D* h2 = new TH3D("d3D1-h2", "h2-Title", 
02059                        numberOfBins, minRange, maxRange,
02060                        numberOfBins + 1, minRange, maxRange,
02061                        numberOfBins + 2, minRange, maxRange);
02062 
02063    h1->Sumw2();h2->Sumw2();
02064 
02065    UInt_t seed = r.GetSeed();
02066    // For possible problems
02067    r.SetSeed(seed);
02068    for ( Int_t e = 0; e < nEvents*nEvents; ++e ) {
02069       Double_t x,y,z;
02070       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02071       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02072       z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02073       h1->Fill(x, y, z, 1.0);
02074       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02075       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02076       z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02077       h2->Fill(x, y, z, 1.0);
02078    }
02079    // avoid bins in h2 with zero content
02080    for (int i = 0; i < h2->GetSize(); ++i) 
02081       if (h2->GetBinContent(i) == 0) h2->SetBinContent(i,1);
02082 
02083    TH3D* h3 = new TH3D("d3D1-h3", "h3=(c1*h1)/(c2*h2)", 
02084                        numberOfBins, minRange, maxRange,
02085                        numberOfBins + 1, minRange, maxRange,
02086                        numberOfBins + 2, minRange, maxRange);
02087    h3->Divide(h1, h2, c1, c2);
02088       
02089    TH3D* h4 = new TH3D("d3D1-h4", "h4=h3*h2)", 
02090                        numberOfBins, minRange, maxRange,
02091                        numberOfBins + 1, minRange, maxRange,
02092                        numberOfBins + 2, minRange, maxRange);
02093    h4->Multiply(h2, h3, c2/c1, 1.0);
02094    for ( Int_t i = 0; i <= h4->GetNbinsX() + 1; ++i ) {
02095       for ( Int_t j = 0; j <= h4->GetNbinsY() + 1; ++j ) {
02096          for ( Int_t h = 0; h <= h4->GetNbinsZ() + 1; ++h ) {
02097             Double_t error = h4->GetBinError(i,j,h) * h4->GetBinError(i,j,h);
02098             //error -= 2 * h3->GetBinContent(i,j,h)*h3->GetBinContent(i,j,h)*h2->GetBinError(i,j,h)*h2->GetBinError(i,j,h); 
02099             error -= (2*(c2*c2)/(c1*c1)) * 
02100                h3->GetBinContent(i,j,h)*h3->GetBinContent(i,j,h)*h2->GetBinError(i,j,h)*h2->GetBinError(i,j,h); 
02101             h4->SetBinError( i, j, h, sqrt(error) );
02102          }
02103       }
02104    }
02105 
02106    h4->ResetStats(); 
02107    h1->ResetStats(); 
02108 
02109    bool ret = equals("Divide3D1", h1, h4, cmpOptStats);
02110    delete h1;
02111    delete h2;
02112    delete h3;
02113    return ret;
02114 }
02115 
02116 bool testDivide3D2() 
02117 {
02118    // Tests the second Divide method for 3D Histograms
02119 
02120    TH3D* h1 = new TH3D("d3D2-h1", "h1-Title", 
02121                        numberOfBins, minRange, maxRange,
02122                        numberOfBins + 1, minRange, maxRange,
02123                        numberOfBins + 2, minRange, maxRange);
02124    TH3D* h2 = new TH3D("d3D2-h2", "h2-Title", 
02125                        numberOfBins, minRange, maxRange,
02126                        numberOfBins + 1, minRange, maxRange,
02127                        numberOfBins + 2, minRange, maxRange);
02128 
02129    h1->Sumw2();h2->Sumw2();
02130 
02131    UInt_t seed = r.GetSeed();
02132    // For possible problems
02133    r.SetSeed(seed);
02134    for ( Int_t e = 0; e < nEvents*nEvents; ++e ) {
02135       Double_t x,y,z;
02136       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02137       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02138       z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02139       h1->Fill(x, y, z, 1.0);
02140       x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02141       y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02142       z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02143       h2->Fill(x, y, z, 1.0);
02144    }
02145    // avoid bins in h2 with zero content
02146    for (int i = 0; i < h2->GetSize(); ++i) 
02147       if (h2->GetBinContent(i) == 0) h2->SetBinContent(i,1);
02148 
02149    TH3D* h3 = static_cast<TH3D*>( h1->Clone() );
02150    h3->Divide(h2);
02151       
02152    TH3D* h4 = new TH3D("d3D2-h4", "h4=h3*h2)", 
02153                        numberOfBins, minRange, maxRange,
02154                        numberOfBins + 1, minRange, maxRange,
02155                        numberOfBins + 2, minRange, maxRange);
02156    h4->Multiply(h2, h3, 1.0, 1.0);
02157    for ( Int_t i = 0; i <= h4->GetNbinsX() + 1; ++i ) {
02158       for ( Int_t j = 0; j <= h4->GetNbinsY() + 1; ++j ) {
02159          for ( Int_t h = 0; h <= h4->GetNbinsZ() + 1; ++h ) {
02160             Double_t error = h4->GetBinError(i,j,h) * h4->GetBinError(i,j,h);
02161             error -= 2 * h3->GetBinContent(i,j,h)*h3->GetBinContent(i,j,h)*h2->GetBinError(i,j,h)*h2->GetBinError(i,j,h); 
02162             h4->SetBinError( i, j, h, sqrt(error) );
02163          }
02164       }
02165    }
02166 
02167    h4->ResetStats(); 
02168    h1->ResetStats(); 
02169 
02170    bool ret = equals("Divide3D2", h1, h4, cmpOptStats);
02171    delete h1;
02172    delete h2;
02173    delete h3;
02174    return ret;
02175 }
02176 
02177 bool testDivSparse1()
02178 {
02179    // Tests the first Divide method for 3D Histograms
02180 
02181    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
02182                      TMath::Nint( r.Uniform(1, 5) ),
02183                      TMath::Nint( r.Uniform(1, 5) )};
02184    Double_t xmin[] = {minRange, minRange, minRange};
02185    Double_t xmax[] = {maxRange, maxRange, maxRange};
02186 
02187    // There is no multiply with coefficients!
02188    const Double_t c1 = 1; 
02189    const Double_t c2 = 1;
02190 
02191    THnSparseD* s1 = new THnSparseD("dND1-s1", "s1-Title", 3, bsize, xmin, xmax);
02192    THnSparseD* s2 = new THnSparseD("dND1-s2", "s2-Title", 3, bsize, xmin, xmax);
02193    THnSparseD* s4 = new THnSparseD("dND1-s4", "s4=s3*s2)", 3, bsize, xmin, xmax);
02194 
02195    s1->Sumw2();s2->Sumw2();s4->Sumw2();
02196 
02197    UInt_t seed = r.GetSeed();
02198    // For possible problems
02199    r.SetSeed(seed);
02200 
02201    for ( Int_t e = 0; e < nEvents*nEvents; ++e ) {
02202       Double_t points[3];
02203       points[0] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02204       points[1] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02205       points[2] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02206       s1->Fill(points, 1.0);
02207       points[0] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02208       points[1] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02209       points[2] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02210       s2->Fill(points, 1.0);
02211       s4->Fill(points, 1.0);
02212    }
02213 
02214    THnSparseD* s3 = new THnSparseD("dND1-s3", "s3=(c1*s1)/(c2*s2)", 3, bsize, xmin, xmax);
02215    s3->Divide(s1, s2, c1, c2);
02216       
02217    s4->Multiply(s3);
02218 
02219    // No the bin contents has to be reduced, as it was filled twice!
02220    for ( Long64_t i = 0; i < s3->GetNbins(); ++i ) {
02221       Int_t coord[3];
02222       s3->GetBinContent(i, coord);
02223       Double_t s4BinError = s4->GetBinError(coord);
02224       Double_t s2BinError = s2->GetBinError(coord);
02225       Double_t s3BinContent = s3->GetBinContent(coord);
02226       Double_t error = s4BinError * s4BinError;
02227       error -= (2*(c2*c2)/(c1*c1)) * s3BinContent * s3BinContent * s2BinError * s2BinError;
02228       s4->SetBinError(coord, sqrt(error));
02229    }
02230 
02231    bool ret = equals("DivideND1", s1, s4, cmpOptNone, 1E-6);
02232    delete s1;
02233    delete s2;
02234    delete s3;
02235    return ret;
02236 }
02237 
02238 
02239 bool testDivSparse2()
02240 {
02241    // Tests the second Divide method for 3D Histograms
02242 
02243    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
02244                      TMath::Nint( r.Uniform(1, 5) ),
02245                      TMath::Nint( r.Uniform(1, 5) )};
02246    Double_t xmin[] = {minRange, minRange, minRange};
02247    Double_t xmax[] = {maxRange, maxRange, maxRange};
02248 
02249    // There is no multiply with coefficients!
02250    const Double_t c1 = 1; 
02251    const Double_t c2 = 1;
02252 
02253    THnSparseD* s1 = new THnSparseD("dND2-s1", "s1-Title", 3, bsize, xmin, xmax);
02254    THnSparseD* s2 = new THnSparseD("dND2-s2", "s2-Title", 3, bsize, xmin, xmax);
02255    THnSparseD* s4 = new THnSparseD("dND2-s4", "s4=s3*s2)", 3, bsize, xmin, xmax);
02256 
02257    s1->Sumw2();s2->Sumw2();s4->Sumw2();
02258 
02259    UInt_t seed = r.GetSeed();
02260    // For possible problems
02261    r.SetSeed(seed);
02262 
02263    for ( Int_t e = 0; e < nEvents*nEvents; ++e ) {
02264       Double_t points[3];
02265       points[0] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02266       points[1] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02267       points[2] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02268       s1->Fill(points, 1.0);
02269       points[0] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02270       points[1] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02271       points[2] = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02272       s2->Fill(points, 1.0);
02273       s4->Fill(points, 1.0);
02274    }
02275 
02276    THnSparseD* s3 = static_cast<THnSparseD*>( s1->Clone() );
02277    s3->Divide(s2);
02278    
02279    THnSparseD* s5 = new THnSparseD("dND2-s5", "s5=(c1*s1)/(c2*s2)", 3, bsize, xmin, xmax);
02280    s5->Divide(s1,s2);
02281       
02282    s4->Multiply(s3);
02283    
02284    // No the bin contents has to be reduced, as it was filled twice!
02285    for ( Long64_t i = 0; i < s3->GetNbins(); ++i ) {
02286       Int_t coord[3];
02287       s3->GetBinContent(i, coord);
02288       Double_t s4BinError = s4->GetBinError(coord);
02289       Double_t s2BinError = s2->GetBinError(coord);
02290       Double_t s3BinContent = s3->GetBinContent(coord);
02291       Double_t error = s4BinError * s4BinError;
02292       error -= (2*(c2*c2)/(c1*c1)) * s3BinContent * s3BinContent * s2BinError * s2BinError;
02293       s4->SetBinError(coord, sqrt(error));
02294    }
02295 
02296    bool ret = equals("DivideND2", s1, s4, cmpOptNone, 1E-6);
02297    
02298    delete s1;
02299    delete s2;
02300    delete s3;
02301    return ret;
02302 }
02303 
02304 bool testAssign1D()
02305 {
02306    // Tests the operator=() method for 1D Histograms
02307 
02308    TH1D* h1 = new TH1D("=1D-h1", "h1-Title", numberOfBins, minRange, maxRange);
02309 
02310    h1->Sumw2();
02311 
02312    for ( Int_t e = 0; e < nEvents; ++e ) {
02313       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02314       h1->Fill(value, 1.0);
02315    }
02316 
02317    TH1D* h2 = new TH1D("=1D-h2", "h2-Title", numberOfBins, minRange, maxRange);
02318    *h2 = *h1;
02319 
02320    bool ret = equals("Assign Oper Hist '='  1D", h1, h2, cmpOptStats);
02321    delete h1;
02322    return ret;
02323 }
02324 
02325 bool testAssignVar1D()
02326 {
02327    // Tests the operator=() method for 1D Histograms with variable bin size
02328 
02329    Double_t v[numberOfBins+1];
02330    FillVariableRange(v);
02331 
02332    TH1D* h1 = new TH1D("=1D-h1", "h1-Title", numberOfBins, v);
02333 
02334    h1->Sumw2();
02335 
02336    for ( Int_t e = 0; e < nEvents; ++e ) {
02337       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02338       h1->Fill(value, 1.0);
02339    }
02340 
02341    TH1D* h2 = new TH1D("=1D-h2", "h2-Title", numberOfBins, v);
02342    *h2 = *h1;
02343 
02344    bool ret = equals("Assign Oper VarH '='  1D", h1, h2, cmpOptStats);
02345    delete h1;
02346    return ret;
02347 }
02348 
02349 bool testAssignProfile1D()
02350 {
02351    // Tests the operator=() method for 1D Profiles
02352 
02353    TProfile* p1 = new TProfile("=1D-p1", "p1-Title", numberOfBins, minRange, maxRange);
02354 
02355    for ( Int_t e = 0; e < nEvents; ++e ) {
02356       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02357       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02358       p1->Fill(x, y, 1.0);
02359    }
02360 
02361    TProfile* p2 = new TProfile("=1D-p2", "p2-Title", numberOfBins, minRange, maxRange);
02362    *p2 = *p1;
02363 
02364    bool ret = equals("Assign Oper Prof '='  1D", p1, p2, cmpOptStats);
02365    delete p1;
02366    return ret;
02367 }
02368 
02369 bool testAssignProfileVar1D()
02370 {
02371    // Tests the operator=() method for 1D Profiles with variable bin size
02372 
02373    Double_t v[numberOfBins+1];
02374    FillVariableRange(v);
02375 
02376    TProfile* p1 = new TProfile("=1D-p1", "p1-Title", numberOfBins, v);
02377 
02378    for ( Int_t e = 0; e < nEvents; ++e ) {
02379       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02380       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02381       p1->Fill(x, y, 1.0);
02382    }
02383 
02384    TProfile* p2 = new TProfile("=1D-p2", "p2-Title", numberOfBins, v);
02385    *p2 = *p1;
02386 
02387    bool ret = equals("Assign Oper VarP '='  1D", p1, p2, cmpOptStats);
02388    delete p1;
02389    return ret;
02390 }
02391 
02392 bool testCopyConstructor1D()
02393 {
02394    // Tests the copy constructor for 1D Histograms
02395 
02396    TH1D* h1 = new TH1D("cc1D-h1", "h1-Title", numberOfBins, minRange, maxRange);
02397 
02398    h1->Sumw2();
02399 
02400    for ( Int_t e = 0; e < nEvents; ++e ) {
02401       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02402       h1->Fill(value, 1.0);
02403    }
02404 
02405    TH1D* h2 = new TH1D(*h1);
02406 
02407    bool ret = equals("Copy Constructor Hist 1D", h1, h2, cmpOptStats);
02408    delete h1;
02409    return ret;
02410 }
02411 
02412 bool testCopyConstructorVar1D()
02413 {
02414    // Tests the copy constructor for 1D Histograms with variable bin size
02415 
02416    Double_t v[numberOfBins+1];
02417    FillVariableRange(v);
02418    
02419    TH1D* h1 = new TH1D("cc1D-h1", "h1-Title", numberOfBins, v);
02420 
02421    h1->Sumw2();
02422 
02423    for ( Int_t e = 0; e < nEvents; ++e ) {
02424       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02425       h1->Fill(value, 1.0);
02426    }
02427 
02428    TH1D* h2 = new TH1D(*h1);
02429 
02430    bool ret = equals("Copy Constructor VarH 1D", h1, h2, cmpOptStats);
02431    delete h1;
02432    return ret;
02433 }
02434 
02435 bool testCopyConstructorProfile1D()
02436 {
02437    // Tests the copy constructor for 1D Profiles
02438 
02439    TProfile* p1 = new TProfile("cc1D-p1", "p1-Title", numberOfBins, minRange, maxRange);
02440 
02441    for ( Int_t e = 0; e < nEvents; ++e ) {
02442       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02443       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02444       p1->Fill(x, y, 1.0);
02445    }
02446 
02447    TProfile* p2 = new TProfile(*p1);
02448 
02449    bool ret = equals("Copy Constructor Prof 1D", p1, p2, cmpOptStats);
02450    delete p1;
02451    return ret;
02452 }
02453 
02454 bool testCopyConstructorProfileVar1D()
02455 {
02456    // Tests the copy constructor for 1D Profiles with variable bin size
02457 
02458    Double_t v[numberOfBins+1];
02459    FillVariableRange(v);
02460 
02461    TProfile* p1 = new TProfile("cc1D-p1", "p1-Title", numberOfBins, v);
02462 
02463    for ( Int_t e = 0; e < nEvents; ++e ) {
02464       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02465       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02466       p1->Fill(x, y, 1.0);
02467    }
02468 
02469    TProfile* p2 = new TProfile(*p1);
02470 
02471    bool ret = equals("Copy Constructor VarP 1D", p1, p2, cmpOptStats);
02472    delete p1;
02473    return ret;
02474 }
02475 
02476 bool testClone1D()
02477 {
02478    // Tests the clone method for 1D Histograms
02479 
02480    TH1D* h1 = new TH1D("cl1D-h1", "h1-Title", numberOfBins, minRange, maxRange);
02481 
02482    h1->Sumw2();
02483 
02484    for ( Int_t e = 0; e < nEvents; ++e ) {
02485       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02486       h1->Fill(value, 1.0);
02487    }
02488 
02489    TH1D* h2 = static_cast<TH1D*> ( h1->Clone() );
02490 
02491    bool ret = equals("Clone Function Hist   1D", h1, h2, cmpOptStats);
02492    delete h1;
02493    return ret;
02494 }
02495 
02496 bool testCloneVar1D()
02497 {
02498    // Tests the clone method for 1D Histograms with variable bin size
02499 
02500    Double_t v[numberOfBins+1];
02501    FillVariableRange(v);
02502 
02503    TH1D* h1 = new TH1D("cl1D-h1", "h1-Title", numberOfBins, v);
02504 
02505    h1->Sumw2();
02506 
02507    for ( Int_t e = 0; e < nEvents; ++e ) {
02508       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02509       h1->Fill(value, 1.0);
02510    }
02511 
02512    TH1D* h2 = static_cast<TH1D*> ( h1->Clone() );
02513 
02514    bool ret = equals("Clone Function VarH   1D", h1, h2, cmpOptStats);
02515    delete h1;
02516    return ret;
02517 }
02518 
02519 bool testCloneProfile1D()
02520 {
02521    // Tests the clone method for 1D Profiles
02522 
02523    TProfile* p1 = new TProfile("cl1D-p1", "p1-Title", numberOfBins, minRange, maxRange);
02524 
02525    for ( Int_t e = 0; e < nEvents; ++e ) {
02526       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02527       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02528       p1->Fill(x, y, 1.0);
02529    }
02530 
02531    TProfile* p2 = static_cast<TProfile*> ( p1->Clone() );
02532 
02533    bool ret = equals("Clone Function Prof   1D", p1, p2, cmpOptStats);
02534    delete p1;
02535    return ret;
02536 }
02537 
02538 bool testCloneProfileVar1D()
02539 {
02540    // Tests the clone method for 1D Profiles with variable bin size
02541 
02542    Double_t v[numberOfBins+1];
02543    FillVariableRange(v);
02544 
02545    TProfile* p1 = new TProfile("cl1D-p1", "p1-Title", numberOfBins, v);
02546 
02547    for ( Int_t e = 0; e < nEvents; ++e ) {
02548       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02549       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02550       p1->Fill(x, y, 1.0);
02551    }
02552 
02553    TProfile* p2 = static_cast<TProfile*> ( p1->Clone() );
02554 
02555    bool ret = equals("Clone Function VarP   1D", p1, p2, cmpOptStats);
02556    delete p1;
02557    return ret;
02558 }
02559 
02560 bool testAssign2D()
02561 {
02562    // Tests the operator=() method for 2D Histograms
02563 
02564    TH2D* h1 = new TH2D("=2D-h1", "h1-Title", 
02565                        numberOfBins, minRange, maxRange,
02566                        numberOfBins + 2, minRange, maxRange);
02567 
02568    h1->Sumw2();
02569 
02570    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02571       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02572       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02573       h1->Fill(x, y, 1.0);
02574    }
02575    
02576    TH2D* h2 = new TH2D("=2D-h2", "h2-Title", 
02577                        numberOfBins, minRange, maxRange, 
02578                        numberOfBins + 2, minRange, maxRange);
02579    *h2 = *h1;
02580 
02581    bool ret = equals("Assign Oper Hist '='  2D", h1, h2, cmpOptStats);
02582    delete h1;
02583    return ret;
02584 }
02585 
02586 bool testAssignProfile2D()
02587 {
02588    // Tests the operator=() method for 2D Profiles
02589 
02590    TProfile2D* p1 = new TProfile2D("=2D-p1", "p1-Title", 
02591                                    numberOfBins, minRange, maxRange,
02592                                    numberOfBins + 2, minRange, maxRange);
02593 
02594    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02595       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02596       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02597       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02598       p1->Fill(x, y, z, 1.0);
02599    }
02600 
02601    TProfile2D* p2 = new TProfile2D("=2D-p2", "p2-Title", 
02602                                    numberOfBins, minRange, maxRange, 
02603                                    numberOfBins + 2, minRange, maxRange);
02604    *p2 = *p1;
02605 
02606    bool ret = equals("Assign Oper Prof '='  2D", p1, p2, cmpOptStats);
02607    delete p1;
02608    return ret;
02609 }
02610 
02611 
02612 bool testCopyConstructor2D()
02613 {
02614    // Tests the copy constructor for 2D Histograms
02615 
02616    TH2D* h1 = new TH2D("cc2D-h1", "h1-Title", 
02617                        numberOfBins, minRange, maxRange,
02618                        numberOfBins + 2, minRange, maxRange);
02619 
02620    h1->Sumw2();
02621 
02622    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02623       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02624       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02625       h1->Fill(x, y, 1.0);
02626    }
02627 
02628    TH2D* h2 = new TH2D(*h1);
02629 
02630    bool ret = equals("Copy Constructor Hist 2D", h1, h2, cmpOptStats);
02631    delete h1;
02632    return ret;
02633 }
02634 
02635 bool testCopyConstructorProfile2D()
02636 {
02637    // Tests the copy constructor for 2D Profiles
02638 
02639    TProfile2D* p1 = new TProfile2D("cc2D-p1", "p1-Title", 
02640                                    numberOfBins, minRange, maxRange,
02641                                    numberOfBins + 2, minRange, maxRange);
02642 
02643    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02644       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02645       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02646       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02647       p1->Fill(x, y, z, 1.0);
02648    }
02649 
02650    TProfile2D* p2 = new TProfile2D(*p1);
02651 
02652    bool ret = equals("Copy Constructor Prof 2D", p1, p2, cmpOptStats);
02653    delete p1;
02654    return ret;
02655 }
02656 
02657 bool testClone2D()
02658 {
02659    // Tests the clone method for 2D Histograms
02660 
02661    TH2D* h1 = new TH2D("cl2D-h1", "h1-Title", 
02662                        numberOfBins, minRange, maxRange,
02663                        numberOfBins + 2, minRange, maxRange);
02664 
02665    h1->Sumw2();
02666 
02667    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02668       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02669       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02670       h1->Fill(x, y, 1.0);
02671    }
02672 
02673    TH2D* h2 = static_cast<TH2D*> ( h1->Clone() );
02674 
02675    bool ret = equals("Clone Function Hist   2D", h1, h2, cmpOptStats);
02676    delete h1;
02677    return ret;
02678 }
02679 
02680 bool testCloneProfile2D()
02681 {
02682    // Tests the clone method for 2D Profiles
02683 
02684    TProfile2D* p1 = new TProfile2D("cl2D-p1", "p1-Title", 
02685                                    numberOfBins, minRange, maxRange,
02686                                    numberOfBins + 2, minRange, maxRange);
02687 
02688    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02689       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02690       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02691       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02692       p1->Fill(x, y, z, 1.0);
02693    }
02694 
02695    TProfile2D* p2 = static_cast<TProfile2D*> ( p1->Clone() );
02696 
02697    bool ret = equals("Clone Function Prof   2D", p1, p2, cmpOptStats);
02698    delete p1;
02699    return ret;
02700 }
02701 
02702 bool testAssign3D()
02703 {
02704    // Tests the operator=() method for 3D Histograms
02705 
02706    TH3D* h1 = new TH3D("=3D-h1", "h1-Title", 
02707                        numberOfBins, minRange, maxRange,
02708                        numberOfBins + 1, minRange, maxRange,
02709                        numberOfBins + 2, minRange, maxRange);
02710 
02711    h1->Sumw2();
02712 
02713    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02714       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02715       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02716       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02717       h1->Fill(x, y, z, 1.0);
02718    }
02719 
02720    TH3D* h2 = new TH3D("=3D-h2", "h2-Title", 
02721                        numberOfBins, minRange, maxRange, 
02722                        numberOfBins + 1, minRange, maxRange, 
02723                        numberOfBins + 2, minRange, maxRange);
02724    *h2 = *h1;
02725 
02726    bool ret = equals("Assign Oper Hist '='  3D", h1, h2, cmpOptStats);
02727    delete h1;
02728    return ret;
02729 }
02730 
02731 bool testAssignProfile3D()
02732 {
02733    // Tests the operator=() method for 3D Profiles
02734 
02735    TProfile3D* p1 = new TProfile3D("=3D-p1", "p1-Title", 
02736                                    numberOfBins, minRange, maxRange,
02737                                    numberOfBins + 1, minRange, maxRange,
02738                                    numberOfBins + 2, minRange, maxRange);
02739 
02740    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02741       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02742       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02743       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02744       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02745       p1->Fill(x, y, z, t, 1.0);
02746    }
02747 
02748    TProfile3D* p2 = new TProfile3D("=3D-p2", "p2-Title", 
02749                                    numberOfBins, minRange, maxRange, 
02750                                    numberOfBins + 1, minRange, maxRange, 
02751                                    numberOfBins + 2, minRange, maxRange);
02752    *p2 = *p1;
02753 
02754    bool ret = equals("Assign Oper Prof '='  3D", p1, p2);
02755    delete p1;
02756    return ret;
02757 }
02758 
02759 bool testCopyConstructor3D()
02760 {
02761    // Tests the copy constructor for 3D Histograms
02762 
02763    TH3D* h1 = new TH3D("cc3D-h1", "h1-Title", 
02764                        numberOfBins, minRange, maxRange,
02765                        numberOfBins + 1, minRange, maxRange,
02766                        numberOfBins + 2, minRange, maxRange);
02767 
02768    h1->Sumw2();
02769 
02770    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02771       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02772       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02773       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02774       h1->Fill(x, y, z, 1.0);
02775    }
02776 
02777    TH3D* h2 = new TH3D(*h1);
02778 
02779    bool ret = equals("Copy Constructor Hist 3D", h1, h2, cmpOptStats);
02780    delete h1;
02781    return ret;
02782 }
02783 
02784 bool testCopyConstructorProfile3D()
02785 {
02786    // Tests the copy constructor for 3D Profiles
02787 
02788    TProfile3D* p1 = new TProfile3D("cc3D-p1", "p1-Title", 
02789                                    numberOfBins, minRange, maxRange,
02790                                    numberOfBins + 1, minRange, maxRange,
02791                                    numberOfBins + 2, minRange, maxRange);
02792 
02793    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02794       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02795       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02796       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02797       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02798       p1->Fill(x, y, z, t, 1.0);
02799    }
02800 
02801    TProfile3D* p2 = new TProfile3D(*p1);
02802 
02803    bool ret = equals("Copy Constructor Prof 3D", p1, p2/*, cmpOptStats*/);
02804    delete p1;
02805    return ret;
02806 }
02807 
02808 bool testClone3D()
02809 {
02810    // Tests the clone method for 3D Histograms
02811 
02812    TH3D* h1 = new TH3D("cl3D-h1", "h1-Title", 
02813                        numberOfBins, minRange, maxRange,
02814                        numberOfBins + 1, minRange, maxRange,
02815                        numberOfBins + 2, minRange, maxRange);
02816 
02817    h1->Sumw2();
02818 
02819    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02820       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02821       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02822       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02823       h1->Fill(x, y, z, 1.0);
02824    }
02825 
02826    TH3D* h2 = static_cast<TH3D*> ( h1->Clone() );
02827 
02828    bool ret = equals("Clone Function Hist   3D", h1, h2, cmpOptStats);
02829    delete h1;
02830    return ret;
02831 }
02832 
02833 bool testCloneProfile3D()
02834 {
02835    // Tests the clone method for 3D Profiles
02836 
02837    TProfile3D* p1 = new TProfile3D("cl3D-p1", "p1-Title", 
02838                        numberOfBins, minRange, maxRange,
02839                        numberOfBins + 1, minRange, maxRange,
02840                        numberOfBins + 2, minRange, maxRange);
02841 
02842    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
02843       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02844       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02845       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02846       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02847       p1->Fill(x, y, z, t, 1.0);
02848    }
02849 
02850    TProfile3D* p2 = static_cast<TProfile3D*> ( p1->Clone() );
02851 
02852    bool ret = equals("Clone Function Prof   3D", p1, p2);
02853    delete p1;
02854    return ret;
02855 }
02856 
02857 bool testCloneSparse()
02858 {
02859    // Tests the clone method for Sparse histograms
02860 
02861    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
02862                      TMath::Nint( r.Uniform(1, 5) ),
02863                      TMath::Nint( r.Uniform(1, 5) )
02864    };
02865    Double_t xmin[] = {minRange, minRange, minRange};
02866    Double_t xmax[] = {maxRange, maxRange, maxRange};
02867 
02868    THnSparseD* s1 = new THnSparseD("clS-s1","s1-Title", 3, bsize, xmin, xmax);
02869 
02870    for ( Int_t i = 0; i < nEvents * nEvents; ++i ) {
02871       Double_t points[3];
02872       points[0] = r.Uniform( minRange * .9, maxRange * 1.1);
02873       points[1] = r.Uniform( minRange * .9, maxRange * 1.1);
02874       points[2] = r.Uniform( minRange * .9, maxRange * 1.1);
02875       s1->Fill(points);
02876    }
02877 
02878    THnSparseD* s2 = (THnSparseD*) s1->Clone();
02879 
02880    bool ret = equals("Clone Function THnSparse", s1, s2);
02881    delete s1;
02882    return ret;
02883 }
02884 
02885 bool testWriteRead1D()
02886 {
02887    // Tests the write and read methods for 1D Histograms
02888 
02889    TH1D* h1 = new TH1D("wr1D-h1", "h1-Title", numberOfBins, minRange, maxRange);
02890 
02891    h1->Sumw2();
02892 
02893    for ( Int_t e = 0; e < nEvents; ++e ) {
02894       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02895       h1->Fill(value, 1.0);
02896    }
02897 
02898    TFile f("tmpHist.root", "RECREATE");
02899    h1->Write();
02900    f.Close();
02901 
02902    TFile f2("tmpHist.root");
02903    TH1D* h2 = static_cast<TH1D*> ( f2.Get("wr1D-h1") );
02904 
02905    bool ret = equals("Read/Write Hist 1D", h1, h2, cmpOptStats);
02906    delete h1;
02907    return ret;
02908 }
02909 
02910 bool testWriteReadVar1D()
02911 {
02912    // Tests the write and read methods for 1D Histograms with variable bin size
02913 
02914    Double_t v[numberOfBins+1];
02915    FillVariableRange(v);
02916 
02917    TH1D* h1 = new TH1D("wr1D-h1", "h1-Title", numberOfBins, v);
02918 
02919    h1->Sumw2();
02920 
02921    for ( Int_t e = 0; e < nEvents; ++e ) {
02922       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02923       h1->Fill(value, 1.0);
02924    }
02925 
02926    TFile f("tmpHist.root", "RECREATE");
02927    h1->Write();
02928    f.Close();
02929 
02930    TFile f2("tmpHist.root");
02931    TH1D* h2 = static_cast<TH1D*> ( f2.Get("wr1D-h1") );
02932 
02933    bool ret = equals("Read/Write VarH 1D", h1, h2, cmpOptStats);
02934    delete h1;
02935    return ret;
02936 }
02937 
02938 bool testWriteReadProfile1D()
02939 {
02940    // Tests the write and read methods for 1D Profiles
02941 
02942    TProfile* p1 = new TProfile("wr1D-p1", "p1-Title", numberOfBins, minRange, maxRange);
02943 
02944    for ( Int_t e = 0; e < nEvents; ++e ) {
02945       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02946       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02947       p1->Fill(x, y, 1.0);
02948    }
02949 
02950    TFile f("tmpHist.root", "RECREATE");
02951    p1->Write();
02952    f.Close();
02953 
02954    TFile f2("tmpHist.root");
02955    TProfile* p2 = static_cast<TProfile*> ( f2.Get("wr1D-p1") );
02956 
02957    bool ret = equals("Read/Write Prof 1D", p1, p2, cmpOptStats);
02958    delete p1;
02959    return ret;
02960 }
02961 
02962 bool testWriteReadProfileVar1D()
02963 {
02964    // Tests the write and read methods for 1D Profiles with variable bin size
02965 
02966    Double_t v[numberOfBins+1];
02967    FillVariableRange(v);
02968 
02969    TProfile* p1 = new TProfile("wr1D-p1", "p1-Title", numberOfBins, v);
02970 
02971    for ( Int_t e = 0; e < nEvents; ++e ) {
02972       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02973       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
02974       p1->Fill(x, y, 1.0);
02975    }
02976 
02977    TFile f("tmpHist.root", "RECREATE");
02978    p1->Write();
02979    f.Close();
02980 
02981    TFile f2("tmpHist.root");
02982    TProfile* p2 = static_cast<TProfile*> ( f2.Get("wr1D-p1") );
02983 
02984    bool ret = equals("Read/Write VarP 1D", p1, p2, cmpOptStats);
02985    delete p1;
02986    return ret;
02987 }
02988 
02989 bool testWriteRead2D()
02990 {
02991    // Tests the write and read methods for 2D Histograms
02992 
02993    TH2D* h1 = new TH2D("wr2D-h1", "h1-Title", 
02994                        numberOfBins, minRange, maxRange,
02995                        numberOfBins + 2, minRange, maxRange);
02996 
02997    h1->Sumw2();
02998 
02999    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03000       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03001       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03002       h1->Fill(x, y, 1.0);
03003    }
03004 
03005    TFile f("tmpHist.root", "RECREATE");
03006    h1->Write();
03007    f.Close();
03008 
03009    TFile f2("tmpHist.root");
03010    TH2D* h2 = static_cast<TH2D*> ( f2.Get("wr2D-h1") );
03011 
03012    bool ret = equals("Read/Write Hist 2D", h1, h2, cmpOptStats);
03013    delete h1;
03014    return ret;
03015 }
03016 
03017 bool testWriteReadProfile2D()
03018 {
03019    // Tests the write and read methods for 2D Profiles
03020 
03021    TProfile2D* p1 = new TProfile2D("wr2D-p1", "p1-Title", 
03022                                    numberOfBins, minRange, maxRange,
03023                                    numberOfBins + 2, minRange, maxRange);
03024 
03025    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03026       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03027       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03028       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03029       p1->Fill(x, y, z, 1.0);
03030    }
03031 
03032    TFile f("tmpHist.root", "RECREATE");
03033    p1->Write();
03034    f.Close();
03035 
03036    TFile f2("tmpHist.root");
03037    TProfile2D* p2 = static_cast<TProfile2D*> ( f2.Get("wr2D-p1") );
03038 
03039    bool ret = equals("Read/Write Prof 2D", p1, p2, cmpOptStats);
03040    delete p1;
03041    return ret;
03042 }
03043 
03044 bool testWriteRead3D()
03045 {
03046    // Tests the write and read methods for 3D Histograms
03047 
03048    TH3D* h1 = new TH3D("wr3D-h1", "h1-Title", 
03049                        numberOfBins, minRange, maxRange,
03050                        numberOfBins + 1, minRange, maxRange,
03051                        numberOfBins + 2, minRange, maxRange);
03052 
03053    h1->Sumw2();
03054 
03055    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03056       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03057       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03058       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03059       h1->Fill(x, y, z, 1.0);
03060    }
03061 
03062    TFile f("tmpHist.root", "RECREATE");
03063    h1->Write();
03064    f.Close();
03065 
03066    TFile f2("tmpHist.root");
03067    TH3D* h2 = static_cast<TH3D*> ( f2.Get("wr3D-h1") );
03068 
03069    bool ret = equals("Read/Write Hist 3D", h1, h2, cmpOptStats);
03070    delete h1;
03071    return ret;
03072 }
03073 
03074 bool testWriteReadProfile3D()
03075 {
03076    // Tests the write and read methods for 3D Profile
03077 
03078    TProfile3D* p1 = new TProfile3D("wr3D-p1", "p1-Title", 
03079                                  numberOfBins, minRange, maxRange,
03080                                  numberOfBins + 1, minRange, maxRange,
03081                                  numberOfBins + 2, minRange, maxRange);
03082 
03083    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03084       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03085       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03086       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03087       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03088       p1->Fill(x, y, z, t, 1.0);
03089    }
03090 
03091    TFile f("tmpHist.root", "RECREATE");
03092    p1->Write();
03093    f.Close();
03094 
03095    TFile f2("tmpHist.root");
03096    TProfile3D* p2 = static_cast<TProfile3D*> ( f2.Get("wr3D-p1") );
03097 
03098    // In this particular case the statistics are not checked. The
03099    // Chi2Test is not properly implemented for the TProfile3D
03100    // class. If the cmpOptStats flag is set, then there will be a
03101    // crash.
03102    bool ret = equals("Read/Write Prof 3D", p1, p2);
03103    delete p1;
03104    return ret;
03105 }
03106 
03107 bool testWriteReadSparse()
03108 {
03109    // Tests the write and read methods for Sparse Histograms
03110 
03111    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
03112                      TMath::Nint( r.Uniform(1, 5) ),
03113                      TMath::Nint( r.Uniform(1, 5) )
03114    };
03115    Double_t xmin[] = {minRange, minRange, minRange};
03116    Double_t xmax[] = {maxRange, maxRange, maxRange};
03117    
03118    THnSparseD* s1 = new THnSparseD("wrS-s1","s1-Title", 3, bsize, xmin, xmax);
03119    s1->Sumw2();
03120 
03121    for ( Int_t i = 0; i < nEvents * nEvents; ++i ) {
03122       Double_t points[3];
03123       points[0] = r.Uniform( minRange * .9, maxRange * 1.1);
03124       points[1] = r.Uniform( minRange * .9, maxRange * 1.1);
03125       points[2] = r.Uniform( minRange * .9, maxRange * 1.1);
03126       s1->Fill(points);
03127    }
03128 
03129    TFile f("tmpHist.root", "RECREATE");
03130    s1->Write();
03131    f.Close();
03132 
03133    TFile f2("tmpHist.root");
03134    THnSparseD* s2 = static_cast<THnSparseD*> ( f2.Get("wrS-s1") );
03135 
03136    bool ret = equals("Read/Write Hist 3D", s1, s2, cmpOptNone);
03137    delete s1;
03138    return ret;
03139 }
03140 
03141 
03142 bool testMerge1D() 
03143 {
03144    // Tests the merge method for 1D Histograms
03145 
03146    TH1D* h1 = new TH1D("merge1D-h1", "h1-Title", numberOfBins, minRange, maxRange);
03147    TH1D* h2 = new TH1D("merge1D-h2", "h2-Title", numberOfBins, minRange, maxRange);
03148    TH1D* h3 = new TH1D("merge1D-h3", "h3-Title", numberOfBins, minRange, maxRange);
03149    TH1D* h4 = new TH1D("merge1D-h4", "h4-Title", numberOfBins, minRange, maxRange);
03150 
03151    h1->Sumw2();h2->Sumw2();h3->Sumw2();
03152 
03153    FillHistograms(h1, h4);
03154    FillHistograms(h2, h4);
03155    FillHistograms(h3, h4);
03156 
03157    TList *list = new TList;
03158    list->Add(h2);
03159    list->Add(h3);
03160 
03161    h1->Merge(list);
03162 
03163    bool ret = equals("Merge1D", h1, h4, cmpOptStats, 1E-10);
03164    delete h1;
03165    delete h2;
03166    delete h3;
03167    return ret;
03168 }
03169 
03170 bool testMergeVar1D() 
03171 {
03172    // Tests the merge method for 1D Histograms with variable bin size
03173 
03174    Double_t v[numberOfBins+1];
03175    FillVariableRange(v);
03176 
03177    TH1D* h1 = new TH1D("merge1D-h1", "h1-Title", numberOfBins, v);
03178    TH1D* h2 = new TH1D("merge1D-h2", "h2-Title", numberOfBins, v);
03179    TH1D* h3 = new TH1D("merge1D-h3", "h3-Title", numberOfBins, v);
03180    TH1D* h4 = new TH1D("merge1D-h4", "h4-Title", numberOfBins, v);
03181 
03182    h1->Sumw2();h2->Sumw2();h3->Sumw2();
03183 
03184    FillHistograms(h1, h4);
03185    FillHistograms(h2, h4);
03186    FillHistograms(h3, h4);
03187 
03188    TList *list = new TList;
03189    list->Add(h2);
03190    list->Add(h3);
03191 
03192    h1->Merge(list);
03193 
03194    bool ret = equals("MergeVar1D", h1, h4, cmpOptStats, 1E-10);
03195    delete h1;
03196    delete h2;
03197    delete h3;
03198    return ret;
03199 }
03200 
03201 bool testMergeProf1D() 
03202 {
03203    // Tests the merge method for 1D Profiles
03204 
03205    TProfile* p1 = new TProfile("merge1D-p1", "p1-Title", numberOfBins, minRange, maxRange);
03206    TProfile* p2 = new TProfile("merge1D-p2", "p2-Title", numberOfBins, minRange, maxRange);
03207    TProfile* p3 = new TProfile("merge1D-p3", "p3-Title", numberOfBins, minRange, maxRange);
03208    TProfile* p4 = new TProfile("merge1D-p4", "p4-Title", numberOfBins, minRange, maxRange);
03209 
03210    FillProfiles(p1, p4);
03211    FillProfiles(p2, p4);
03212    FillProfiles(p3, p4);
03213 
03214    TList *list = new TList;
03215    list->Add(p2);
03216    list->Add(p3);
03217 
03218    p1->Merge(list);
03219 
03220    bool ret = equals("Merge1DProf", p1, p4, cmpOptStats, 1E-10);
03221    delete p1;
03222    delete p2;
03223    delete p3;
03224    return ret;
03225 }
03226 
03227 bool testMergeProfVar1D() 
03228 {
03229    // Tests the merge method for 1D Profiles with variable bin size
03230 
03231    Double_t v[numberOfBins+1];
03232    FillVariableRange(v);
03233 
03234    TProfile* p1 = new TProfile("merge1D-p1", "p1-Title", numberOfBins, v);
03235    TProfile* p2 = new TProfile("merge1D-p2", "p2-Title", numberOfBins, v);
03236    TProfile* p3 = new TProfile("merge1D-p3", "p3-Title", numberOfBins, v);
03237    TProfile* p4 = new TProfile("merge1D-p4", "p4-Title", numberOfBins, v);
03238 
03239    FillProfiles(p1, p4);
03240    FillProfiles(p2, p4);
03241    FillProfiles(p3, p4);
03242 
03243    TList *list = new TList;
03244    list->Add(p2);
03245    list->Add(p3);
03246 
03247    p1->Merge(list);
03248 
03249    bool ret = equals("Merge1DVarP", p1, p4, cmpOptStats, 1E-10);
03250    delete p1;
03251    delete p2;
03252    delete p3;
03253    return ret;
03254 }
03255 
03256 bool testMerge2D() 
03257 {
03258    // Tests the merge method for 2D Histograms
03259 
03260    TH2D* h1 = new TH2D("merge2D-h1", "h1-Title",
03261                        numberOfBins, minRange, maxRange,
03262                        numberOfBins + 2, minRange, maxRange);
03263    TH2D* h2 = new TH2D("merge2D-h2", "h2-Title",
03264                        numberOfBins, minRange, maxRange,
03265                        numberOfBins + 2, minRange, maxRange);
03266    TH2D* h3 = new TH2D("merge2D-h3", "h3-Title",
03267                        numberOfBins, minRange, maxRange,
03268                        numberOfBins + 2, minRange, maxRange);
03269    TH2D* h4 = new TH2D("merge2D-h4", "h4-Title",
03270                        numberOfBins, minRange, maxRange,
03271                        numberOfBins + 2, minRange, maxRange);
03272 
03273    h1->Sumw2();h2->Sumw2();h3->Sumw2();
03274 
03275    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03276       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03277       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03278       h1->Fill(x, y, 1.0);
03279       h4->Fill(x, y, 1.0);
03280    }
03281 
03282    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03283       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03284       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03285       h2->Fill(x, y, 1.0);
03286       h4->Fill(x, y, 1.0);
03287    }
03288 
03289    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03290       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03291       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03292       h3->Fill(x, y, 1.0);
03293       h4->Fill(x, y, 1.0);
03294    }
03295 
03296    TList *list = new TList;
03297    list->Add(h2);
03298    list->Add(h3);
03299 
03300    h1->Merge(list);
03301 
03302    bool ret = equals("Merge2D", h1, h4, cmpOptStats, 1E-10);
03303    delete h1;
03304    delete h2;
03305    delete h3;
03306    return ret;
03307 }
03308 
03309 bool testMergeProf2D() 
03310 {
03311    // Tests the merge method for 2D Profiles
03312 
03313    TProfile2D* p1 = new TProfile2D("merge2D-p1", "p1-Title",
03314                                    numberOfBins, minRange, maxRange,
03315                                    numberOfBins + 2, minRange, maxRange);
03316    TProfile2D* p2 = new TProfile2D("merge2D-p2", "p2-Title",
03317                                    numberOfBins, minRange, maxRange,
03318                                    numberOfBins + 2, minRange, maxRange);
03319    TProfile2D* p3 = new TProfile2D("merge2D-p3", "p3-Title",
03320                                    numberOfBins, minRange, maxRange,
03321                                    numberOfBins + 2, minRange, maxRange);
03322    TProfile2D* p4 = new TProfile2D("merge2D-p4", "p4-Title",
03323                                    numberOfBins, minRange, maxRange,
03324                                    numberOfBins + 2, minRange, maxRange);
03325 
03326    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03327       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03328       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03329       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03330       p1->Fill(x, y, z, 1.0);
03331       p4->Fill(x, y, z, 1.0);
03332    }
03333 
03334    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03335       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03336       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03337       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03338       p2->Fill(x, y, z, 1.0);
03339       p4->Fill(x, y, z, 1.0);
03340    }
03341 
03342    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03343       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03344       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03345       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03346       p3->Fill(x, y, z, 1.0);
03347       p4->Fill(x, y, z, 1.0);
03348    }
03349 
03350    TList *list = new TList;
03351    list->Add(p2);
03352    list->Add(p3);
03353 
03354    p1->Merge(list);
03355 
03356    bool ret = equals("Merge2DProf", p1, p4, cmpOptStats, 1E-10);
03357    delete p1;
03358    delete p2;
03359    delete p3;
03360    return ret;
03361 }
03362 
03363 bool testMerge3D() 
03364 {
03365    // Tests the merge method for 3D Histograms
03366 
03367    TH3D* h1 = new TH3D("merge3D-h1", "h1-Title",
03368                        numberOfBins, minRange, maxRange,
03369                        numberOfBins + 1, minRange, maxRange,
03370                        numberOfBins + 2, minRange, maxRange);
03371    TH3D* h2 = new TH3D("merge3D-h2", "h2-Title",
03372                        numberOfBins, minRange, maxRange,
03373                        numberOfBins + 1, minRange, maxRange,
03374                        numberOfBins + 2, minRange, maxRange);
03375    TH3D* h3 = new TH3D("merge3D-h3", "h3-Title",
03376                        numberOfBins, minRange, maxRange,
03377                        numberOfBins + 1, minRange, maxRange,
03378                        numberOfBins + 2, minRange, maxRange);
03379    TH3D* h4 = new TH3D("merge3D-h4", "h4-Title",
03380                        numberOfBins, minRange, maxRange,
03381                        numberOfBins + 1, minRange, maxRange,
03382                        numberOfBins + 2, minRange, maxRange);
03383 
03384    h1->Sumw2();h2->Sumw2();h3->Sumw2();
03385 
03386    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03387       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03388       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03389       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03390       h1->Fill(x, y, z, 1.0);
03391       h4->Fill(x, y, z, 1.0);
03392    }
03393 
03394    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03395       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03396       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03397       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03398       h2->Fill(x, y, z, 1.0);
03399       h4->Fill(x, y, z, 1.0);
03400    }
03401 
03402    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03403       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03404       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03405       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03406       h3->Fill(x, y, z, 1.0);
03407       h4->Fill(x, y, z, 1.0);
03408    }
03409 
03410    TList *list = new TList;
03411    list->Add(h2);
03412    list->Add(h3);
03413 
03414    h1->Merge(list);
03415 
03416    bool ret = equals("Merge3D", h1, h4, cmpOptStats, 1E-10);
03417    delete h1;
03418    delete h2;
03419    delete h3;
03420    return ret;
03421 }
03422 
03423 bool testMergeProf3D() 
03424 {
03425    // Tests the merge method for 3D Profiles
03426 
03427    TProfile3D* p1 = new TProfile3D("merge3D-p1", "p1-Title",
03428                                    numberOfBins, minRange, maxRange,
03429                                    numberOfBins + 1, minRange, maxRange,
03430                                    numberOfBins + 2, minRange, maxRange);
03431    TProfile3D* p2 = new TProfile3D("merge3D-p2", "p2-Title",
03432                                    numberOfBins, minRange, maxRange,
03433                                    numberOfBins + 1, minRange, maxRange,
03434                                    numberOfBins + 2, minRange, maxRange);
03435    TProfile3D* p3 = new TProfile3D("merge3D-p3", "p3-Title",
03436                                    numberOfBins, minRange, maxRange,
03437                                    numberOfBins + 1, minRange, maxRange,
03438                                    numberOfBins + 2, minRange, maxRange);
03439    TProfile3D* p4 = new TProfile3D("merge3D-p4", "p4-Title",
03440                                    numberOfBins, minRange, maxRange,
03441                                    numberOfBins + 1, minRange, maxRange,
03442                                    numberOfBins + 2, minRange, maxRange);
03443 
03444    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03445       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03446       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03447       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03448       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03449       p1->Fill(x, y, z, t, 1.0);
03450       p4->Fill(x, y, z, t, 1.0);
03451    }
03452 
03453    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03454       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03455       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03456       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03457       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03458       p2->Fill(x, y, z, t, 1.0);
03459       p4->Fill(x, y, z, t, 1.0);
03460    }
03461 
03462    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03463       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03464       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03465       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03466       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03467       p3->Fill(x, y, z, t, 1.0);
03468       p4->Fill(x, y, z, t, 1.0);
03469    }
03470 
03471    TList *list = new TList;
03472    list->Add(p2);
03473    list->Add(p3);
03474 
03475    p1->Merge(list);
03476 
03477    bool ret = equals("Merge3DProf", p1, p4, cmpOptStats, 1E-10);
03478    delete p1;
03479    delete p2;
03480    delete p3;
03481    return ret;
03482 }
03483 
03484 bool testMergeSparse() 
03485 {
03486    // Tests the merge method for Sparse Histograms
03487 
03488    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
03489                      TMath::Nint( r.Uniform(1, 5) ),
03490                      TMath::Nint( r.Uniform(1, 5) )
03491    };
03492    Double_t xmin[] = {minRange, minRange, minRange};
03493    Double_t xmax[] = {maxRange, maxRange, maxRange};
03494 
03495    THnSparseD* s1 = new THnSparseD("mergeS-s1", "s1-Title", 3, bsize, xmin, xmax);
03496    THnSparseD* s2 = new THnSparseD("mergeS-s2", "s2-Title", 3, bsize, xmin, xmax);
03497    THnSparseD* s3 = new THnSparseD("mergeS-s3", "s3-Title", 3, bsize, xmin, xmax);
03498    THnSparseD* s4 = new THnSparseD("mergeS-s4", "s4-Title", 3, bsize, xmin, xmax);
03499 
03500    s1->Sumw2();s2->Sumw2();s3->Sumw2();
03501 
03502    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03503       Double_t points[3];
03504       points[0] = r.Uniform( minRange * .9, maxRange * 1.1);
03505       points[1] = r.Uniform( minRange * .9, maxRange * 1.1);
03506       points[2] = r.Uniform( minRange * .9, maxRange * 1.1);
03507       s1->Fill(points, 1.0);
03508       s4->Fill(points, 1.0);
03509    }
03510 
03511    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03512       Double_t points[3];
03513       points[0] = r.Uniform( minRange * .9, maxRange * 1.1);
03514       points[1] = r.Uniform( minRange * .9, maxRange * 1.1);
03515       points[2] = r.Uniform( minRange * .9, maxRange * 1.1);
03516       s2->Fill(points, 1.0);
03517       s4->Fill(points, 1.0);
03518    }
03519 
03520    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03521       Double_t points[3];
03522       points[0] = r.Uniform( minRange * .9, maxRange * 1.1);
03523       points[1] = r.Uniform( minRange * .9, maxRange * 1.1);
03524       points[2] = r.Uniform( minRange * .9, maxRange * 1.1);
03525       s3->Fill(points, 1.0);
03526       s4->Fill(points, 1.0);
03527    }
03528 
03529    TList *list = new TList;
03530    list->Add(s2);
03531    list->Add(s3);
03532 
03533    s1->Merge(list);
03534 
03535    bool ret = equals("MergeSparse", s1, s4, cmpOptNone, 1E-10);
03536    delete s1;
03537    delete s2;
03538    delete s3;
03539    return ret;
03540 }
03541 
03542 bool testMerge1DLabelSame()
03543 {
03544    // Tests the merge with some equal labels method for 1D Histograms
03545 
03546    TH1D* h1 = new TH1D("merge1DLabelSame-h1", "h1-Title", numberOfBins, minRange, maxRange);
03547    TH1D* h2 = new TH1D("merge1DLabelSame-h2", "h2-Title", numberOfBins, minRange, maxRange);
03548    TH1D* h3 = new TH1D("merge1DLabelSame-h3", "h3-Title", numberOfBins, minRange, maxRange);
03549    TH1D* h4 = new TH1D("merge1DLabelSame-h4", "h4-Title", numberOfBins, minRange, maxRange);
03550 
03551    h1->GetXaxis()->SetBinLabel(4, "alpha");
03552    h2->GetXaxis()->SetBinLabel(4, "alpha");
03553    h3->GetXaxis()->SetBinLabel(4, "alpha");
03554    h4->GetXaxis()->SetBinLabel(4, "alpha");
03555 
03556    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03557       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03558       h1->Fill(x, 1.0);
03559       h4->Fill(x, 1.0);
03560    }
03561 
03562    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03563       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03564       h2->Fill(x, 1.0);
03565       h4->Fill(x, 1.0);
03566    }
03567 
03568    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03569       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03570       h3->Fill(x, 1.0);
03571       h4->Fill(x, 1.0);
03572    }
03573 
03574    TList *list = new TList;
03575    list->Add(h2);
03576    list->Add(h3);
03577 
03578    h1->Merge(list);
03579 
03580    bool ret = equals("MergeLabelSame1D", h1, h4, cmpOptStats, 1E-10);
03581    delete h1;
03582    delete h2;
03583    delete h3;
03584    return ret;
03585 }
03586 
03587 bool testMerge2DLabelSame()
03588 {
03589    // Tests the merge with some equal labels method for 2D Histograms
03590 
03591    TH2D* h1 = new TH2D("merge2DLabelSame-h1", "h1-Title", 
03592                        numberOfBins, minRange, maxRange,
03593                        numberOfBins + 2, minRange, maxRange);
03594    TH2D* h2 = new TH2D("merge2DLabelSame-h2", "h2-Title",
03595                        numberOfBins, minRange, maxRange,
03596                        numberOfBins + 2, minRange, maxRange);
03597    TH2D* h3 = new TH2D("merge2DLabelSame-h3", "h3-Title", 
03598                        numberOfBins, minRange, maxRange,
03599                        numberOfBins + 2, minRange, maxRange);
03600    TH2D* h4 = new TH2D("merge2DLabelSame-h4", "h4-Title", 
03601                        numberOfBins, minRange, maxRange,
03602                        numberOfBins + 2, minRange, maxRange);
03603 
03604    h1->GetXaxis()->SetBinLabel(4, "alpha");
03605    h2->GetXaxis()->SetBinLabel(4, "alpha");
03606    h3->GetXaxis()->SetBinLabel(4, "alpha");
03607    h4->GetXaxis()->SetBinLabel(4, "alpha");
03608 
03609    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03610       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03611       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03612       h1->Fill(x, y, 1.0);
03613       h4->Fill(x, y, 1.0);
03614    }
03615 
03616    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03617       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03618       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03619       h2->Fill(x, y, 1.0);
03620       h4->Fill(x, y, 1.0);
03621    }
03622 
03623    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03624       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03625       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03626       h3->Fill(x, y, 1.0);
03627       h4->Fill(x, y, 1.0);
03628    }
03629 
03630    TList *list = new TList;
03631    list->Add(h2);
03632    list->Add(h3);
03633 
03634    h1->Merge(list);
03635 
03636    bool ret = equals("MergeLabelSame2D", h1, h4, cmpOptStats, 1E-10);
03637    delete h1;
03638    delete h2;
03639    delete h3;
03640    return ret;
03641 }
03642 
03643 bool testMerge3DLabelSame()
03644 {
03645    // Tests the merge with some equal labels method for 3D Histograms
03646 
03647    TH3D* h1 = new TH3D("merge3DLabelSame-h1", "h1-Title", 
03648                        numberOfBins, minRange, maxRange,
03649                        numberOfBins + 1, minRange, maxRange,
03650                        numberOfBins + 2, minRange, maxRange);
03651    TH3D* h2 = new TH3D("merge3DLabelSame-h2", "h2-Title",
03652                        numberOfBins, minRange, maxRange,
03653                        numberOfBins + 1, minRange, maxRange,
03654                        numberOfBins + 2, minRange, maxRange);
03655    TH3D* h3 = new TH3D("merge3DLabelSame-h3", "h3-Title", 
03656                        numberOfBins, minRange, maxRange,
03657                        numberOfBins + 1, minRange, maxRange,
03658                        numberOfBins + 2, minRange, maxRange);
03659    TH3D* h4 = new TH3D("merge3DLabelSame-h4", "h4-Title", 
03660                        numberOfBins, minRange, maxRange,
03661                        numberOfBins + 1, minRange, maxRange,
03662                        numberOfBins + 2, minRange, maxRange);
03663 
03664    h1->GetXaxis()->SetBinLabel(4, "alpha");
03665    h2->GetXaxis()->SetBinLabel(4, "alpha");
03666    h3->GetXaxis()->SetBinLabel(4, "alpha");
03667    h4->GetXaxis()->SetBinLabel(4, "alpha");
03668 
03669    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03670       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03671       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03672       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03673       h1->Fill(x, y, z, 1.0);
03674       h4->Fill(x, y, z, 1.0);
03675    }
03676 
03677    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03678       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03679       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03680       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03681       h2->Fill(x, y, z, 1.0);
03682       h4->Fill(x, y, z, 1.0);
03683    }
03684 
03685    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03686       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03687       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03688       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03689       h3->Fill(x, y, z, 1.0);
03690       h4->Fill(x, y, z, 1.0);
03691    }
03692 
03693    TList *list = new TList;
03694    list->Add(h2);
03695    list->Add(h3);
03696 
03697    h1->Merge(list);
03698 
03699    bool ret = equals("MergeLabelSame3D", h1, h4, cmpOptStats, 1E-10);
03700    delete h1;
03701    delete h2;
03702    delete h3;
03703    return ret;
03704 }
03705 
03706 bool testMergeProf1DLabelSame()
03707 {
03708    // Tests the merge with some equal labels method for 1D Profiles
03709 
03710    TProfile* p1 = new TProfile("merge1DLabelSame-p1", "p1-Title", numberOfBins, minRange, maxRange);
03711    TProfile* p2 = new TProfile("merge1DLabelSame-p2", "p2-Title", numberOfBins, minRange, maxRange);
03712    TProfile* p3 = new TProfile("merge1DLabelSame-p3", "p3-Title", numberOfBins, minRange, maxRange);
03713    TProfile* p4 = new TProfile("merge1DLabelSame-p4", "p4-Title", numberOfBins, minRange, maxRange);
03714 
03715    // It does not work properly! Look, the bins with the same labels
03716    // are different ones and still the tests passes! This is not
03717    // consistent with TH1::Merge()
03718    p1->GetXaxis()->SetBinLabel(4, "alpha");
03719    p2->GetXaxis()->SetBinLabel(6, "alpha");
03720    p3->GetXaxis()->SetBinLabel(8, "alpha");
03721    p4->GetXaxis()->SetBinLabel(4, "alpha");
03722 
03723    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03724       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03725       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03726       p1->Fill(x, y, 1.0);
03727       p4->Fill(x, y, 1.0);
03728    }
03729 
03730    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03731       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03732       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03733       p2->Fill(x, y, 1.0);
03734       p4->Fill(x, y, 1.0);
03735    }
03736 
03737    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03738       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03739       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03740       p3->Fill(x, y, 1.0);
03741       p4->Fill(x, y, 1.0);
03742    }
03743 
03744    TList *list = new TList;
03745    list->Add(p2);
03746    list->Add(p3);
03747    
03748    p1->Merge(list);
03749 
03750    bool ret = equals("MergeLabelSame1DProf", p1, p4, cmpOptStats, 1E-10);
03751    delete p1;
03752    delete p2;
03753    delete p3;
03754    return ret;
03755 }
03756 
03757 bool testMergeProf2DLabelSame()
03758 {
03759    // Tests the merge with some equal labels method for 2D Profiles
03760 
03761    TProfile2D* p1 = new TProfile2D("merge2DLabelSame-p1", "p1-Title",
03762                                    numberOfBins, minRange, maxRange, 
03763                                    numberOfBins + 2, minRange, maxRange);
03764    TProfile2D* p2 = new TProfile2D("merge2DLabelSame-p2", "p2-Title",
03765                                    numberOfBins, minRange, maxRange,
03766                                    numberOfBins + 2, minRange, maxRange);
03767    TProfile2D* p3 = new TProfile2D("merge2DLabelSame-p3", "p3-Title", 
03768                                    numberOfBins, minRange, maxRange,
03769                                    numberOfBins + 2, minRange, maxRange);
03770    TProfile2D* p4 = new TProfile2D("merge2DLabelSame-p4", "p4-Title",
03771                                    numberOfBins, minRange, maxRange, 
03772                                    numberOfBins + 2, minRange, maxRange);
03773 
03774    // It does not work properly! Look, the bins with the same labels
03775    // are different ones and still the tests passes! This is not
03776    // consistent with TH1::Merge()
03777    p1->GetXaxis()->SetBinLabel(4, "alpha");
03778    p2->GetXaxis()->SetBinLabel(6, "alpha");
03779    p3->GetXaxis()->SetBinLabel(8, "alpha");
03780    p4->GetXaxis()->SetBinLabel(4, "alpha");
03781 
03782    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03783       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03784       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03785       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03786       p1->Fill(x, y, z, 1.0);
03787       p4->Fill(x, y, z, 1.0);
03788    }
03789 
03790    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03791       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03792       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03793       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03794       p2->Fill(x, y, z, 1.0);
03795       p4->Fill(x, y, z, 1.0);
03796    }
03797 
03798    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03799       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03800       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03801       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03802       p3->Fill(x, y, z, 1.0);
03803       p4->Fill(x, y, z, 1.0);
03804    }
03805 
03806    TList *list = new TList;
03807    list->Add(p2);
03808    list->Add(p3);
03809    
03810    p1->Merge(list);
03811 
03812    bool ret = equals("MergeLabelSame2DProf", p1, p4, cmpOptStats, 1E-10);
03813    delete p1;
03814    delete p2;
03815    delete p3;
03816    return ret;
03817 }
03818 
03819 bool testMergeProf3DLabelSame()
03820 {
03821    // Tests the merge with some equal labels method for 3D Profiles
03822 
03823    TProfile3D* p1 = new TProfile3D("merge3DLabelSame-p1", "p1-Title",
03824                                    numberOfBins, minRange, maxRange, 
03825                                    numberOfBins + 1, minRange, maxRange, 
03826                                    numberOfBins + 2, minRange, maxRange);
03827    TProfile3D* p2 = new TProfile3D("merge3DLabelSame-p2", "p2-Title",
03828                                    numberOfBins, minRange, maxRange,
03829                                    numberOfBins + 1, minRange, maxRange, 
03830                                    numberOfBins + 2, minRange, maxRange);
03831    TProfile3D* p3 = new TProfile3D("merge3DLabelSame-p3", "p3-Title", 
03832                                    numberOfBins, minRange, maxRange,
03833                                    numberOfBins + 1, minRange, maxRange, 
03834                                    numberOfBins + 2, minRange, maxRange);
03835    TProfile3D* p4 = new TProfile3D("merge3DLabelSame-p4", "p4-Title",
03836                                    numberOfBins, minRange, maxRange, 
03837                                    numberOfBins + 1, minRange, maxRange, 
03838                                    numberOfBins + 2, minRange, maxRange);
03839 
03840    // It does not work properly! Look, the bins with the same labels
03841    // are different ones and still the tests passes! This is not
03842    // consistent with TH1::Merge()
03843    p1->GetXaxis()->SetBinLabel(4, "alpha");
03844    p2->GetXaxis()->SetBinLabel(6, "alpha");
03845    p3->GetXaxis()->SetBinLabel(8, "alpha");
03846    p4->GetXaxis()->SetBinLabel(4, "alpha");
03847 
03848    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03849       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03850       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03851       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03852       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03853       p1->Fill(x, y, z, t, 1.0);
03854       p4->Fill(x, y, z, t, 1.0);
03855    }
03856 
03857    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03858       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03859       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03860       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03861       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03862       p2->Fill(x, y, z, t, 1.0);
03863       p4->Fill(x, y, z, t, 1.0);
03864    }
03865 
03866    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03867       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03868       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03869       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03870       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03871       p3->Fill(x, y, z, t, 1.0);
03872       p4->Fill(x, y, z, t, 1.0);
03873    }
03874 
03875    TList *list = new TList;
03876    list->Add(p2);
03877    list->Add(p3);
03878    
03879    p1->Merge(list);
03880 
03881    bool ret = equals("MergeLabelSame3DProf", p1, p4, cmpOptStats, 1E-10);
03882    delete p1;
03883    delete p2;
03884    delete p3;
03885    return ret;  
03886 }
03887 
03888 bool testMerge1DLabelDiff()
03889 {
03890    // Tests the merge with some different labels method for 1D Histograms
03891 
03892    // This test fails, as expected! That is why it is not run in the tests suite.
03893 
03894    TH1D* h1 = new TH1D("merge1DLabelDiff-h1", "h1-Title", numberOfBins, minRange, maxRange);
03895    TH1D* h2 = new TH1D("merge1DLabelDiff-h2", "h2-Title", numberOfBins, minRange, maxRange);
03896    TH1D* h3 = new TH1D("merge1DLabelDiff-h3", "h3-Title", numberOfBins, minRange, maxRange);
03897    TH1D* h4 = new TH1D("merge1DLabelDiff-h4", "h4-Title", numberOfBins, minRange, maxRange);
03898 
03899    h1->GetXaxis()->SetBinLabel(2, "gamma");
03900    h2->GetXaxis()->SetBinLabel(6, "beta");
03901    h3->GetXaxis()->SetBinLabel(4, "alpha");
03902    h4->GetXaxis()->SetBinLabel(4, "alpha");
03903 
03904    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03905       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03906       h1->Fill(x, 1.0);
03907       h4->Fill(x, 1.0);
03908    }
03909 
03910    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03911       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03912       h2->Fill(x, 1.0);
03913       h4->Fill(x, 1.0);
03914    }
03915 
03916    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03917       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03918       h3->Fill(x, 1.0);
03919       h4->Fill(x, 1.0);
03920    }
03921 
03922    TList *list = new TList;
03923    list->Add(h2);
03924    list->Add(h3);
03925    
03926    h1->Merge(list);
03927 
03928    bool ret = equals("MergeLabelDiff1D", h1, h4, cmpOptStats, 1E-10);
03929    delete h1;
03930    delete h2;
03931    delete h3;
03932    return ret;
03933 }
03934 
03935 bool testMerge2DLabelDiff()
03936 {
03937    // Tests the merge with some different labels method for 2D Histograms
03938 
03939    // It does not work properly! Look, the bins with the same labels
03940    // are different ones and still the tests passes! This is not
03941    // consistent with TH1::Merge()
03942 
03943    TH2D* h1 = new TH2D("merge2DLabelDiff-h1", "h1-Title", 
03944                        numberOfBins, minRange, maxRange,
03945                        numberOfBins + 2, minRange, maxRange);
03946    TH2D* h2 = new TH2D("merge2DLabelDiff-h2", "h2-Title",
03947                        numberOfBins, minRange, maxRange,
03948                        numberOfBins + 2, minRange, maxRange);
03949    TH2D* h3 = new TH2D("merge2DLabelDiff-h3", "h3-Title",
03950                        numberOfBins, minRange, maxRange,
03951                        numberOfBins + 2, minRange, maxRange);
03952    TH2D* h4 = new TH2D("merge2DLabelDiff-h4", "h4-Title",
03953                        numberOfBins, minRange, maxRange,
03954                        numberOfBins + 2, minRange, maxRange);
03955 
03956    h1->GetXaxis()->SetBinLabel(2, "gamma");
03957    h2->GetXaxis()->SetBinLabel(6, "beta");
03958    h3->GetXaxis()->SetBinLabel(4, "alpha");
03959    h4->GetXaxis()->SetBinLabel(4, "alpha");
03960 
03961    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03962       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03963       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03964       h1->Fill(x, y, 1.0);
03965       h4->Fill(x, y, 1.0);
03966    }
03967 
03968    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03969       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03970       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03971       h2->Fill(x, y, 1.0);
03972       h4->Fill(x, y, 1.0);
03973    }
03974 
03975    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
03976       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03977       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
03978       h3->Fill(x, y, 1.0);
03979       h4->Fill(x, y, 1.0);
03980    }
03981 
03982    TList *list = new TList;
03983    list->Add(h2);
03984    list->Add(h3);
03985    
03986    h1->Merge(list);
03987 
03988    bool ret = equals("MergeLabelDiff2D", h1, h4, cmpOptStats, 1E-10);
03989    delete h1;
03990    delete h2;
03991    delete h3;
03992    return ret;
03993 }
03994 
03995 bool testMerge3DLabelDiff()
03996 {
03997    // Tests the merge with some different labels method for 3D Histograms
03998 
03999    // It does not work properly! Look, the bins with the same labels
04000    // are different ones and still the tests passes! This is not
04001    // consistent with TH1::Merge()
04002 
04003    TH3D* h1 = new TH3D("merge3DLabelDiff-h1", "h1-Title", 
04004                        numberOfBins, minRange, maxRange,
04005                        numberOfBins + 1, minRange, maxRange,
04006                        numberOfBins + 2, minRange, maxRange);
04007    TH3D* h2 = new TH3D("merge3DLabelDiff-h2", "h2-Title",
04008                        numberOfBins, minRange, maxRange,
04009                        numberOfBins + 1, minRange, maxRange,
04010                        numberOfBins + 2, minRange, maxRange);
04011    TH3D* h3 = new TH3D("merge3DLabelDiff-h3", "h3-Title",
04012                        numberOfBins, minRange, maxRange,
04013                        numberOfBins + 1, minRange, maxRange,
04014                        numberOfBins + 2, minRange, maxRange);
04015    TH3D* h4 = new TH3D("merge3DLabelDiff-h4", "h4-Title",
04016                        numberOfBins, minRange, maxRange,
04017                        numberOfBins + 1, minRange, maxRange,
04018                        numberOfBins + 2, minRange, maxRange);
04019 
04020    h1->GetXaxis()->SetBinLabel(2, "gamma");
04021    h2->GetXaxis()->SetBinLabel(6, "beta");
04022    h3->GetXaxis()->SetBinLabel(4, "alpha");
04023    h4->GetXaxis()->SetBinLabel(4, "alpha");
04024 
04025    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04026       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04027       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04028       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04029       h1->Fill(x, y, z, 1.0);
04030       h4->Fill(x, y, z, 1.0);
04031    }
04032 
04033    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04034       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04035       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04036       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04037       h2->Fill(x, y, z, 1.0);
04038       h4->Fill(x, y, z, 1.0);
04039    }
04040 
04041    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04042       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04043       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04044       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04045       h3->Fill(x, y, z, 1.0);
04046       h4->Fill(x, y, z, 1.0);
04047    }
04048 
04049    TList *list = new TList;
04050    list->Add(h2);
04051    list->Add(h3);
04052    
04053    h1->Merge(list);
04054 
04055    bool ret = equals("MergeLabelDiff3D", h1, h4, cmpOptStats, 1E-10);
04056    delete h1;
04057    delete h2;
04058    delete h3;
04059    return ret;
04060 }
04061 
04062 bool testMergeProf1DLabelDiff()
04063 {
04064    // Tests the merge with some different labels method for 1D Profiles
04065 
04066    TProfile* p1 = new TProfile("merge1DLabelDiff-p1", "p1-Title", numberOfBins, minRange, maxRange);
04067    TProfile* p2 = new TProfile("merge1DLabelDiff-p2", "p2-Title", numberOfBins, minRange, maxRange);
04068    TProfile* p3 = new TProfile("merge1DLabelDiff-p3", "p3-Title", numberOfBins, minRange, maxRange);
04069    TProfile* p4 = new TProfile("merge1DLabelDiff-p4", "p4-Title", numberOfBins, minRange, maxRange);
04070 
04071    // It does not work properly! Look, the bins with the same labels
04072    // are different ones and still the tests passes! This is not
04073    // consistent with TH1::Merge()
04074    p1->GetXaxis()->SetBinLabel(2, "gamma");
04075    p2->GetXaxis()->SetBinLabel(6, "beta");
04076    p3->GetXaxis()->SetBinLabel(4, "alpha");
04077    p4->GetXaxis()->SetBinLabel(4, "alpha");
04078 
04079    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04080       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04081       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04082       p1->Fill(x, y, 1.0);
04083       p4->Fill(x, y, 1.0);
04084    }
04085 
04086    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04087       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04088       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04089       p2->Fill(x, y, 1.0);
04090       p4->Fill(x, y, 1.0);
04091    }
04092 
04093    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04094       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04095       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04096       p3->Fill(x, y, 1.0);
04097       p4->Fill(x, y, 1.0);
04098    }
04099 
04100    TList *list = new TList;
04101    list->Add(p2);
04102    list->Add(p3);
04103    
04104    p1->Merge(list);
04105 
04106    bool ret = equals("MergeLabelDiff1DProf", p1, p4, cmpOptStats, 1E-10);
04107    delete p1;
04108    delete p2;
04109    delete p3;
04110    return ret;
04111 }
04112 
04113 bool testMergeProf2DLabelDiff()
04114 {
04115    // Tests the merge with some different labels method for 2D Profiles
04116 
04117    TProfile2D* p1 = new TProfile2D("merge2DLabelDiff-p1", "p1-Title", 
04118                                    numberOfBins, minRange, maxRange,
04119                                    numberOfBins + 2, minRange, maxRange);
04120    TProfile2D* p2 = new TProfile2D("merge2DLabelDiff-p2", "p2-Title", 
04121                                    numberOfBins, minRange, maxRange,
04122                                    numberOfBins + 2, minRange, maxRange);
04123    TProfile2D* p3 = new TProfile2D("merge2DLabelDiff-p3", "p3-Title",
04124                                    numberOfBins, minRange, maxRange,
04125                                    numberOfBins + 2, minRange, maxRange);
04126    TProfile2D* p4 = new TProfile2D("merge2DLabelDiff-p4", "p4-Title",
04127                                    numberOfBins, minRange, maxRange,
04128                                    numberOfBins + 2, minRange, maxRange);
04129 
04130    // It does not work properly! Look, the bins with the same labels
04131    // are different ones and still the tests passes! This is not
04132    // consistent with TH1::Merge()
04133    p1->GetXaxis()->SetBinLabel(2, "gamma");
04134    p2->GetXaxis()->SetBinLabel(6, "beta");
04135    p3->GetXaxis()->SetBinLabel(4, "alpha");
04136    p4->GetXaxis()->SetBinLabel(4, "alpha");
04137 
04138    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04139       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04140       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04141       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04142       p1->Fill(x, y, z, 1.0);
04143       p4->Fill(x, y, z, 1.0);
04144    }
04145 
04146    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04147       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04148       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04149       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04150       p2->Fill(x, y, z, 1.0);
04151       p4->Fill(x, y, z, 1.0);
04152    }
04153 
04154    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04155       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04156       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04157       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04158       p3->Fill(x, y, z, 1.0);
04159       p4->Fill(x, y, z, 1.0);
04160    }
04161 
04162    TList *list = new TList;
04163    list->Add(p2);
04164    list->Add(p3);
04165    
04166    p1->Merge(list);
04167 
04168    bool ret = equals("MergeLabelDiff2DProf", p1, p4, cmpOptStats, 1E-10);
04169    delete p1;
04170    delete p2;
04171    delete p3;
04172    return ret;
04173 }
04174 
04175 bool testMergeProf3DLabelDiff()
04176 {
04177    // Tests the merge with some different labels method for 3D Profiles
04178 
04179    TProfile3D* p1 = new TProfile3D("merge3DLabelDiff-p1", "p1-Title", 
04180                                    numberOfBins, minRange, maxRange,
04181                                    numberOfBins + 1, minRange, maxRange,
04182                                    numberOfBins + 2, minRange, maxRange);
04183    TProfile3D* p2 = new TProfile3D("merge3DLabelDiff-p2", "p2-Title", 
04184                                    numberOfBins, minRange, maxRange,
04185                                    numberOfBins + 1, minRange, maxRange,
04186                                    numberOfBins + 2, minRange, maxRange);
04187    TProfile3D* p3 = new TProfile3D("merge3DLabelDiff-p3", "p3-Title",
04188                                    numberOfBins, minRange, maxRange,
04189                                    numberOfBins + 1, minRange, maxRange,
04190                                    numberOfBins + 2, minRange, maxRange);
04191    TProfile3D* p4 = new TProfile3D("merge3DLabelDiff-p4", "p4-Title",
04192                                    numberOfBins, minRange, maxRange,
04193                                    numberOfBins + 1, minRange, maxRange,
04194                                    numberOfBins + 2, minRange, maxRange);
04195 
04196    // It does not work properly! Look, the bins with the same labels
04197    // are different ones and still the tests passes! This is not
04198    // consistent with TH1::Merge()
04199    p1->GetXaxis()->SetBinLabel(2, "gamma");
04200    p2->GetXaxis()->SetBinLabel(6, "beta");
04201    p3->GetXaxis()->SetBinLabel(4, "alpha");
04202    p4->GetXaxis()->SetBinLabel(4, "alpha");
04203 
04204    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04205       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04206       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04207       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04208       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04209       p1->Fill(x, y, z, t, 1.0);
04210       p4->Fill(x, y, z, t, 1.0);
04211    }
04212 
04213    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04214       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04215       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04216       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04217       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04218       p2->Fill(x, y, z, t, 1.0);
04219       p4->Fill(x, y, z, t, 1.0);
04220    }
04221 
04222    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04223       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04224       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04225       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04226       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04227       p3->Fill(x, y, z, t, 1.0);
04228       p4->Fill(x, y, z, t, 1.0);
04229    }
04230 
04231    TList *list = new TList;
04232    list->Add(p2);
04233    list->Add(p3);
04234    
04235    p1->Merge(list);
04236 
04237    bool ret = equals("MergeLabelDiff3DProf", p1, p4, cmpOptStats, 1E-10);
04238    delete p1;
04239    delete p2;
04240    delete p3;
04241    return ret;
04242 }
04243 
04244 bool testMerge1DLabelAll()
04245 {
04246    // Tests the merge method with fully equally labelled 1D Histograms
04247 
04248    TH1D* h1 = new TH1D("merge1DLabelAll-h1", "h1-Title", numberOfBins, minRange, maxRange);
04249    TH1D* h2 = new TH1D("merge1DLabelAll-h2", "h2-Title", numberOfBins, minRange, maxRange);
04250    TH1D* h3 = new TH1D("merge1DLabelAll-h3", "h3-Title", numberOfBins, minRange, maxRange);
04251    TH1D* h4 = new TH1D("merge1DLabelAll-h4", "h4-Title", numberOfBins, minRange, maxRange);
04252 
04253    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04254       ostringstream name;
04255       name << (char) ((int) 'a' + i - 1);
04256       h1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04257       h2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04258       h3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04259       h4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04260    }
04261 
04262    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04263       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04264       h1->Fill(x, 1.0);
04265       h4->Fill(x, 1.0);
04266    }
04267 
04268    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04269       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04270       h2->Fill(x, 1.0);
04271       h4->Fill(x, 1.0);
04272    }
04273 
04274    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04275       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04276       h3->Fill(x, 1.0);
04277       h4->Fill(x, 1.0);
04278    }
04279 
04280    TList *list = new TList;
04281    list->Add(h2);
04282    list->Add(h3);
04283    
04284    h1->Merge(list);
04285 
04286    bool ret = equals("MergeLabelAll1D", h1, h4, cmpOptStats, 1E-10);
04287    delete h1;
04288    delete h2;
04289    delete h3;
04290    return ret;
04291 }
04292 
04293 bool testMerge2DLabelAll()
04294 {
04295    // Tests the merge method with fully equally labelled 2D Histograms
04296 
04297    TH2D* h1 = new TH2D("merge2DLabelAll-h1", "h1-Title", 
04298                        numberOfBins, minRange, maxRange,
04299                        numberOfBins + 2, minRange, maxRange);
04300    TH2D* h2 = new TH2D("merge2DLabelAll-h2", "h2-Title",
04301                        numberOfBins, minRange, maxRange,
04302                        numberOfBins + 2, minRange, maxRange);
04303    TH2D* h3 = new TH2D("merge2DLabelAll-h3", "h3-Title", 
04304                        numberOfBins, minRange, maxRange,
04305                        numberOfBins + 2, minRange, maxRange);
04306    TH2D* h4 = new TH2D("merge2DLabelAll-h4", "h4-Title",
04307                        numberOfBins, minRange, maxRange,
04308                        numberOfBins + 2, minRange, maxRange);
04309 
04310    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04311       ostringstream name;
04312       name << (char) ((int) 'a' + i - 1);
04313       h1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04314       h2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04315       h3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04316       h4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04317    }
04318 
04319    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04320       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04321       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04322       h1->Fill(x, y, 1.0);
04323       h4->Fill(x, y, 1.0);
04324    }
04325 
04326    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04327       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04328       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04329       h2->Fill(x, y, 1.0);
04330       h4->Fill(x, y, 1.0);
04331    }
04332 
04333    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04334       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04335       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04336       h3->Fill(x, y, 1.0);
04337       h4->Fill(x, y, 1.0);
04338    }
04339 
04340    TList *list = new TList;
04341    list->Add(h2);
04342    list->Add(h3);
04343    
04344    h1->Merge(list);
04345 
04346    bool ret = equals("MergeLabelAll2D", h1, h4, cmpOptStats, 1E-10);
04347    delete h1;
04348    delete h2;
04349    delete h3;
04350    return ret;
04351 }
04352 
04353 bool testMerge3DLabelAll()
04354 {
04355    // Tests the merge method with fully equally labelled 3D Histograms
04356 
04357    TH3D* h1 = new TH3D("merge3DLabelAll-h1", "h1-Title", 
04358                        numberOfBins, minRange, maxRange,
04359                        numberOfBins + 1, minRange, maxRange,
04360                        numberOfBins + 2, minRange, maxRange);
04361    TH3D* h2 = new TH3D("merge3DLabelAll-h2", "h2-Title",
04362                        numberOfBins, minRange, maxRange,
04363                        numberOfBins + 1, minRange, maxRange,
04364                        numberOfBins + 2, minRange, maxRange);
04365    TH3D* h3 = new TH3D("merge3DLabelAll-h3", "h3-Title", 
04366                        numberOfBins, minRange, maxRange,
04367                        numberOfBins + 1, minRange, maxRange,
04368                        numberOfBins + 2, minRange, maxRange);
04369    TH3D* h4 = new TH3D("merge3DLabelAll-h4", "h4-Title",
04370                        numberOfBins, minRange, maxRange,
04371                        numberOfBins + 1, minRange, maxRange,
04372                        numberOfBins + 2, minRange, maxRange);
04373 
04374    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04375       ostringstream name;
04376       name << (char) ((int) 'a' + i - 1);
04377       h1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04378       h2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04379       h3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04380       h4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04381    }
04382 
04383    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04384       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04385       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04386       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04387       h1->Fill(x, y, z, 1.0);
04388       h4->Fill(x, y, z, 1.0);
04389    }
04390 
04391    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04392       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04393       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04394       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04395       h2->Fill(x, y, z, 1.0);
04396       h4->Fill(x, y, z, 1.0);
04397    }
04398 
04399    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04400       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04401       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04402       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04403       h3->Fill(x, y, z, 1.0);
04404       h4->Fill(x, y, z, 1.0);
04405    }
04406 
04407    TList *list = new TList;
04408    list->Add(h2);
04409    list->Add(h3);
04410    
04411    h1->Merge(list);
04412 
04413    bool ret = equals("MergeLabelAll3D", h1, h4, cmpOptStats, 1E-10);
04414    delete h1;
04415    delete h2;
04416    delete h3;
04417    return ret;
04418 }
04419 
04420 bool testMergeProf1DLabelAll()
04421 {
04422    // Tests the merge method with fully equally labelled 1D Profiles
04423 
04424    TProfile* p1 = new TProfile("merge1DLabelAll-p1", "p1-Title", numberOfBins, minRange, maxRange);
04425    TProfile* p2 = new TProfile("merge1DLabelAll-p2", "p2-Title", numberOfBins, minRange, maxRange);
04426    TProfile* p3 = new TProfile("merge1DLabelAll-p3", "p3-Title", numberOfBins, minRange, maxRange);
04427    TProfile* p4 = new TProfile("merge1DLabelAll-p4", "p4-Title", numberOfBins, minRange, maxRange);
04428 
04429    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04430       ostringstream name;
04431       name << (char) ((int) 'a' + i - 1);
04432       p1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04433       p2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04434       p3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04435       p4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04436    }
04437 
04438    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04439       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04440       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04441       p1->Fill(x, y, 1.0);
04442       p4->Fill(x, y, 1.0);
04443    }
04444 
04445    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04446       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04447       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04448       p2->Fill(x, y, 1.0);
04449       p4->Fill(x, y, 1.0);
04450    }
04451 
04452    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04453       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04454       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04455       p3->Fill(x, y, 1.0);
04456       p4->Fill(x, y, 1.0);
04457    }
04458 
04459    TList *list = new TList;
04460    list->Add(p2);
04461    list->Add(p3);
04462    
04463    p1->Merge(list);
04464 
04465    bool ret = equals("MergeLabelAll1DProf", p1, p4, cmpOptStats, 1E-10);
04466    delete p1;
04467    delete p2;
04468    delete p3;
04469    return ret;
04470 }
04471 
04472 bool testMergeProf2DLabelAll()
04473 {
04474    // Tests the merge method with fully equally labelled 2D Profiles
04475 
04476    TProfile2D* p1 = new TProfile2D("merge2DLabelAll-p1", "p1-Title", 
04477                                    numberOfBins, minRange, maxRange,
04478                                    numberOfBins + 2, minRange, maxRange);
04479    TProfile2D* p2 = new TProfile2D("merge2DLabelAll-p2", "p2-Title",
04480                                    numberOfBins, minRange, maxRange,
04481                                    numberOfBins + 2, minRange, maxRange);
04482    TProfile2D* p3 = new TProfile2D("merge2DLabelAll-p3", "p3-Title",
04483                                    numberOfBins, minRange, maxRange,
04484                                    numberOfBins + 2, minRange, maxRange);
04485    TProfile2D* p4 = new TProfile2D("merge2DLabelAll-p4", "p4-Title",
04486                                    numberOfBins, minRange, maxRange,
04487                                    numberOfBins + 2, minRange, maxRange);
04488 
04489    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04490       ostringstream name;
04491       name << (char) ((int) 'a' + i - 1);
04492       p1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04493       p2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04494       p3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04495       p4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04496    }
04497 
04498    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04499       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04500       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04501       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04502       p1->Fill(x, y, z, 1.0);
04503       p4->Fill(x, y, z, 1.0);
04504    }
04505 
04506    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04507       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04508       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04509       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04510       p2->Fill(x, y, z, 1.0);
04511       p4->Fill(x, y, z, 1.0);
04512    }
04513 
04514    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04515       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04516       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04517       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04518       p3->Fill(x, y, z, 1.0);
04519       p4->Fill(x, y, z, 1.0);
04520    }
04521 
04522    TList *list = new TList;
04523    list->Add(p2);
04524    list->Add(p3);
04525    
04526    p1->Merge(list);
04527 
04528    bool ret = equals("MergeLabelAll2DProf", p1, p4, cmpOptStats, 1E-10);
04529    delete p1;
04530    delete p2;
04531    delete p3;
04532    return ret;
04533 }
04534 
04535 bool testMergeProf3DLabelAll()
04536 {
04537    // Tests the merge method with fully equally labelled 3D Profiles
04538 
04539    TProfile3D* p1 = new TProfile3D("merge3DLabelAll-p1", "p1-Title", 
04540                                    numberOfBins, minRange, maxRange,
04541                                    numberOfBins + 1, minRange, maxRange,
04542                                    numberOfBins + 2, minRange, maxRange);
04543    TProfile3D* p2 = new TProfile3D("merge3DLabelAll-p2", "p2-Title",
04544                                    numberOfBins, minRange, maxRange,
04545                                    numberOfBins + 1, minRange, maxRange,
04546                                    numberOfBins + 2, minRange, maxRange);
04547    TProfile3D* p3 = new TProfile3D("merge3DLabelAll-p3", "p3-Title",
04548                                    numberOfBins, minRange, maxRange,
04549                                    numberOfBins + 1, minRange, maxRange,
04550                                    numberOfBins + 2, minRange, maxRange);
04551    TProfile3D* p4 = new TProfile3D("merge3DLabelAll-p4", "p4-Title",
04552                                    numberOfBins, minRange, maxRange,
04553                                    numberOfBins + 1, minRange, maxRange,
04554                                    numberOfBins + 2, minRange, maxRange);
04555 
04556    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04557       ostringstream name;
04558       name << (char) ((int) 'a' + i - 1);
04559       p1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04560       p2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04561       p3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04562       p4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04563    }
04564 
04565    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04566       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04567       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04568       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04569       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04570       p1->Fill(x, y, z, t, 1.0);
04571       p4->Fill(x, y, z, t, 1.0);
04572    }
04573 
04574    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04575       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04576       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04577       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04578       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04579       p2->Fill(x, y, z, t, 1.0);
04580       p4->Fill(x, y, z, t, 1.0);
04581    }
04582 
04583    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04584       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04585       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04586       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04587       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04588       p3->Fill(x, y, z, t, 1.0);
04589       p4->Fill(x, y, z, t, 1.0);
04590    }
04591 
04592    TList *list = new TList;
04593    list->Add(p2);
04594    list->Add(p3);
04595    
04596    p1->Merge(list);
04597 
04598    bool ret = equals("MergeLabelAll3DProf", p1, p4, cmpOptStats, 1E-10);
04599    delete p1;
04600    delete p2;
04601    delete p3;
04602    return ret;
04603 }
04604 
04605 bool testMerge1DLabelAllDiff()
04606 {
04607    // Tests the merge method with fully differently labelled 1D Histograms
04608 
04609    // This test fails, as expected! That is why it is not run in the tests suite.
04610 
04611    TH1D* h1 = new TH1D("merge1DLabelAllDiff-h1", "h1-Title", numberOfBins, minRange, maxRange);
04612    TH1D* h2 = new TH1D("merge1DLabelAllDiff-h2", "h2-Title", numberOfBins, minRange, maxRange);
04613    TH1D* h3 = new TH1D("merge1DLabelAllDiff-h3", "h3-Title", numberOfBins, minRange, maxRange);
04614    TH1D* h4 = new TH1D("merge1DLabelAllDiff-h4", "h4-Title", numberOfBins, minRange, maxRange);
04615 
04616    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04617       ostringstream name;
04618       name << (char) ((int) 'a' + i - 1);
04619       h1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04620       name << 1;
04621       h2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04622       name << 2;
04623       h3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04624       name << 3;
04625       h4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04626    }
04627 
04628    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04629       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04630       h1->Fill(x, 1.0);
04631       h4->Fill(x, 1.0);
04632    }
04633 
04634    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04635       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04636       h2->Fill(x, 1.0);
04637       h4->Fill(x, 1.0);
04638    }
04639 
04640    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04641       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04642       h3->Fill(x, 1.0);
04643       h4->Fill(x, 1.0);
04644    }
04645 
04646    TList *list = new TList;
04647    list->Add(h2);
04648    list->Add(h3);
04649    
04650    h1->Merge(list);
04651    
04652    bool ret = equals("MergeLabelAllDiff1D", h1, h4, cmpOptStats, 1E-10);
04653    delete h1;
04654    delete h2;
04655    delete h3;
04656    return ret;
04657 }
04658 
04659 bool testMerge2DLabelAllDiff()
04660 {
04661    // Tests the merge method with fully differently labelled 2D Histograms
04662 
04663    // It does not work properly! Look, the bins with the same labels
04664    // are different ones and still the tests passes! This is not
04665    // consistent with TH1::Merge()
04666 
04667    TH2D* h1 = new TH2D("merge2DLabelAllDiff-h1", "h1-Title", 
04668                        numberOfBins, minRange, maxRange,
04669                        numberOfBins + 2, minRange, maxRange);
04670    TH2D* h2 = new TH2D("merge2DLabelAllDiff-h2", "h2-Title",
04671                        numberOfBins, minRange, maxRange,
04672                        numberOfBins + 2, minRange, maxRange);
04673    TH2D* h3 = new TH2D("merge2DLabelAllDiff-h3", "h3-Title",
04674                        numberOfBins, minRange, maxRange,
04675                        numberOfBins + 2, minRange, maxRange);
04676    TH2D* h4 = new TH2D("merge2DLabelAllDiff-h4", "h4-Title",
04677                        numberOfBins, minRange, maxRange, 
04678                        numberOfBins + 2, minRange, maxRange);
04679 
04680    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04681       ostringstream name;
04682       name << (char) ((int) 'a' + i - 1);
04683       h1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04684       h1->GetYaxis()->SetBinLabel(i, name.str().c_str());
04685       name << 1;
04686       h2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04687       h2->GetYaxis()->SetBinLabel(i, name.str().c_str());
04688       name << 2;
04689       h3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04690       h3->GetYaxis()->SetBinLabel(i, name.str().c_str());
04691       name << 3;
04692       h4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04693    }
04694 
04695    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04696       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04697       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04698       h1->Fill(x, y, 1.0);
04699       h4->Fill(x, y, 1.0);
04700    }
04701 
04702    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04703       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04704       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04705       h2->Fill(x, y, 1.0);
04706       h4->Fill(x, y, 1.0);
04707    }
04708 
04709    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04710       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04711       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04712       h3->Fill(x, y, 1.0);
04713       h4->Fill(x, y, 1.0);
04714    }
04715 
04716    TList *list = new TList;
04717    list->Add(h2);
04718    list->Add(h3);
04719    
04720    h1->Merge(list);
04721 
04722    bool ret = equals("MergeLabelAllDiff2D", h1, h4, cmpOptStats, 1E-10);
04723    delete h1;
04724    delete h2;
04725    delete h3;
04726    return ret;
04727 }
04728 
04729 bool testMerge3DLabelAllDiff()
04730 {
04731    // Tests the merge method with fully differently labelled 3D Histograms
04732 
04733    // It does not work properly! Look, the bins with the same labels
04734    // are different ones and still the tests passes! This is not
04735    // consistent with TH1::Merge()
04736 
04737    TH3D* h1 = new TH3D("merge3DLabelAllDiff-h1", "h1-Title", 
04738                        numberOfBins, minRange, maxRange,
04739                        numberOfBins + 1, minRange, maxRange,
04740                        numberOfBins + 2, minRange, maxRange);
04741    TH3D* h2 = new TH3D("merge3DLabelAllDiff-h2", "h2-Title",
04742                        numberOfBins, minRange, maxRange,
04743                        numberOfBins + 1, minRange, maxRange,
04744                        numberOfBins + 2, minRange, maxRange);
04745    TH3D* h3 = new TH3D("merge3DLabelAllDiff-h3", "h3-Title",
04746                        numberOfBins, minRange, maxRange,
04747                        numberOfBins + 1, minRange, maxRange,
04748                        numberOfBins + 2, minRange, maxRange);
04749    TH3D* h4 = new TH3D("merge3DLabelAllDiff-h4", "h4-Title",
04750                        numberOfBins, minRange, maxRange,
04751                        numberOfBins + 1, minRange, maxRange, 
04752                        numberOfBins + 2, minRange, maxRange);
04753 
04754    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04755       ostringstream name;
04756       name << (char) ((int) 'a' + i - 1);
04757       h1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04758       h1->GetYaxis()->SetBinLabel(i, name.str().c_str());
04759       h1->GetZaxis()->SetBinLabel(i, name.str().c_str());
04760       name << 1;
04761       h2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04762       h2->GetYaxis()->SetBinLabel(i, name.str().c_str());
04763       h2->GetZaxis()->SetBinLabel(i, name.str().c_str());
04764       name << 2;
04765       h3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04766       h3->GetYaxis()->SetBinLabel(i, name.str().c_str());
04767       h3->GetZaxis()->SetBinLabel(i, name.str().c_str());
04768       name << 3;
04769       h4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04770       h4->GetYaxis()->SetBinLabel(i, name.str().c_str());
04771       h4->GetZaxis()->SetBinLabel(i, name.str().c_str());
04772    }
04773 
04774    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04775       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04776       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04777       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04778       h1->Fill(x, y, z, 1.0);
04779       h4->Fill(x, y, z, 1.0);
04780    }
04781 
04782    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04783       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04784       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04785       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04786       h2->Fill(x, y, z, 1.0);
04787       h4->Fill(x, y, z, 1.0);
04788    }
04789 
04790    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04791       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04792       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04793       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04794       h3->Fill(x, y, z, 1.0);
04795       h4->Fill(x, y, z, 1.0);
04796    }
04797 
04798    TList *list = new TList;
04799    list->Add(h2);
04800    list->Add(h3);
04801    
04802    h1->Merge(list);
04803 
04804    bool ret = equals("MergeLabelAllDiff3D", h1, h4, cmpOptStats, 1E-10);
04805    delete h1;
04806    delete h2;
04807    delete h3;
04808    return ret;  
04809 }
04810 
04811 bool testMergeProf1DLabelAllDiff()
04812 {
04813    // Tests the merge method with fully differently labelled 1D Profiles
04814 
04815    TProfile* p1 = new TProfile("merge1DLabelAllDiff-p1", "p1-Title", numberOfBins, minRange, maxRange);
04816    TProfile* p2 = new TProfile("merge1DLabelAllDiff-p2", "p2-Title", numberOfBins, minRange, maxRange);
04817    TProfile* p3 = new TProfile("merge1DLabelAllDiff-p3", "p3-Title", numberOfBins, minRange, maxRange);
04818    TProfile* p4 = new TProfile("merge1DLabelAllDiff-p4", "p4-Title", numberOfBins, minRange, maxRange);
04819 
04820    // It does not work properly! Look, the bins with the same labels
04821    // are different ones and still the tests passes! This is not
04822    // consistent with TH1::Merge()
04823    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04824       ostringstream name;
04825       name << (char) ((int) 'a' + i - 1);
04826       p1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04827       name << 1;
04828       p2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04829       name << 2;
04830       p3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04831       name << 3;
04832       p4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04833    }
04834 
04835    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04836       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04837       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04838       p1->Fill(x, y, 1.0);
04839       p4->Fill(x, y, 1.0);
04840    }
04841 
04842    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04843       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04844       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04845       p2->Fill(x, y, 1.0);
04846       p4->Fill(x, y, 1.0);
04847    }
04848 
04849    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04850       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04851       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04852       p3->Fill(x, y, 1.0);
04853       p4->Fill(x, y, 1.0);
04854    }
04855 
04856    TList *list = new TList;
04857    list->Add(p2);
04858    list->Add(p3);
04859    
04860    p1->Merge(list);
04861    
04862    bool ret = equals("MergeLabelAllDiff1DProf", p1, p4, cmpOptStats, 1E-10);
04863    delete p1;
04864    delete p2;
04865    delete p3;
04866    return ret;
04867 }
04868 
04869 bool testMergeProf2DLabelAllDiff()
04870 {
04871    // Tests the merge method with fully differently labelled 2D Profiles
04872 
04873    TProfile2D* p1 = new TProfile2D("merge2DLabelAllDiff-p1", "p1-Title", 
04874                                    numberOfBins, minRange, maxRange,
04875                                    numberOfBins + 2, minRange, maxRange);
04876    TProfile2D* p2 = new TProfile2D("merge2DLabelAllDiff-p2", "p2-Title",
04877                                    numberOfBins, minRange, maxRange,
04878                                    numberOfBins + 2, minRange, maxRange);
04879    TProfile2D* p3 = new TProfile2D("merge2DLabelAllDiff-p3", "p3-Title",
04880                                    numberOfBins, minRange, maxRange,
04881                                    numberOfBins + 2, minRange, maxRange);
04882    TProfile2D* p4 = new TProfile2D("merge2DLabelAllDiff-p4", "p4-Title",
04883                                    numberOfBins, minRange, maxRange,
04884                                    numberOfBins + 2, minRange, maxRange);
04885 
04886    // It does not work properly! Look, the bins with the same labels
04887    // are different ones and still the tests passes! This is not
04888    // consistent with TH1::Merge()
04889    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04890       ostringstream name;
04891       name << (char) ((int) 'a' + i - 1);
04892       p1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04893       p1->GetYaxis()->SetBinLabel(i, name.str().c_str());
04894       name << 1;
04895       p2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04896       p2->GetYaxis()->SetBinLabel(i, name.str().c_str());
04897       name << 2;
04898       p3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04899       p3->GetYaxis()->SetBinLabel(i, name.str().c_str());
04900       name << 3;
04901       p4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04902       p4->GetYaxis()->SetBinLabel(i, name.str().c_str());
04903    }
04904 
04905    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04906       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04907       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04908       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04909       p1->Fill(x, y, z, 1.0);
04910       p4->Fill(x, y, z, 1.0);
04911    }
04912 
04913    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04914       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04915       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04916       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04917       p2->Fill(x, y, z, 1.0);
04918       p4->Fill(x, y, z, 1.0);
04919    }
04920 
04921    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04922       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04923       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04924       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04925       p3->Fill(x, y, z, 1.0);
04926       p4->Fill(x, y, z, 1.0);
04927    }
04928 
04929    TList *list = new TList;
04930    list->Add(p2);
04931    list->Add(p3);
04932    
04933    p1->Merge(list);
04934    
04935    bool ret = equals("MergeLabelAllDiff2DProf", p1, p4, cmpOptStats, 1E-10);
04936    delete p1;
04937    delete p2;
04938    delete p3;
04939    return ret;
04940 }
04941 
04942 bool testMergeProf3DLabelAllDiff()
04943 {
04944    // Tests the merge method with fully differently labelled 3D Profiles
04945 
04946    TProfile3D* p1 = new TProfile3D("merge3DLabelAllDiff-p1", "p1-Title", 
04947                                    numberOfBins, minRange, maxRange,
04948                                    numberOfBins + 1, minRange, maxRange,
04949                                    numberOfBins + 2, minRange, maxRange);
04950    TProfile3D* p2 = new TProfile3D("merge3DLabelAllDiff-p2", "p2-Title",
04951                                    numberOfBins, minRange, maxRange,
04952                                    numberOfBins + 1, minRange, maxRange,
04953                                    numberOfBins + 2, minRange, maxRange);
04954    TProfile3D* p3 = new TProfile3D("merge3DLabelAllDiff-p3", "p3-Title",
04955                                    numberOfBins, minRange, maxRange,
04956                                    numberOfBins + 1, minRange, maxRange,
04957                                    numberOfBins + 2, minRange, maxRange);
04958    TProfile3D* p4 = new TProfile3D("merge3DLabelAllDiff-p4", "p4-Title",
04959                                    numberOfBins, minRange, maxRange,
04960                                    numberOfBins + 1, minRange, maxRange,
04961                                    numberOfBins + 2, minRange, maxRange);
04962 
04963    // It does not work properly! Look, the bins with the same labels
04964    // are different ones and still the tests passes! This is not
04965    // consistent with TH1::Merge()
04966    for ( Int_t i = 1; i <= numberOfBins; ++ i) {
04967       ostringstream name;
04968       name << (char) ((int) 'a' + i - 1);
04969       p1->GetXaxis()->SetBinLabel(i, name.str().c_str());
04970       p1->GetYaxis()->SetBinLabel(i, name.str().c_str());
04971       p1->GetZaxis()->SetBinLabel(i, name.str().c_str());
04972       name << 1;
04973       p2->GetXaxis()->SetBinLabel(i, name.str().c_str());
04974       p2->GetYaxis()->SetBinLabel(i, name.str().c_str());
04975       p2->GetZaxis()->SetBinLabel(i, name.str().c_str());
04976       name << 2;
04977       p3->GetXaxis()->SetBinLabel(i, name.str().c_str());
04978       p3->GetYaxis()->SetBinLabel(i, name.str().c_str());
04979       p3->GetZaxis()->SetBinLabel(i, name.str().c_str());
04980       name << 3;
04981       p4->GetXaxis()->SetBinLabel(i, name.str().c_str());
04982       p4->GetYaxis()->SetBinLabel(i, name.str().c_str());
04983       p4->GetZaxis()->SetBinLabel(i, name.str().c_str());
04984    }
04985 
04986    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04987       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04988       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04989       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04990       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04991       p1->Fill(x, y, z, t, 1.0);
04992       p4->Fill(x, y, z, t, 1.0);
04993    }
04994 
04995    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
04996       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04997       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04998       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
04999       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05000       p2->Fill(x, y, z, t, 1.0);
05001       p4->Fill(x, y, z, t, 1.0);
05002    }
05003 
05004    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
05005       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05006       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05007       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05008       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05009       p3->Fill(x, y, z, t, 1.0);
05010       p4->Fill(x, y, z, t, 1.0);
05011    }
05012 
05013    TList *list = new TList;
05014    list->Add(p2);
05015    list->Add(p3);
05016    
05017    p1->Merge(list);
05018    
05019    bool ret = equals("MergeLabelAllDiff3DProf", p1, p4, cmpOptStats, 1E-10);
05020    delete p1;
05021    delete p2;
05022    delete p3;
05023    return ret;
05024 }
05025 
05026 bool testMerge1DDiff() 
05027 {
05028    // Tests the merge method with different binned 1D Histograms
05029 
05030    TH1D *h1 = new TH1D("merge1DDiff-h1","h1-Title",110,-110,0);
05031    TH1D *h2 = new TH1D("merge1DDiff-h2","h2-Title",220,0,110);
05032    TH1D *h3 = new TH1D("merge1DDiff-h3","h3-Title",330,-55,55);
05033    TH1D *h4 = new TH1D("merge1DDiff-h4","h4-Title",220,-110,110);
05034 
05035    h1->Sumw2();h2->Sumw2();h3->Sumw2();h4->Sumw2();
05036 
05037    for ( Int_t e = 0; e < nEvents; ++e ) {
05038       Double_t value = r.Gaus(-55,10);
05039       h1->Fill(value, 1.0);
05040       h4->Fill(value, 1.0);
05041    }
05042 
05043    for ( Int_t e = 0; e < nEvents; ++e ) {
05044       Double_t value = r.Gaus(55,10);
05045       h2->Fill(value, 1.0);
05046       h4->Fill(value, 1.0);
05047    }
05048 
05049    for ( Int_t e = 0; e < nEvents; ++e ) {
05050       Double_t value = r.Gaus(0,10);
05051       h3->Fill(value, 1.0);
05052       h4->Fill(value, 1.0);
05053    }
05054 
05055    TList *list = new TList;
05056    list->Add(h2);
05057    list->Add(h3);
05058 
05059    h1->Merge(list);
05060 
05061    bool ret = equals("MergeDiff1D", h1, h4, cmpOptStats, 1E-10);
05062    delete h1;
05063    delete h2;
05064    delete h3;
05065    return ret;
05066 }
05067 
05068 bool testMerge2DDiff() 
05069 {
05070    // Tests the merge method with different binned 2D Histograms
05071 
05072    TH2D *h1 = new TH2D("merge2DDiff-h1","h1-Title",
05073                        110,-110,0,
05074                        110,-110,0);
05075    TH2D *h2 = new TH2D("merge2DDiff-h2","h2-Title",
05076                        220,0,110,
05077                        220,0,110);
05078    TH2D *h3 = new TH2D("merge2DDiff-h3","h3-Title",
05079                        330,-55,55,
05080                        330,-55,55);
05081    TH2D *h4 = new TH2D("merge2DDiff-h4","h4-Title",
05082                        220,-110,110,
05083                        220,-110,110);
05084 
05085    h1->Sumw2();h2->Sumw2();h3->Sumw2();h4->Sumw2();
05086 
05087    for ( Int_t e = 0; e < nEvents; ++e ) {
05088       Double_t x = r.Gaus(-55,10);
05089       Double_t y = r.Gaus(-55,10);
05090       h1->Fill(x, y, 1.0);
05091       h4->Fill(x, y, 1.0);
05092    }
05093 
05094    for ( Int_t e = 0; e < nEvents; ++e ) {
05095       Double_t x = r.Gaus(55,10);
05096       Double_t y = r.Gaus(55,10);
05097       h2->Fill(x, y, 1.0);
05098       h4->Fill(x, y, 1.0);
05099    }
05100 
05101    for ( Int_t e = 0; e < nEvents; ++e ) {
05102       Double_t x = r.Gaus(0,10);
05103       Double_t y = r.Gaus(0,10);
05104       h3->Fill(x, y, 1.0);
05105       h4->Fill(x, y, 1.0);
05106    }
05107 
05108    TList *list = new TList;
05109    list->Add(h2);
05110    list->Add(h3);
05111 
05112    h1->Merge(list);
05113 
05114    bool ret = equals("MergeDiff2D", h1, h4, cmpOptStats, 1E-10);
05115    delete h1;
05116    delete h2;
05117    delete h3;
05118    return ret;
05119 }
05120 
05121 bool testMerge3DDiff() 
05122 {
05123    // Tests the merge method with different binned 3D Histograms
05124 
05125    // This tests fails! It should not!
05126    TH3D *h1 = new TH3D("merge3DDiff-h1","h1-Title",
05127                        110,-110,0,
05128                        110,-110,0,
05129                        110,-110,0);
05130    TH3D *h2 = new TH3D("merge3DDiff-h2","h2-Title",
05131                        220,0,110,
05132                        220,0,110,
05133                        220,0,110);
05134    TH3D *h3 = new TH3D("merge3DDiff-h3","h3-Title",
05135                        330,-55,55,
05136                        330,-55,55,
05137                        330,-55,55);
05138    TH3D *h4 = new TH3D("merge3DDiff-h4","h4-Title",
05139                        220,-110,110,
05140                        220,-110,110,
05141                        220,-110,110);
05142 
05143    h1->Sumw2();h2->Sumw2();h3->Sumw2();h4->Sumw2();
05144 
05145    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
05146       Double_t x = r.Gaus(-55,10);
05147       Double_t y = r.Gaus(-55,10);
05148       Double_t z = r.Gaus(-55,10);
05149       h1->Fill(x, y, z, 1.0);
05150       h4->Fill(x, y, z, 1.0);
05151    }
05152 
05153    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
05154       Double_t x = r.Gaus(55,10);
05155       Double_t y = r.Gaus(55,10);
05156       Double_t z = r.Gaus(55,10);
05157       h2->Fill(x, y, z, 1.0);
05158       h4->Fill(x, y, z, 1.0);
05159    }
05160 
05161    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
05162       Double_t x = r.Gaus(0,10);
05163       Double_t y = r.Gaus(55,10);
05164       Double_t z = r.Gaus(0,10);
05165       h3->Fill(x, y, z, 1.0);
05166       h4->Fill(x, y, z, 1.0);
05167    }
05168 
05169    TList *list = new TList;
05170    list->Add(h2);
05171    list->Add(h3);
05172 
05173    h1->Merge(list);
05174 
05175    bool ret = equals("MergeDiff3D", h1, h4, cmpOptStats, 1E-10);
05176    delete h1;
05177    delete h2;
05178    delete h3;
05179    return ret;
05180 }
05181 
05182 bool testMergeProf1DDiff() 
05183 {
05184    // Tests the merge method with different binned 1D Profile
05185 
05186    // Stats fail, for a reason I do not know :S
05187 
05188    TProfile *p1 = new TProfile("merge1DDiff-p1","p1-Title",110,-110,0);
05189    TProfile *p2 = new TProfile("merge1DDiff-p2","p2-Title",220,0,110);
05190    TProfile *p3 = new TProfile("merge1DDiff-p3","p3-Title",330,-55,55);
05191    TProfile *p4 = new TProfile("merge1DDiff-p4","p4-Title",220,-110,110);
05192 
05193    for ( Int_t e = 0; e < nEvents; ++e ) {
05194       Double_t x = r.Gaus(-55,10);
05195       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05196       p1->Fill(x, y, 1.0);
05197       p4->Fill(x, y, 1.0);
05198    }
05199 
05200    for ( Int_t e = 0; e < nEvents; ++e ) {
05201       Double_t x = r.Gaus(55,10);
05202       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05203       p2->Fill(x, y, 1.0);
05204       p4->Fill(x, y, 1.0);
05205    }
05206 
05207    for ( Int_t e = 0; e < nEvents; ++e ) {
05208       Double_t x = r.Gaus(0,10);
05209       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05210       p3->Fill(x, y, 1.0);
05211       p4->Fill(x, y, 1.0);
05212    }
05213 
05214    TList *list = new TList;
05215    list->Add(p2);
05216    list->Add(p3);
05217 
05218    p1->Merge(list);
05219 
05220    bool ret = equals("MergeDiff1DProf", p1, p4, cmpOptNone , 1E-10);
05221    delete p1;
05222    delete p2;
05223    delete p3;
05224    return ret;
05225 }
05226 
05227 bool testMergeProf2DDiff() 
05228 {
05229    // Tests the merge method with different binned 2D Profile
05230 
05231    // This tests fails! It should not!
05232    TProfile2D *p1 = new TProfile2D("merge2DDiff-p1","p1-Title",
05233                                    110,-110,0,
05234                                    110,-110,0);
05235    TProfile2D *p2 = new TProfile2D("merge2DDiff-p2","p2-Title",
05236                                    220,0,110,
05237                                    220,0,110);
05238    TProfile2D *p3 = new TProfile2D("merge2DDiff-p3","p3-Title",
05239                                    330,-55,55,
05240                                    330,-55,55);
05241    TProfile2D *p4 = new TProfile2D("merge2DDiff-p4","p4-Title",
05242                                    220,-110,110,
05243                                    220,-110,110);
05244 
05245    for ( Int_t e = 0; e < nEvents; ++e ) {
05246       Double_t x = r.Gaus(-55,10);
05247       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05248       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05249       p1->Fill(x, y, z, 1.0);
05250       p4->Fill(x, y, z, 1.0);
05251    }
05252 
05253    for ( Int_t e = 0; e < nEvents; ++e ) {
05254       Double_t x = r.Gaus(55,10);
05255       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05256       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05257       p2->Fill(x, y, z, 1.0);
05258       p4->Fill(x, y, z, 1.0);
05259    }
05260 
05261    for ( Int_t e = 0; e < nEvents; ++e ) {
05262       Double_t x = r.Gaus(0,10);
05263       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05264       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05265       p3->Fill(x, y, z, 1.0);
05266       p4->Fill(x, y, z, 1.0);
05267    }
05268 
05269    TList *list = new TList;
05270    list->Add(p2);
05271    list->Add(p3);
05272 
05273    p1->Merge(list);
05274 
05275    bool ret = equals("MergeDiff2DProf", p1, p4, cmpOptStats, 1E-10);
05276    delete p1;
05277    delete p2;
05278    delete p3;
05279    return ret;
05280 }
05281 
05282 bool testMergeProf3DDiff() 
05283 {
05284    // Tests the merge method with different binned 3D Profile
05285 
05286    // This tests fails! Segmentation Fault!!It should not!
05287    TProfile3D *p1 = new TProfile3D("merge3DDiff-p1","p1-Title",
05288                                    110,-110,0,
05289                                    110,-110,0,
05290                                    110,-110,0);
05291    TProfile3D *p2 = new TProfile3D("merge3DDiff-p2","p2-Title",
05292                                    220,0,110,
05293                                    220,0,110,
05294                                    220,0,110);
05295    TProfile3D *p3 = new TProfile3D("merge3DDiff-p3","p3-Title",
05296                                    330,-55,55,
05297                                    330,-55,55,
05298                                    330,-55,55);
05299    TProfile3D *p4 = new TProfile3D("merge3DDiff-p4","p4-Title",
05300                                    220,-110,110,
05301                                    220,-110,110,
05302                                    220,-110,110);
05303 
05304    for ( Int_t e = 0; e < nEvents; ++e ) {
05305       Double_t x = r.Gaus(-55,10);
05306       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05307       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05308       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05309       p1->Fill(x, y, z, t, 1.0);
05310       p4->Fill(x, y, z, t, 1.0);
05311    }
05312 
05313    for ( Int_t e = 0; e < nEvents; ++e ) {
05314       Double_t x = r.Gaus(55,10);
05315       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05316       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05317       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05318       p2->Fill(x, y, z, t, 1.0);
05319       p4->Fill(x, y, z, t, 1.0);
05320    }
05321 
05322    for ( Int_t e = 0; e < nEvents; ++e ) {
05323       Double_t x = r.Gaus(0,10);
05324       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05325       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05326       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05327       p3->Fill(x, y, z, t, 1.0);
05328       p4->Fill(x, y, z, t, 1.0);
05329    }
05330 
05331    TList *list = new TList;
05332    list->Add(p2);
05333    list->Add(p3);
05334 
05335    p1->Merge(list);
05336 
05337    bool ret = equals("MergeDiff3DProf", p1, p4, cmpOptStats, 1E-10);
05338    delete p1;
05339    delete p2;
05340    delete p3;
05341    return ret;
05342 }
05343 
05344 bool testLabel()
05345 {
05346    // Tests labelling a 1D Histogram
05347 
05348    TH1D* h1 = new TH1D("lD1-h1", "h1-Title", numberOfBins, minRange, maxRange);
05349    TH1D* h2 = new TH1D("lD1-h2", "h2-Title", numberOfBins, minRange, maxRange);
05350 
05351    for ( Int_t bin = 1; bin <= h1->GetNbinsX() ; ++bin ) {
05352       ostringstream label;
05353       label << bin;
05354       h2->GetXaxis()->SetBinLabel(bin, label.str().c_str());
05355    }
05356 
05357    for ( Int_t e = 0; e < nEvents; ++e ) {
05358       Double_t value = r.Uniform(minRange, maxRange);
05359       Int_t bin = h1->GetXaxis()->FindBin(value);
05360       h1->Fill(h1->GetXaxis()->GetBinCenter(bin), 1.0);
05361 
05362       ostringstream label;
05363       label << bin;
05364       h2->Fill(label.str().c_str(), 1.0);
05365    }
05366 
05367    bool status = equals("Fill(char*)", h1, h2, cmpOptStats, 1E-13);
05368    delete h1;
05369    return status;
05370 }
05371 
05372 bool testLabelsInflateProf1D()
05373 {
05374    // Tests labelling a 1D Profile
05375 
05376    Int_t numberOfInflates=4;
05377    Int_t numberOfFills = numberOfBins;
05378    Double_t maxRangeInflate = maxRange;
05379    for ( Int_t i = 0; i < numberOfInflates; ++i )
05380    {
05381       numberOfFills *= 2;
05382       maxRangeInflate = 2*maxRangeInflate - 1;
05383    }
05384       
05385 
05386    TProfile* p1 = new TProfile("tLI1D-p1", "p1-Title", numberOfBins, minRange, maxRange);
05387    TProfile* p2 = new TProfile("tLI1D-p2", "p2-Title", numberOfFills, minRange, maxRangeInflate);
05388 
05389    p1->GetXaxis()->SetTimeDisplay(1);
05390 
05391    for ( Int_t e = 0; e < numberOfFills; ++e ) {
05392       Double_t x = e;
05393       Double_t y = sin(x/10);
05394 
05395       p1->SetBinContent(int(x+0.5)+1, y );
05396       p1->SetBinEntries(int(x+0.5)+1, 10.0);
05397 
05398       p2->SetBinContent(int(x+0.5)+1, y );
05399       p2->SetBinEntries(int(x+0.5)+1, 10.0);
05400    }
05401 
05402    bool ret = equals("LabelsInflateProf1D", p1, p2);
05403    delete p1;
05404    return ret;
05405 }
05406 
05407 Double_t function1D(Double_t x)
05408 {
05409    Double_t a = -1.8;
05410 
05411    return a * x;
05412 }
05413 
05414 bool testInterpolation1D() 
05415 {
05416    // Tests interpolation method for 1D Histogram
05417 
05418    bool status = false;
05419 
05420    TH1D* h1 = new TH1D("h1", "h1", 
05421                        numberOfBins, minRange, maxRange);
05422    
05423    h1->Reset();
05424 
05425    for ( Int_t nbinsx = 1; nbinsx <= h1->GetXaxis()->GetNbins(); ++nbinsx ) {
05426       Double_t x = h1->GetXaxis()->GetBinCenter(nbinsx);
05427       h1->Fill(x, function1D(x));
05428    }
05429    
05430    int itest = 0;
05431    for (itest = 0; itest < 1000; ++itest) { 
05432       double xp = r.Uniform( h1->GetXaxis()->GetBinCenter(1), h1->GetXaxis()->GetBinCenter(numberOfBins) ); 
05433       
05434       double ip = h1->Interpolate(xp); 
05435      
05436       if (  fabs(ip  - function1D(xp) ) > 1.E-13*fabs(ip) ) {
05437          status = true;
05438          cout << "x: " << xp 
05439               << " h3->Inter: " << ip
05440               << " functionD: " << function1D(xp)
05441               << " diff: " << fabs(ip  - function1D(xp))
05442               << endl;
05443       }
05444    }
05445 
05446    delete h1;
05447    if ( defaultEqualOptions & cmpOptPrint ) cout << "testInterpolation1D: \t" << (status?"FAILED":"OK") << endl;
05448    return status; 
05449 }
05450 
05451 bool testInterpolationVar1D() 
05452 {
05453    // Tests interpolation method for 1D Histogram with variable bin size
05454 
05455    Double_t v[numberOfBins+1];
05456    FillVariableRange(v);
05457 
05458    bool status = false;
05459 
05460    TH1D* h1 = new TH1D("h1", "h1", numberOfBins, v);
05461    
05462    h1->Reset();
05463 
05464    for ( Int_t nbinsx = 1; nbinsx <= h1->GetXaxis()->GetNbins(); ++nbinsx ) {
05465       Double_t x = h1->GetXaxis()->GetBinCenter(nbinsx);
05466       h1->Fill(x, function1D(x));
05467    }
05468    
05469    int itest = 0;
05470    for (itest = 0; itest < 1000; ++itest) { 
05471       double xp = r.Uniform( h1->GetXaxis()->GetBinCenter(1), h1->GetXaxis()->GetBinCenter(numberOfBins) ); 
05472       
05473       double ip = h1->Interpolate(xp); 
05474      
05475       if (  fabs(ip  - function1D(xp) ) > 1.E-13*fabs(ip) ) {
05476          status = true;
05477          cout << "x: " << xp 
05478               << " h3->Inter: " << ip
05479               << " functionD: " << function1D(xp)
05480               << " diff: " << fabs(ip  - function1D(xp))
05481               << endl;
05482       }
05483    }
05484 
05485    delete h1;
05486    if ( defaultEqualOptions & cmpOptPrint ) cout << "testInterpolaVar1D: \t" << (status?"FAILED":"OK") << endl;
05487    return status; 
05488 }
05489 
05490 Double_t function2D(Double_t x, Double_t y)
05491 {
05492    Double_t a = -2.1;
05493    Double_t b = 0.6;
05494 
05495    return a * x + b * y;
05496 }
05497 
05498 bool testInterpolation2D()
05499 {
05500    // Tests interpolation method for 2D Histogram
05501 
05502    bool status = false;
05503 
05504    TH2D* h1 = new TH2D("h1", "h1", 
05505                        numberOfBins, minRange, maxRange,
05506                        2*numberOfBins, minRange, maxRange);
05507    
05508    h1->Reset();
05509 
05510    for ( Int_t nbinsx = 1; nbinsx <= h1->GetXaxis()->GetNbins(); ++nbinsx )
05511       for ( Int_t nbinsy = 1; nbinsy <= h1->GetYaxis()->GetNbins(); ++nbinsy ) {
05512             Double_t x = h1->GetXaxis()->GetBinCenter(nbinsx);
05513             Double_t y = h1->GetYaxis()->GetBinCenter(nbinsy);
05514             h1->Fill(x, y, function2D(x, y));
05515          }
05516    
05517    int itest = 0;
05518    for (itest = 0; itest < 1000; ++itest) { 
05519 
05520       double xp = r.Uniform( h1->GetXaxis()->GetBinCenter(1), h1->GetXaxis()->GetBinCenter(numberOfBins) ); 
05521       double yp = r.Uniform( h1->GetYaxis()->GetBinCenter(1), h1->GetYaxis()->GetBinCenter(numberOfBins) );
05522       
05523       double ip = h1->Interpolate(xp, yp); 
05524      
05525       if (  fabs(ip  - function2D(xp, yp) ) > 1.E-13*fabs(ip) ) {
05526          status = true;
05527          cout << "x: " << xp << " y: " << yp
05528               << " h3->Inter: " << ip
05529               << " function: " << function2D(xp, yp)
05530               << " diff: " << fabs(ip  - function2D(xp, yp))
05531               << endl;
05532       }
05533    }
05534 
05535    delete h1;
05536    if ( defaultEqualOptions & cmpOptPrint ) cout << "testInterpolation2D: \t" << (status?"FAILED":"OK") << endl;
05537    return status; 
05538 }
05539 
05540 Double_t function3D(Double_t x, Double_t y, Double_t z)
05541 {
05542 
05543    Double_t a = 0.3;
05544    Double_t b = 6;
05545    Double_t c = -2;
05546 
05547    return a * x + b * y + c * z;
05548 }
05549 
05550 bool testInterpolation3D()
05551 {
05552    // Tests interpolation method for 3D Histogram
05553 
05554    bool status = false;
05555    TH3D* h1 = new TH3D("h1", "h1", 
05556                        numberOfBins, minRange, maxRange,
05557                        2*numberOfBins, minRange, maxRange,
05558                        4*numberOfBins, minRange, maxRange);
05559    
05560    h1->Reset();
05561 
05562    for ( Int_t nbinsx = 1; nbinsx <= h1->GetXaxis()->GetNbins(); ++nbinsx )
05563       for ( Int_t nbinsy = 1; nbinsy <= h1->GetYaxis()->GetNbins(); ++nbinsy )
05564          for ( Int_t nbinsz = 1; nbinsz <= h1->GetZaxis()->GetNbins(); ++nbinsz ) {
05565             Double_t x = h1->GetXaxis()->GetBinCenter(nbinsx);
05566             Double_t y = h1->GetYaxis()->GetBinCenter(nbinsy);
05567             Double_t z = h1->GetZaxis()->GetBinCenter(nbinsz);
05568             h1->Fill(x, y, z, function3D(x, y, z));
05569          }
05570 
05571    
05572    int itest = 0;
05573    for (itest = 0; itest < 1000; ++itest) { 
05574       double xp = r.Uniform( h1->GetXaxis()->GetBinCenter(1), h1->GetXaxis()->GetBinCenter(numberOfBins) ); 
05575       double yp = r.Uniform( h1->GetYaxis()->GetBinCenter(1), h1->GetYaxis()->GetBinCenter(numberOfBins) );
05576       double zp = r.Uniform( h1->GetZaxis()->GetBinCenter(1), h1->GetZaxis()->GetBinCenter(numberOfBins) );
05577       
05578       double ip = h1->Interpolate(xp, yp, zp); 
05579       
05580       if (  fabs(ip  - function3D(xp, yp, zp) ) > 1.E-15*fabs(ip) ) 
05581          status = true;
05582    }
05583 
05584    delete h1;
05585 
05586    if ( defaultEqualOptions & cmpOptPrint ) cout << "testInterpolation3D: \t" << (status?"FAILED":"OK") << endl;
05587 
05588    return status; 
05589 }
05590 
05591 bool testScale1DProf()
05592 {
05593    TProfile* p1 = new TProfile("scD1-p1", "p1-Title", numberOfBins, minRange, maxRange);
05594    TProfile* p2 = new TProfile("scD1-p2", "p2=c1*p1", numberOfBins, minRange, maxRange);
05595 
05596    Double_t c1 = r.Rndm();
05597 
05598    for ( Int_t e = 0; e < nEvents; ++e ) {
05599       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05600       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05601       p1->Fill(x,      y, 1.0);
05602       p2->Fill(x, c1 * y, 1.0);
05603    }
05604 
05605    p1->Scale(c1);
05606 
05607    int status = equals("testScale Prof 1D", p1, p2, cmpOptStats);
05608    delete p1;
05609    return status;
05610 }
05611 
05612 bool testScale2DProf()
05613 {
05614    TProfile2D* p1 = new TProfile2D("scD2-p1", "p1", 
05615                                    numberOfBins, minRange, maxRange,
05616                                    numberOfBins + 2, minRange, maxRange);
05617 
05618    TProfile2D* p2 = new TProfile2D("scD2-p2", "p2=c1*p1", 
05619                                    numberOfBins, minRange, maxRange,
05620                                    numberOfBins + 2, minRange, maxRange);
05621    Double_t c1 = r.Rndm();
05622 
05623    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
05624       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05625       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05626       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05627       p1->Fill(x, y, z     , 1.0);
05628       p2->Fill(x, y, c1 * z, 1.0);
05629    }
05630 
05631    p1->Scale(c1);
05632 
05633    int status = equals("testScale Prof 2D", p1, p2, cmpOptStats);
05634    delete p1;
05635    return status;
05636 }
05637 
05638 bool testScale3DProf()
05639 {
05640    TProfile3D* p1 = new TProfile3D("scD3-p1", "p1", 
05641                                    numberOfBins, minRange, maxRange,
05642                                    numberOfBins + 1, minRange, maxRange,
05643                                    numberOfBins + 2, minRange, maxRange);
05644 
05645    TProfile3D* p2 = new TProfile3D("scD3-p2", "p2=c1*p1", 
05646                                    numberOfBins, minRange, maxRange,
05647                                    numberOfBins + 1, minRange, maxRange,
05648                                    numberOfBins + 2, minRange, maxRange);
05649    Double_t c1 = r.Rndm();
05650 
05651    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
05652       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05653       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05654       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05655       Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
05656       p1->Fill(x, y, z, t     , 1.0);
05657       p2->Fill(x, y, z, c1 * t, 1.0);
05658    }
05659 
05660    p1->Scale(c1);
05661 
05662    int status = equals("testScale Prof 3D", p1, p2, cmpOptStats);
05663    delete p1;
05664    return status;
05665 }
05666 
05667 bool testH1Integral() 
05668 { 
05669    int i1 = 1;
05670    int i2 = 100;
05671    
05672    int n = 10000; 
05673    TH1D * h1 = new TH1D("h1","h1",100,-5,5); 
05674    h1->FillRandom("gaus",n); 
05675 
05676   
05677    TF1 * gaus = new TF1("gaus","gaus"); 
05678    h1->Fit(gaus, "Q0");
05679 
05680    // test first nentries
05681    double err = 0;
05682    double nent = h1->IntegralAndError(0, -1, err);
05683 
05684    int iret = 0;
05685    iret |= (nent != h1->GetEntries() );
05686 
05687    double err1 = 0;
05688    double igh = h1->IntegralAndError(i1,i2,err1,"width");
05689 
05690    double x1 = h1->GetXaxis()->GetBinLowEdge(i1);
05691    double x2 = h1->GetXaxis()->GetBinUpEdge(i2);
05692 
05693    double igf = gaus->Integral(x1,x2); 
05694    double err2 = gaus->IntegralError(x1,x2);
05695 
05696 
05697    double delta = fabs( igh - igf)/ err2; 
05698 
05699    if ( defaultEqualOptions & cmpOptDebug ) {
05700       std::cout << "Estimated entries = " << nent << " +/- " << err << std::endl; 
05701       std::cout << "Histogram integral =  " << igh << " +/- " << err1 << std::endl;
05702       std::cout << "Function  integral =  " << igf << " +/- " << err2 << std::endl;
05703       std::cout << " Difference (histogram - function) in nsigma  = " <<  delta << std::endl;
05704    }
05705 
05706 
05707    iret |= (delta > 3); 
05708 
05709    if ( defaultEqualOptions & cmpOptPrint )
05710       std::cout << "Integral H1:\t" << (iret?"FAILED":"OK") << std::endl;
05711 
05712    return iret;
05713 }
05714 
05715 double gaus1d(const double *x, const double * p) { 
05716    return p[0] * TMath::Gaus( x[0], p[1], p[2] );
05717 }
05718 double gaus2d(const double *x, const double * p) { 
05719    return p[0] * TMath::Gaus( x[0], p[1], p[2] ) * TMath::Gaus( x[1], p[3], p[4] );
05720 }
05721 double gaus3d(const double *x, const double * p) { 
05722    return p[0] * TMath::Gaus( x[0], p[1], p[2] ) * TMath::Gaus( x[1], p[3], p[4] ) * TMath::Gaus( x[2], p[5], p[6] );
05723 }
05724 
05725 bool testH2Integral()
05726 { 
05727    int ix1 = 1;
05728    int ix2 = 50;
05729    int iy1 = 1;
05730    int iy2 = 50;
05731 
05732    int n = 10000; 
05733    TH2D * h2 = new TH2D("h2","h2",50,-5,5, 50, -5, 5); 
05734   
05735    TF2 * gaus = new TF2("gaus2d",gaus2d,-5,5,-5,5,5); 
05736    gaus->SetParameters(100,0,2,1.,1);
05737    h2->FillRandom("gaus2d",n);
05738    h2->Fit(gaus,"LQ0");
05739 
05740 
05741    // test first nentries
05742    double err = 0; 
05743    double nent = h2->IntegralAndError(0,-1, 0, -1, err);
05744 
05745    int iret = 0;
05746    iret |= (nent != h2->GetEntries() );
05747 
05748    double err1 = 0;
05749    double igh = h2->IntegralAndError(ix1,ix2, iy1, iy2, err1,"width");
05750 
05751    double x1 = h2->GetXaxis()->GetBinLowEdge(ix1);
05752    double x2 = h2->GetXaxis()->GetBinUpEdge(ix2);
05753    double y1 = h2->GetYaxis()->GetBinLowEdge(iy1);
05754    double y2 = h2->GetYaxis()->GetBinUpEdge(iy2);
05755 
05756    double a[2]; 
05757    double b[2]; 
05758    a[0] = x1; a[1] = y1; 
05759    b[0] = x2; b[1] = y2; 
05760    
05761    double igf = gaus->Integral(x1,x2,y1,y2);    
05762    double err2 = gaus->IntegralError(2,a,b);
05763 
05764    double delta = fabs( igh - igf)/ err1; 
05765 
05766    if ( defaultEqualOptions & cmpOptDebug ) {
05767       std::cout << "Estimated entries = " << nent << " +/- " << err << std::endl; 
05768       std::cout << "Histogram integral =  " << igh << " +/- " << err1 << std::endl;
05769       std::cout << "Function  integral =  " << igf << " +/- " << err2 << std::endl;
05770       std::cout << " Difference (histogram - function) in nsigma  = " <<  delta << std::endl;
05771    }
05772 
05773    iret |= (delta > 3); 
05774 
05775    if ( defaultEqualOptions & cmpOptPrint )
05776       std::cout << "Integral H2:\t" << (iret?"FAILED":"OK") << std::endl;
05777    return iret;
05778 
05779 }
05780 
05781 bool testH3Integral()
05782 { 
05783    int ix1 = 1;
05784    int ix2 = 50;
05785    int iy1= 1;
05786    int iy2 = 50;
05787    int iz1 = 1;
05788    int iz2 = 50;
05789 
05790    TStopwatch w; 
05791    int n = 1000000; 
05792    TH3D * h3 = new TH3D("h3","h3",50,-5,5, 50, -5, 5, 50, -5, 5); 
05793   
05794    TF3 * gaus = new TF3("gaus3d",gaus3d,-5,5,-5,5,-5,5,7); 
05795    gaus->SetParameters(100,0,2,1.,2,-1,1);
05796    w.Start(); 
05797    h3->FillRandom("gaus3d",n);
05798 
05799    //gaus->SetParameter(0, h3->GetMaximum() );
05800 
05801    w.Stop(); 
05802    if ( defaultEqualOptions & cmpOptDebug )
05803       std::cout << "Time to fill random " << w.RealTime() << std::endl;
05804    w.Start(); 
05805    h3->Fit(gaus,"LQ0");
05806    if ( defaultEqualOptions & cmpOptDebug )
05807       std::cout << "Time to fit         " << w.RealTime() << std::endl;
05808 
05809 
05810    // test first nentries
05811    double err = 0;
05812    w.Start(); 
05813    double nent = h3->IntegralAndError(0, -1, 0, -1, 0, -1, err);
05814    w.Stop();
05815    if ( defaultEqualOptions & cmpOptDebug ) {
05816       std::cout << "Estimated entries = " << nent << " +/- " << err << std::endl; 
05817       std::cout << "Time to integral of all  " << w.RealTime() << std::endl;
05818    }
05819 
05820    int iret = 0;
05821    iret |= (nent != h3->GetEntries() );
05822 
05823    double err1 = 0;
05824    w.Start();
05825    double igh = h3->IntegralAndError(ix1,ix2, iy1, iy2, iz1, iz2, err1,"width");
05826    w.Stop();    
05827    if ( defaultEqualOptions & cmpOptDebug ) 
05828       std::cout << "Time to integral of selected  " << w.RealTime() << std::endl;
05829    
05830    double x1 = h3->GetXaxis()->GetBinLowEdge(ix1);
05831    double x2 = h3->GetXaxis()->GetBinUpEdge(ix2);
05832    double y1 = h3->GetYaxis()->GetBinLowEdge(iy1);
05833    double y2 = h3->GetYaxis()->GetBinUpEdge(iy2);
05834    double z1 = h3->GetZaxis()->GetBinLowEdge(iz1);
05835    double z2 = h3->GetZaxis()->GetBinUpEdge(iz2);
05836 
05837    double a[3]; 
05838    double b[3]; 
05839    a[0] = x1; a[1] = y1; a[2] = z1;  
05840    b[0] = x2; b[1] = y2; b[2] = z2; 
05841 
05842    w.Start();
05843    double igf = gaus->Integral(x1,x2,y1,y2,z1,z2); 
05844    double err2 = gaus->IntegralError(3,a,b);
05845    w.Stop();    
05846 
05847    double delta = fabs( igh - igf)/ err1; 
05848 
05849    if ( defaultEqualOptions & cmpOptDebug ) {
05850       std::cout << "Time to function integral   " << w.RealTime() << std::endl;
05851       std::cout << "Histogram integral =  " << igh << " +/- " << err1 << std::endl;
05852       std::cout << "Function  integral =  " << igf << " +/- " << err2 << std::endl;
05853       std::cout << " Difference (histogram - function) in nsigma  = " <<  delta << std::endl;
05854    }
05855    
05856    iret |= (delta > 3); 
05857    
05858    if ( defaultEqualOptions & cmpOptPrint )
05859       std::cout << "Integral H3:\t" << (iret?"FAILED":"OK") << std::endl;                                                                               
05860    return iret;
05861 }
05862 
05863 bool testConversion1D()
05864 {
05865    const int nbins[3] = {50,11,12};
05866    const double minRangeArray[3] = {2.,4.,4.};
05867    const double maxRangeArray[3] = {5.,8.,10.};
05868    
05869    const int nevents = 500;
05870 
05871    TF1* f = new TF1("gaus1D", gaus1d, minRangeArray[0], maxRangeArray[0], 3);
05872    f->SetParameters(10., 3.5, .4);
05873 
05874    TH1 *h1c = new TH1C("h1c", "h1-title", nbins[0], minRangeArray[0], maxRangeArray[0]);
05875    TH1 *h1s = new TH1S("h1s", "h1-title", nbins[0], minRangeArray[0], maxRangeArray[0]);
05876    TH1 *h1i = new TH1I("h1i", "h1-title", nbins[0], minRangeArray[0], maxRangeArray[0]);
05877    TH1 *h1f = new TH1F("h1f", "h1-title", nbins[0], minRangeArray[0], maxRangeArray[0]);
05878    TH1 *h1d = new TH1D("h1d", "h1-title", nbins[0], minRangeArray[0], maxRangeArray[0]);
05879 
05880    h1c->FillRandom("gaus1D", nevents);
05881    h1s->FillRandom("gaus1D", nevents);
05882    h1i->FillRandom("gaus1D", nevents);
05883    h1f->FillRandom("gaus1D", nevents);
05884    h1d->FillRandom("gaus1D", nevents);
05885 
05886    THnSparse* s1c = THnSparse::CreateSparse("s1c", "s1cTitle", h1c);
05887    THnSparse* s1s = THnSparse::CreateSparse("s1s", "s1sTitle", h1s);
05888    THnSparse* s1i = THnSparse::CreateSparse("s1i", "s1iTitle", h1i);
05889    THnSparse* s1f = THnSparse::CreateSparse("s1f", "s1fTitle", h1f);
05890    THnSparse* s1d = THnSparse::CreateSparse("s1d", "s1dTitle", h1d);
05891 
05892    int status = 0;
05893    status += equals("TH1-THnSparseC", s1c, h1c);
05894    status += equals("TH1-THnSparseS", s1s, h1s);
05895    status += equals("TH1-THnSparseI", s1i, h1i);
05896    status += equals("TH1-THnSparseF", s1f, h1f);
05897    status += equals("TH1-THnSparseD", s1d, h1d);
05898 
05899    delete s1c;
05900    delete s1s;
05901    delete s1i;
05902    delete s1f;
05903    delete s1d;
05904 
05905    return status;
05906 }
05907 
05908 bool testConversion2D()
05909 {
05910    const int nbins[3] = {50,11,12};
05911    const double minRangeArray[3] = {2.,4.,4.};
05912    const double maxRangeArray[3] = {5.,8.,10.};
05913    
05914    const int nevents = 500;
05915 
05916    TF2* f = new TF2("gaus2D", gaus2d,
05917                     minRangeArray[0], maxRangeArray[0], 
05918                     minRangeArray[1], maxRangeArray[1],
05919                     5);
05920    f->SetParameters(10., 3.5, .4, 6, 1);
05921 
05922    TH2 *h2c = new TH2C("h2c", "h2-title", 
05923                        nbins[0], minRangeArray[0], maxRangeArray[0],
05924                        nbins[1], minRangeArray[1], maxRangeArray[1]);
05925                        
05926    TH2 *h2s = new TH2S("h2s", "h2-title", 
05927                        nbins[0], minRangeArray[0], maxRangeArray[0],
05928                        nbins[1], minRangeArray[1], maxRangeArray[1]);
05929    TH2 *h2i = new TH2I("h2i", "h2-title", 
05930                        nbins[0], minRangeArray[0], maxRangeArray[0],
05931                        nbins[1], minRangeArray[1], maxRangeArray[1]);
05932    TH2 *h2f = new TH2F("h2f", "h2-title", 
05933                        nbins[0], minRangeArray[0], maxRangeArray[0],
05934                        nbins[1], minRangeArray[1], maxRangeArray[1]);
05935    TH2 *h2d = new TH2D("h2d", "h2-title", 
05936                        nbins[0], minRangeArray[0], maxRangeArray[0],
05937                        nbins[1], minRangeArray[1], maxRangeArray[1]);
05938 
05939    h2c->FillRandom("gaus2D", nevents);
05940    h2s->FillRandom("gaus2D", nevents);
05941    h2i->FillRandom("gaus2D", nevents);
05942    h2f->FillRandom("gaus2D", nevents);
05943    h2d->FillRandom("gaus2D", nevents);
05944 
05945    THnSparse* s2c = THnSparse::CreateSparse("s2c", "s2cTitle", h2c);
05946    THnSparse* s2s = THnSparse::CreateSparse("s2s", "s2sTitle", h2s);
05947    THnSparse* s2i = THnSparse::CreateSparse("s2i", "s2iTitle", h2i);
05948    THnSparse* s2f = THnSparse::CreateSparse("s2f", "s2fTitle", h2f);
05949    THnSparse* s2d = THnSparse::CreateSparse("s2d", "s2dTitle", h2d);
05950 
05951    int status = 0;
05952    status += equals("TH2-THnSparseC", s2c, h2c);
05953    status += equals("TH2-THnSparseS", s2s, h2s);
05954    status += equals("TH2-THnSparseI", s2i, h2i);
05955    status += equals("TH2-THnSparseF", s2f, h2f);
05956    status += equals("TH2-THnSparseD", s2d, h2d);
05957 
05958    delete s2c;
05959    delete s2s;
05960    delete s2i;
05961    delete s2f;
05962    delete s2d;
05963 
05964    return status;
05965 }
05966 
05967 bool testConversion3D()
05968 {
05969    const int nbins[3] = {50,11,12};
05970    const double minRangeArray[3] = {2.,4.,4.};
05971    const double maxRangeArray[3] = {5.,8.,10.};
05972    
05973    const int nevents = 500;
05974 
05975    TF3* f = new TF3("gaus3D", gaus3d,
05976                     minRangeArray[0], maxRangeArray[0], 
05977                     minRangeArray[1], maxRangeArray[1],
05978                     minRangeArray[2], maxRangeArray[2],
05979                     7);
05980    f->SetParameters(10., 3.5, .4, 6, 1, 7, 2);
05981 
05982    TH3 *h3c = new TH3C("h3c", "h3-title", 
05983                        nbins[0], minRangeArray[0], maxRangeArray[0],
05984                        nbins[1], minRangeArray[1], maxRangeArray[1],
05985                        nbins[2], minRangeArray[2], maxRangeArray[2]);
05986                        
05987    TH3 *h3s = new TH3S("h3s", "h3-title", 
05988                        nbins[0], minRangeArray[0], maxRangeArray[0],
05989                        nbins[1], minRangeArray[1], maxRangeArray[1],
05990                        nbins[2], minRangeArray[2], maxRangeArray[2]);
05991    TH3 *h3i = new TH3I("h3i", "h3-title", 
05992                        nbins[0], minRangeArray[0], maxRangeArray[0],
05993                        nbins[1], minRangeArray[1], maxRangeArray[1],
05994                        nbins[2], minRangeArray[2], maxRangeArray[2]);
05995    TH3 *h3f = new TH3F("h3f", "h3-title", 
05996                        nbins[0], minRangeArray[0], maxRangeArray[0],
05997                        nbins[1], minRangeArray[1], maxRangeArray[1],
05998                        nbins[2], minRangeArray[2], maxRangeArray[2]);
05999    TH3 *h3d = new TH3D("h3d", "h3-title", 
06000                        nbins[0], minRangeArray[0], maxRangeArray[0],
06001                        nbins[1], minRangeArray[1], maxRangeArray[1],
06002                        nbins[2], minRangeArray[2], maxRangeArray[2]);
06003 
06004    h3c->FillRandom("gaus3D", nevents);
06005    h3s->FillRandom("gaus3D", nevents);
06006    h3i->FillRandom("gaus3D", nevents);
06007    h3f->FillRandom("gaus3D", nevents);
06008    h3d->FillRandom("gaus3D", nevents);
06009 
06010    THnSparse* s3c = THnSparse::CreateSparse("s3c", "s3cTitle", h3c);
06011    THnSparse* s3s = THnSparse::CreateSparse("s3s", "s3sTitle", h3s);
06012    THnSparse* s3i = THnSparse::CreateSparse("s3i", "s3iTitle", h3i);
06013    THnSparse* s3f = THnSparse::CreateSparse("s3f", "s3fTitle", h3f);
06014    THnSparse* s3d = THnSparse::CreateSparse("s3d", "s3dTitle", h3d);
06015 
06016    int status = 0;
06017    status += equals("TH3-THnSparseC", s3c, h3c);
06018    status += equals("TH3-THnSparseS", s3s, h3s);
06019    status += equals("TH3-THnSparseI", s3i, h3i);
06020    status += equals("TH3-THnSparseF", s3f, h3f);
06021    status += equals("TH3-THnSparseD", s3d, h3d);
06022 
06023    delete s3c;
06024    delete s3s;
06025    delete s3i;
06026    delete s3f;
06027    delete s3d;
06028 
06029    return status;
06030 }
06031 
06032 int findBin(ROOT::Fit::BinData& bd, const double *x)
06033 {
06034    const unsigned int ndim = bd.NDim();
06035    const unsigned int npoints = bd.NPoints();
06036 
06037    for ( unsigned int i = 0; i < npoints; ++i )
06038    {
06039       double value1, error1;
06040       const double *x1 = bd.GetPoint(i, value1, error1);
06041 
06042 //       cout << "\ti: " << i
06043 //            << " x: ";
06044 //       std::copy(x1, x1+ndim, ostream_iterator<double>(cout, " "));
06045 //       cout << " val: " << value1
06046 //            << " error: " << error1
06047 //            << endl;
06048 
06049       bool thisIsIt = true;
06050       for ( unsigned int j = 0; j < ndim; ++j )
06051       {
06052          thisIsIt &= fabs(x1[j] - x[j]) < 1E-15;
06053       }
06054       if ( thisIsIt ) { 
06055 //          cout << "RETURNED!" << endl;
06056          return i; 
06057       }
06058    }
06059 
06060 //    cout << "ERROR FINDING BIN!" << endl;
06061    return -1;
06062 }
06063 
06064 bool operator ==(ROOT::Fit::BinData& bd1, ROOT::Fit::BinData& bd2)
06065 {
06066    const unsigned int ndim = bd1.NDim();
06067    const unsigned int npoints = bd1.NPoints();
06068 
06069    bool equals = true;
06070 
06071    for ( unsigned int i = 0; i < npoints && equals; ++i )
06072    {
06073       double value1, error1;
06074       const double *x1 = bd1.GetPoint(i, value1, error1);
06075 
06076 //       cout << "i: " << i
06077 //            << " x: ";
06078 //       std::copy(x1, x1+ndim, ostream_iterator<double>(cout, " "));
06079 //       cout << " val: " << value1
06080 //            << " error: " << error1
06081 //            << endl;
06082 
06083       int bin = findBin(bd2, x1);
06084       if ( bin < 0 )
06085          Fatal("operator ==(ROOT::Fit::BinData& bd1, ROOT::Fit::BinData& bd2)","BIN NOT FOUND!");
06086 
06087       double value2 = 0, error2;
06088       const double *x2 = bd2.GetPoint(bin, value2, error2);
06089 
06090       equals &= ( value1 == value2 );
06091       equals &= ( error1 == error2 );
06092       for ( unsigned int j = 0; j < ndim; ++j )
06093       {
06094          equals &= fabs(x1[j] - x2[j]) < 1E-15;
06095       }
06096    }
06097 
06098    return equals;   
06099 }
06100 
06101 
06102 int findBin(ROOT::Fit::SparseData& sd, 
06103             const vector<double>& minRef, const vector<double>& maxRef,
06104             const double valRef, const double errorRef)
06105 {
06106    const unsigned int ndim = sd.NDim();
06107    const unsigned int npoints = sd.NPoints();
06108 
06109    for ( unsigned int i = 0; i < npoints; ++i )
06110    {
06111       vector<double> min(ndim);
06112       vector<double> max(ndim);
06113       double val;
06114       double error;
06115       sd.GetPoint(i, min, max, val, error);
06116 
06117 //       cout << "\ti: " << i
06118 //            << " min: ";
06119 //       std::copy(min.begin(), min.end(), ostream_iterator<double>(cout, " "));
06120 //       cout << " max: ";
06121 //       std::copy(max.begin(), max.end(), ostream_iterator<double>(cout, " "));
06122 //       cout << " val: " << val
06123 //            << " error: " << error
06124 //            << endl;
06125 
06126       bool thisIsIt = true;
06127 //       cout << "\t\t" << thisIsIt << " ";
06128       thisIsIt &= !equals(valRef, val, 1E-8);
06129 //       cout << thisIsIt << " ";
06130       thisIsIt &= !equals(errorRef, error, 1E-15);
06131 //       cout << thisIsIt << " ";
06132       for ( unsigned int j = 0; j < ndim && thisIsIt; ++j )
06133       {
06134          thisIsIt &= !equals(minRef[j], min[j]);
06135 //          cout << thisIsIt << " ";
06136          thisIsIt &= !equals(maxRef[j], max[j]);
06137 //          cout << thisIsIt << " ";
06138       }
06139 //       cout << thisIsIt << " " << endl;
06140       if ( thisIsIt ) { 
06141 //          cout << "RETURNING " << i << endl; 
06142          return i; 
06143       }
06144    }
06145 
06146 //    cout << "ERROR FINDING BIN!" << endl;
06147    return -1;
06148 }
06149 bool operator ==(ROOT::Fit::SparseData& sd1, ROOT::Fit::SparseData& sd2)
06150 {
06151    const unsigned int ndim = sd1.NDim();
06152 
06153    const unsigned int npoints1 = sd1.NPoints();
06154    const unsigned int npoints2 = sd2.NPoints();
06155 
06156    bool equals = (npoints1 == npoints2);
06157 
06158    for ( unsigned int i = 0; i < npoints1 && equals; ++i )
06159    {
06160       vector<double> min(ndim);
06161       vector<double> max(ndim);
06162       double val;
06163       double error;
06164       sd1.GetPoint(i, min, max, val, error);
06165 
06166       equals &= (findBin(sd2, min, max, val, error) >= 0 );
06167    }
06168 
06169    for ( unsigned int i = 0; i < npoints2 && equals; ++i )
06170    {
06171       vector<double> min(ndim);
06172       vector<double> max(ndim);
06173       double val;
06174       double error;
06175       sd2.GetPoint(i, min, max, val, error);
06176 
06177       equals &= (findBin(sd1, min, max, val, error) >= 0 );
06178    }
06179 
06180    return equals;     
06181 }
06182 
06183 bool testSparseData1DFull()
06184 {
06185    TF1* func = new TF1( "GAUS", gaus1d, minRange, maxRange, 3);
06186    func->SetParameters(0.,  3., 200.);
06187    func->SetParLimits( 1, 0, 5 );
06188 
06189    TH1D* h1 = new TH1D("fsdf1D","h1-title",numberOfBins,minRange,maxRange);
06190    for ( Int_t e = 0; e < nEvents; ++e ) {
06191       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06192       h1->Fill(value,  1.0);
06193    }
06194 
06195    THnSparse* s1 = THnSparse::CreateSparse("fsdf1Ds", "THnSparse 1D - title", h1);
06196 
06197    unsigned int const dim = 1;
06198    double min[dim] = {minRange};
06199    double max[dim] = {maxRange};
06200    ROOT::Fit::SparseData spTH1(dim, min,max);
06201    ROOT::Fit::FillData(spTH1,h1, 0);
06202 
06203    ROOT::Fit::SparseData spSparse(dim, min,max);
06204    ROOT::Fit::FillData(spSparse,s1, 0);
06205 
06206    int status = 1;
06207    if ( (spTH1 == spSparse ) &&
06208         (spSparse == spTH1 ) )
06209       status = 0;
06210 
06211    delete func;
06212    delete h1;
06213    delete s1;
06214 
06215    if ( defaultEqualOptions & cmpOptPrint ) cout << "testSparseData1DFull: \t" << (status?"FAILED":"OK") << endl;
06216    return status;
06217 }
06218 
06219 bool testSparseData1DSparse()
06220 {
06221    TF1* func = new TF1( "GAUS", gaus1d, minRange, maxRange, 3);
06222    func->SetParameters(0.,  3., 200.);
06223    func->SetParLimits( 1, 0, 5 );
06224 
06225    TH1D* h1 = new TH1D("fsds1D","h1-title",numberOfBins,minRange,maxRange);
06226    for ( Int_t e = 0; e < numberOfBins; ++e ) {
06227       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06228       h1->Fill(value,  1.0);
06229    }
06230 
06231    THnSparse* s1 = THnSparse::CreateSparse("fsds1Ds", "THnSparse 1D - title", h1);
06232 
06233    unsigned int const dim = 1;
06234    double min[dim] = {minRange};
06235    double max[dim] = {maxRange};
06236    ROOT::Fit::SparseData spTH1(dim, min,max);
06237    ROOT::Fit::FillData(spTH1,h1, 0);
06238 
06239    ROOT::Fit::SparseData spSparse(dim, min,max);
06240    ROOT::Fit::FillData(spSparse,s1, 0);
06241 
06242    int status = 1;
06243    if ( (spTH1 == spSparse ) &&
06244         (spSparse == spTH1 ) )
06245       status = 0;
06246 
06247    delete func;
06248    delete h1;
06249    delete s1;
06250 
06251    if ( defaultEqualOptions & cmpOptPrint ) cout << "testSparseData1DSpar: \t" << (status?"FAILED":"OK") << endl;
06252    return status;
06253 }
06254 
06255 bool testSparseData2DFull()
06256 {
06257    TF2* func = new TF2( "GAUS2D", gaus2d, minRange, maxRange, 3);
06258    func->SetParameters(500., +.5, 1.5, -.5, 2.0);
06259 
06260    TH2D* h2 = new TH2D("fsdf2D","h2-title",
06261                        numberOfBins,minRange,maxRange,
06262                        numberOfBins,minRange,maxRange);
06263    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06264       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06265       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06266       h2->Fill(x, y, 1.0);
06267    }
06268 
06269    THnSparse* s2 = THnSparse::CreateSparse("fsdf2Ds", "THnSparse 2D - title", h2);
06270 
06271    unsigned int const dim = 1;
06272    double min[dim] = {minRange};
06273    double max[dim] = {maxRange};
06274    ROOT::Fit::SparseData spTH2(dim, min,max);
06275    ROOT::Fit::FillData(spTH2,h2, 0);
06276 
06277    ROOT::Fit::SparseData spSparse(dim, min,max);
06278    ROOT::Fit::FillData(spSparse,s2, 0);
06279 
06280    int status = 1;
06281    if ( (spTH2 == spSparse ) &&
06282         (spSparse == spTH2 ) )
06283       status = 0;
06284 
06285    delete func;
06286    delete h2;
06287    delete s2;
06288 
06289    if ( defaultEqualOptions & cmpOptPrint ) cout << "testSparseData2DFull: \t" << (status?"FAILED":"OK") << endl;
06290    return status;
06291 }
06292 
06293 bool testSparseData2DSparse()
06294 {
06295    TF2* func = new TF2( "GAUS2D", gaus2d, minRange, maxRange, 3);
06296    func->SetParameters(500., +.5, 1.5, -.5, 2.0);
06297 
06298    TH2D* h2 = new TH2D("fsds2D","h2-title",
06299                        numberOfBins,minRange,maxRange,
06300                        numberOfBins,minRange,maxRange);
06301    for ( Int_t e = 0; e < numberOfBins * numberOfBins; ++e ) {
06302       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06303       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06304       h2->Fill(x, y, 1.0);
06305    }
06306 
06307    THnSparse* s2 = THnSparse::CreateSparse("fsds2Ds", "THnSparse 2D - title", h2);
06308 
06309    unsigned int const dim = 1;
06310    double min[dim] = {minRange};
06311    double max[dim] = {maxRange};
06312    ROOT::Fit::SparseData spTH2(dim, min,max);
06313    ROOT::Fit::FillData(spTH2,h2, 0);
06314 
06315    ROOT::Fit::SparseData spSparse(dim, min,max);
06316    ROOT::Fit::FillData(spSparse,s2, 0);
06317 
06318    int status = 1;
06319    if ( (spTH2 == spSparse ) &&
06320         (spSparse == spTH2 ) )
06321       status = 0;
06322 
06323    delete func;
06324    delete h2;
06325    delete s2;
06326 
06327    if ( defaultEqualOptions & cmpOptPrint ) cout << "testSparseData2DSpar: \t" << (status?"FAILED":"OK") << endl;
06328    return status;
06329 }
06330 
06331 bool testSparseData3DFull()
06332 {
06333    TF2* func = new TF2( "GAUS3D", gaus3d, minRange, maxRange, 3);
06334    func->SetParameters(500., +.5, 1.5, -.5, 2.0);
06335 
06336    TH3D* h3 = new TH3D("fsdf3D","h3-title",
06337                        numberOfBins,minRange,maxRange,
06338                        numberOfBins,minRange,maxRange,
06339                        numberOfBins,minRange,maxRange);
06340    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06341       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06342       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06343       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06344       h3->Fill(x, y, z, 1.0);
06345    }
06346 
06347    THnSparse* s3 = THnSparse::CreateSparse("fsdf3Ds", "THnSparse 3D - title", h3);
06348 
06349    unsigned int const dim = 1;
06350    double min[dim] = {minRange};
06351    double max[dim] = {maxRange};
06352    ROOT::Fit::SparseData spTH3(dim, min,max);
06353    ROOT::Fit::FillData(spTH3,h3, 0);
06354 
06355    ROOT::Fit::SparseData spSparse(dim, min,max);
06356    ROOT::Fit::FillData(spSparse,s3, 0);
06357 
06358    int status = 1;
06359    if ( (spTH3 == spSparse ) &&
06360         (spSparse == spTH3 ) )
06361       status = 0;
06362 
06363    delete func;
06364    delete h3;
06365    delete s3;
06366 
06367    if ( defaultEqualOptions & cmpOptPrint ) cout << "testSparseData3DFull: \t" << (status?"FAILED":"OK") << endl;
06368    return status;
06369 }
06370 
06371 bool testSparseData3DSparse()
06372 {
06373    TF2* func = new TF2( "GAUS3D", gaus3d, minRange, maxRange, 3);
06374    func->SetParameters(500., +.5, 1.5, -.5, 2.0);
06375 
06376    TH3D* h3 = new TH3D("fsds3D","h3-title",
06377                        numberOfBins,minRange,maxRange,
06378                        numberOfBins,minRange,maxRange,
06379                        numberOfBins,minRange,maxRange);
06380    for ( Int_t e = 0; e < numberOfBins * numberOfBins * numberOfBins; ++e ) {
06381       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06382       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06383       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06384       h3->Fill(x, y, z, 1.0);
06385    }
06386 
06387    THnSparse* s3 = THnSparse::CreateSparse("fsds3Ds", "THnSparse 3D - title", h3);
06388 
06389    unsigned int const dim = 1;
06390    double min[dim] = {minRange};
06391    double max[dim] = {maxRange};
06392    ROOT::Fit::SparseData spTH3(dim, min,max);
06393    ROOT::Fit::FillData(spTH3,h3, 0);
06394 
06395    ROOT::Fit::SparseData spSparse(dim, min,max);
06396    ROOT::Fit::FillData(spSparse,s3, 0);
06397 
06398    int status = 1;
06399    if ( (spTH3 == spSparse ) &&
06400         (spSparse == spTH3 ) )
06401       status = 0;
06402 
06403    delete func;
06404    delete h3;
06405    delete s3;
06406 
06407    if ( defaultEqualOptions & cmpOptPrint ) cout << "testSparseData3DSpar: \t" << (status?"FAILED":"OK") << endl;
06408    return status;
06409 }
06410 
06411 bool testBinDataData1D()
06412 {
06413    TF1* func = new TF1( "GAUS", gaus1d, minRange, maxRange, 3);
06414    func->SetParameters(0.,  3., 200.);
06415    func->SetParLimits( 1, 0, 5 );
06416 
06417    TH1D* h1 = new TH1D("fbd1D","h1-title",numberOfBins,minRange,maxRange);
06418    for ( Int_t e = 0; e < nEvents; ++e ) {
06419       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06420       h1->Fill(value,  1.0);
06421    }
06422 
06423    THnSparse* s1 = THnSparse::CreateSparse("fbd1Ds", "THnSparse 1D - title", h1);
06424 
06425    ROOT::Fit::BinData bdTH1;
06426    ROOT::Fit::FillData(bdTH1, h1);
06427 
06428    unsigned int const dim = 1;
06429    double min[dim] = {minRange};
06430    double max[dim] = {maxRange};
06431    ROOT::Fit::SparseData spSparseTmp(dim, min,max);
06432    ROOT::Fit::FillData(spSparseTmp,s1, 0);
06433    ROOT::Fit::BinData bdSparse;
06434    spSparseTmp.GetBinData(bdSparse);
06435 
06436 
06437    int status = 1;
06438    if ( (bdTH1 == bdSparse ) &&
06439         (bdSparse == bdTH1 ) )
06440       status = 0;
06441 
06442    delete func;
06443    delete h1;
06444    delete s1;
06445 
06446    if ( defaultEqualOptions & cmpOptPrint ) cout << "testBinDataData1D: \t" << (status?"FAILED":"OK") << endl;
06447    return status;
06448 }
06449 
06450 bool testBinDataData2D()
06451 {
06452    TF1* func = new TF1( "GAUS", gaus2d, minRange, maxRange, 3);
06453    func->SetParameters(0.,  3., 200.);
06454    func->SetParLimits( 1, 0, 5 );
06455 
06456    TH2D* h2 = new TH2D("fbd2D","h2-title",
06457                        numberOfBins,minRange,maxRange,
06458                        numberOfBins,minRange,maxRange);
06459    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06460       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06461       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06462       h2->Fill(x, y, 1.0);
06463    }
06464 
06465    THnSparse* s2 = THnSparse::CreateSparse("fbd2Ds", "THnSparse 2D - title", h2);
06466 
06467    ROOT::Fit::BinData bdTH2;
06468    ROOT::Fit::FillData(bdTH2, h2);
06469 
06470    unsigned int const dim = 2;
06471    double min[dim] = {minRange, minRange};
06472    double max[dim] = {maxRange, maxRange};
06473    ROOT::Fit::SparseData spSparseTmp(dim, min,max);
06474    ROOT::Fit::FillData(spSparseTmp,s2, 0);
06475    ROOT::Fit::BinData bdSparse(spSparseTmp.NPoints(), spSparseTmp.NDim());
06476    spSparseTmp.GetBinData(bdSparse);
06477 
06478 
06479    int status = 1;
06480    if ( (bdTH2 == bdSparse ) &&
06481         (bdSparse == bdTH2 ) )
06482       status = 0;
06483 
06484    delete func;
06485    delete h2;
06486    delete s2;
06487 
06488    if ( defaultEqualOptions & cmpOptPrint ) cout << "testBinDataData2D: \t" << (status?"FAILED":"OK") << endl;
06489    return status;
06490 }
06491 
06492 bool testBinDataData3D()
06493 {
06494    TF1* func = new TF1( "GAUS", gaus3d, minRange, maxRange, 3);
06495    func->SetParameters(0.,  3., 200.);
06496    func->SetParLimits( 1, 0, 5 );
06497 
06498    TH3D* h3 = new TH3D("fbd3D","h3-title",
06499                        numberOfBins,minRange,maxRange,
06500                        numberOfBins,minRange,maxRange,
06501                        numberOfBins,minRange,maxRange);
06502    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06503       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06504       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06505       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06506       h3->Fill(x, y, z, 1.0);
06507    }
06508 
06509    THnSparse* s3 = THnSparse::CreateSparse("fbd3Ds", "THnSparse 3D - title", h3);
06510 
06511    ROOT::Fit::BinData bdTH3;
06512    ROOT::Fit::FillData(bdTH3, h3);
06513 
06514    unsigned int const dim = 3;
06515    double min[dim] = {minRange, minRange, minRange};
06516    double max[dim] = {maxRange, maxRange, maxRange};
06517    ROOT::Fit::SparseData spSparseTmp(dim, min,max);
06518    ROOT::Fit::FillData(spSparseTmp,s3, 0);
06519    ROOT::Fit::BinData bdSparse(spSparseTmp.NPoints(), spSparseTmp.NDim());
06520    spSparseTmp.GetBinData(bdSparse);
06521 
06522 
06523    int status = 1;
06524    if ( (bdTH3 == bdSparse ) &&
06525         (bdSparse == bdTH3 ) )
06526       status = 0;
06527 
06528    delete func;
06529    delete h3;
06530    delete s3;
06531 
06532    if ( defaultEqualOptions & cmpOptPrint ) cout << "testBinDataData3D: \t" << (status?"FAILED":"OK") << endl;
06533    return status;
06534 }
06535 
06536 bool testBinDataData1DInt()
06537 {
06538    TF1* func = new TF1( "GAUS", gaus1d, minRange, maxRange, 3);
06539    func->SetParameters(0.,  3., 200.);
06540    func->SetParLimits( 1, 0, 5 );
06541 
06542    TH1D* h1 = new TH1D("fbdi1D","h1-title",numberOfBins,minRange,maxRange);
06543    for ( Int_t e = 0; e < nEvents; ++e ) {
06544       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06545       h1->Fill(value,  1.0);
06546    }
06547 
06548    THnSparse* s1 = THnSparse::CreateSparse("fbdi1Ds", "THnSparse 1D - title", h1);
06549 
06550    ROOT::Fit::DataOptions opt;
06551    opt.fUseEmpty = true;
06552    opt.fIntegral = true;
06553 
06554    ROOT::Fit::BinData bdTH1(opt);
06555    ROOT::Fit::FillData(bdTH1, h1);
06556 
06557    unsigned int const dim = 1;
06558    double min[dim] = {minRange};
06559    double max[dim] = {maxRange};
06560    ROOT::Fit::SparseData spSparseTmp(dim, min,max);
06561    ROOT::Fit::FillData(spSparseTmp,s1, 0);
06562    ROOT::Fit::BinData bdSparse;
06563    spSparseTmp.GetBinDataIntegral(bdSparse);
06564 
06565 
06566    int status = 1;
06567    if ( (bdTH1 == bdSparse ) &&
06568         (bdSparse == bdTH1 ) )
06569       status = 0;
06570 
06571    delete func;
06572    delete h1;
06573    delete s1;
06574 
06575    if ( defaultEqualOptions & cmpOptPrint ) cout << "testBinDataData1DInt: \t" << (status?"FAILED":"OK") << endl;
06576    return status;
06577 }
06578 
06579 bool testBinDataData2DInt()
06580 {
06581    TF1* func = new TF1( "GAUS", gaus2d, minRange, maxRange, 3);
06582    func->SetParameters(0.,  3., 200.);
06583    func->SetParLimits( 1, 0, 5 );
06584 
06585    TH2D* h2 = new TH2D("fbdi2D","h2-title",
06586                        numberOfBins,minRange,maxRange,
06587                        numberOfBins,minRange,maxRange);
06588    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06589       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06590       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06591       h2->Fill(x, y, 1.0);
06592    }
06593 
06594    THnSparse* s2 = THnSparse::CreateSparse("fbdi2Ds", "THnSparse 2D - title", h2);
06595 
06596    ROOT::Fit::DataOptions opt;
06597    opt.fUseEmpty = true;
06598    opt.fIntegral = true;
06599 
06600    ROOT::Fit::BinData bdTH2(opt);
06601    ROOT::Fit::FillData(bdTH2, h2);
06602 
06603    unsigned int const dim = 2;
06604    double min[dim] = {minRange, minRange};
06605    double max[dim] = {maxRange, maxRange};
06606    ROOT::Fit::SparseData spSparseTmp(dim, min,max);
06607    ROOT::Fit::FillData(spSparseTmp,s2, 0);
06608    ROOT::Fit::BinData bdSparse(spSparseTmp.NPoints(), spSparseTmp.NDim());
06609    spSparseTmp.GetBinDataIntegral(bdSparse);
06610 
06611 
06612    int status = 1;
06613    if ( (bdTH2 == bdSparse ) &&
06614         (bdSparse == bdTH2 ) )
06615       status = 0;
06616 
06617    delete func;
06618    delete h2;
06619    delete s2;
06620 
06621    if ( defaultEqualOptions & cmpOptPrint ) cout << "testBinDataData2DInt: \t" << (status?"FAILED":"OK") << endl;
06622    return status;
06623 }
06624 
06625 bool testBinDataData3DInt()
06626 {
06627    TF1* func = new TF1( "GAUS", gaus3d, minRange, maxRange, 3);
06628    func->SetParameters(0.,  3., 200.);
06629    func->SetParLimits( 1, 0, 5 );
06630 
06631    TH3D* h3 = new TH3D("fbdi3D","h3-title",
06632                        numberOfBins,minRange,maxRange,
06633                        numberOfBins,minRange,maxRange,
06634                        numberOfBins,minRange,maxRange);
06635    for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06636       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06637       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06638       Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06639       h3->Fill(x, y, z, 1.0);
06640    }
06641 
06642    THnSparse* s3 = THnSparse::CreateSparse("fbdi3Ds", "THnSparse 3D - title", h3);
06643 
06644    ROOT::Fit::DataOptions opt;
06645    opt.fUseEmpty = true;
06646    opt.fIntegral = true;
06647 
06648    ROOT::Fit::BinData bdTH3(opt);
06649    ROOT::Fit::FillData(bdTH3, h3);
06650 
06651    unsigned int const dim = 3;
06652    double min[dim] = {minRange, minRange, minRange};
06653    double max[dim] = {maxRange, maxRange, maxRange};
06654    ROOT::Fit::SparseData spSparseTmp(dim, min,max);
06655    ROOT::Fit::FillData(spSparseTmp,s3, 0);
06656    ROOT::Fit::BinData bdSparse(spSparseTmp.NPoints(), spSparseTmp.NDim());
06657    spSparseTmp.GetBinDataIntegral(bdSparse);
06658 
06659 
06660    int status = 1;
06661    if ( (bdTH3 == bdSparse ) &&
06662         (bdSparse == bdTH3 ) )
06663       status = 0;
06664 
06665    delete func;
06666    delete h3;
06667    delete s3;
06668 
06669    if ( defaultEqualOptions & cmpOptPrint ) cout << "testBinDataData3DInt: \t" << (status?"FAILED":"OK") << endl;
06670    return status;
06671 }
06672 
06673 bool testRefRead1D()
06674 {
06675    // Tests consistency with a reference file for 1D Histogram
06676 
06677    TH1D* h1 = 0;
06678    bool ret = 0;
06679    if ( refFileOption == refFileWrite ) {
06680       h1 = new TH1D("rr1D-h1", "h1-Title", numberOfBins, minRange, maxRange);
06681       h1->Sumw2();
06682    
06683       for ( Int_t e = 0; e < nEvents; ++e ) {
06684          Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06685          h1->Fill(value, 1.0);
06686       }  
06687       h1->Write();
06688    } else {
06689       h1 = static_cast<TH1D*> ( refFile->Get("rr1D-h1") );
06690       TH1D* h2 = new TH1D("rr1D-h2", "h2-Title", numberOfBins, minRange, maxRange);
06691       h2->Sumw2();
06692    
06693       for ( Int_t e = 0; e < nEvents; ++e ) {
06694          Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06695          h2->Fill(value, 1.0);
06696       }  
06697 
06698       ret = equals("Ref Read Hist 1D", h1, h2, cmpOptStats);
06699    }
06700    if ( h1 ) delete h1;
06701    return ret;
06702 
06703 }
06704 
06705 bool testRefReadProf1D()
06706 {
06707    // Tests consistency with a reference file for 1D Profile
06708 
06709    bool ret = 0;
06710    TProfile* p1 = 0;
06711    if ( refFileOption == refFileWrite ) {
06712       p1 = new TProfile("rr1D-p1", "p1-Title", numberOfBins, minRange, maxRange);
06713 //      p1->Sumw2();
06714    
06715       for ( Int_t e = 0; e < nEvents; ++e ) {
06716          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06717          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06718          p1->Fill(x, y, 1.0);
06719       }  
06720       p1->Write();
06721    } else {
06722       TH1::SetDefaultSumw2(false);
06723       p1 = static_cast<TProfile*> ( refFile->Get("rr1D-p1") );
06724       TProfile* p2 = new TProfile("rr1D-p2", "p2-Title", numberOfBins, minRange, maxRange);
06725 //      p2->Sumw2();
06726    
06727       for ( Int_t e = 0; e < nEvents; ++e ) {
06728          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06729          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06730          p2->Fill(x, y, 1.0);
06731       }  
06732 
06733       ret = equals("Ref Read Prof 1D", p1, p2, cmpOptStats);
06734       TH1::SetDefaultSumw2(true);
06735    }
06736    if (p1) delete p1;
06737    return ret;
06738 
06739 }
06740 
06741 bool testRefRead2D()
06742 {
06743    // Tests consistency with a reference file for 2D Histogram
06744 
06745    TH2D* h1 = 0;
06746    bool ret = 0;
06747    if ( refFileOption == refFileWrite ) {
06748       h1 = new TH2D("rr2D-h1", "h1-Title", 
06749                           numberOfBins, minRange, maxRange,
06750                           numberOfBins, minRange, maxRange);
06751       h1->Sumw2();
06752    
06753       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06754          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06755          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06756          h1->Fill(x, y, 1.0);
06757       }  
06758       h1->Write();
06759    } else {
06760       h1 = static_cast<TH2D*> ( refFile->Get("rr2D-h1") );
06761       TH2D* h2 = new TH2D("rr2D-h2", "h2-Title", 
06762                           numberOfBins, minRange, maxRange,
06763                           numberOfBins, minRange, maxRange);
06764       h2->Sumw2();
06765    
06766       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06767          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06768          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06769          h2->Fill(x, y, 1.0);
06770       }  
06771 
06772       ret = equals("Ref Read Hist 2D", h1, h2, cmpOptStats);
06773    }
06774    if ( h1 ) delete h1;
06775    return ret;
06776 }
06777 
06778 bool testRefReadProf2D()
06779 {
06780    // Tests consistency with a reference file for 2D Profile
06781 
06782    TProfile2D* p1 = 0;
06783    bool ret = 0;
06784    if ( refFileOption == refFileWrite ) {
06785       p1 = new TProfile2D("rr2D-p1", "p1-Title", 
06786                                       numberOfBins, minRange, maxRange,
06787                                       numberOfBins, minRange, maxRange);
06788    
06789       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06790          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06791          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06792          Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06793          p1->Fill(x, y, z, 1.0);
06794       }  
06795       p1->Write();
06796    } else {
06797       p1 = static_cast<TProfile2D*> ( refFile->Get("rr2D-p1") );
06798       TProfile2D* p2 = new TProfile2D("rr2D-p2", "p2-Title", 
06799                                       numberOfBins, minRange, maxRange,
06800                                       numberOfBins, minRange, maxRange);
06801    
06802       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06803          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06804          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06805          Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06806          p2->Fill(x, y, z, 1.0);
06807       }  
06808 
06809       ret = equals("Ref Read Prof 2D", p1, p2, cmpOptStats );
06810    }
06811    if ( p1 ) delete p1;
06812    return ret;
06813 }
06814 
06815 bool testRefRead3D()
06816 {
06817    // Tests consistency with a reference file for 3D Histogram
06818 
06819    TH3D* h1 = 0;
06820    bool ret = 0;
06821    if ( refFileOption == refFileWrite ) {
06822       h1 = new TH3D("rr3D-h1", "h1-Title", 
06823                           numberOfBins, minRange, maxRange,
06824                           numberOfBins, minRange, maxRange,
06825                           numberOfBins, minRange, maxRange);
06826       h1->Sumw2();
06827    
06828       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06829          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06830          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06831          Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06832          h1->Fill(x, y, z, 1.0);
06833       }  
06834       h1->Write();
06835    } else {
06836       h1 = static_cast<TH3D*> ( refFile->Get("rr3D-h1") );
06837       TH3D* h2 = new TH3D("rr3D-h2", "h2-Title", 
06838                           numberOfBins, minRange, maxRange,
06839                           numberOfBins, minRange, maxRange,
06840                           numberOfBins, minRange, maxRange);
06841       h2->Sumw2();
06842    
06843       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06844          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06845          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06846          Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06847          h2->Fill(x, y, z, 1.0);
06848       }  
06849 
06850       ret = equals("Ref Read Hist 3D", h1, h2, cmpOptStats);
06851    }
06852    if ( h1 ) delete h1;
06853    return ret;
06854 }
06855 
06856 bool testRefReadProf3D()
06857 {
06858    // Tests consistency with a reference file for 3D Profile
06859 
06860    TProfile3D* p1 = 0;
06861    bool ret = 0;
06862    if ( refFileOption == refFileWrite ) {
06863       p1 = new TProfile3D("rr3D-p1", "p1-Title", 
06864                           numberOfBins, minRange, maxRange,
06865                           numberOfBins, minRange, maxRange,
06866                           numberOfBins, minRange, maxRange);
06867 
06868       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06869          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06870          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06871          Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06872          Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06873          p1->Fill(x, y, z, t, 1.0);
06874       }  
06875       p1->Write();
06876    } else {
06877       p1 = static_cast<TProfile3D*> ( refFile->Get("rr3D-p1") );
06878       TProfile3D* p2 = new TProfile3D("rr3D-p2", "p2-Title", 
06879                           numberOfBins, minRange, maxRange,
06880                           numberOfBins, minRange, maxRange,
06881                           numberOfBins, minRange, maxRange);
06882 
06883       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06884          Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06885          Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06886          Double_t z = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06887          Double_t t = r.Uniform(0.9 * minRange, 1.1 * maxRange);
06888          p2->Fill(x, y, z, t, 1.0);
06889       }  
06890 
06891       ret = equals("Ref Read Prof 3D", p1, p2, cmpOptStats);
06892    }
06893    if ( p1 ) delete p1;
06894    return ret;
06895 }
06896 
06897 bool testRefReadSparse()
06898 {
06899    // Tests consistency with a reference file for Sparse Histogram
06900 
06901    Int_t bsize[] = { TMath::Nint( r.Uniform(1, 5) ),
06902                      TMath::Nint( r.Uniform(1, 5) ),
06903                      TMath::Nint( r.Uniform(1, 5) )};
06904    Double_t xmin[] = {minRange, minRange, minRange};
06905    Double_t xmax[] = {maxRange, maxRange, maxRange};
06906 
06907    THnSparseD* s1 = 0;
06908    bool ret = 0;
06909 
06910    if ( refFileOption == refFileWrite ) {
06911       s1 = new THnSparseD("rr-s1", "s1-Title", 3, bsize, xmin, xmax);
06912       s1->Sumw2();
06913 
06914       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06915          Double_t points[3];
06916          points[0] = r.Uniform( minRange * .9 , maxRange * 1.1 );
06917          points[1] = r.Uniform( minRange * .9 , maxRange * 1.1 );
06918          points[2] = r.Uniform( minRange * .9 , maxRange * 1.1 );
06919          s1->Fill(points);
06920       }  
06921       s1->Write();
06922    } else {
06923       s1 = static_cast<THnSparseD*> ( refFile->Get("rr-s1") );
06924       THnSparseD* s2 = new THnSparseD("rr-s1", "s1-Title", 3, bsize, xmin, xmax);
06925       s2->Sumw2();
06926 
06927       for ( Int_t e = 0; e < nEvents * nEvents; ++e ) {
06928          Double_t points[3];
06929          points[0] = r.Uniform( minRange * .9 , maxRange * 1.1 );
06930          points[1] = r.Uniform( minRange * .9 , maxRange * 1.1 );
06931          points[2] = r.Uniform( minRange * .9 , maxRange * 1.1 );
06932          s2->Fill(points);
06933       }  
06934 
06935       ret = equals("Ref Read Sparse", s1, s2, cmpOptStats);
06936    }
06937    if ( s1 ) delete s1;
06938    return ret;
06939 }
06940 
06941 bool testIntegerRebin()
06942 {
06943    // Tests rebin method with an integer as input for 1D Histogram
06944 
06945    const int rebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
06946    UInt_t seed = r.GetSeed();
06947    TH1D* h1 = new TH1D("h1","Original Histogram", TMath::Nint( r.Uniform(1, 5) ) * rebin, minRange, maxRange);
06948    r.SetSeed(seed);
06949    for ( Int_t i = 0; i < nEvents; ++i )
06950       h1->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ) );
06951 
06952    TH1D* h2 = static_cast<TH1D*>( h1->Rebin(rebin, "testIntegerRebin") );
06953 
06954    TH1D* h3 = new TH1D("testIntegerRebin2", "testIntegerRebin2", 
06955                        h1->GetNbinsX() / rebin, minRange, maxRange);
06956    r.SetSeed(seed);
06957    for ( Int_t i = 0; i < nEvents; ++i )
06958       h3->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ) );
06959 
06960    bool ret = equals("TestIntegerRebinHist", h2, h3, cmpOptStats  );
06961    delete h1;
06962    delete h2;
06963    return ret;
06964 }
06965 
06966 bool testIntegerRebinProfile()
06967 {
06968    // Tests rebin method with an integer as input for 1D Profile
06969 
06970    const int rebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
06971    TProfile* p1 = new TProfile("p1","p1-Title", TMath::Nint( r.Uniform(1, 5) ) * rebin, minRange, maxRange);
06972    TProfile* p3 = new TProfile("testIntRebProf", "testIntRebProf", p1->GetNbinsX() / rebin, minRange, maxRange);
06973 
06974    for ( Int_t i = 0; i < nEvents; ++i ) {
06975       Double_t x = r.Uniform( minRange * .9 , maxRange * 1.1 );
06976       Double_t y = r.Uniform( minRange * .9 , maxRange * 1.1 );
06977       p1->Fill( x, y );
06978       p3->Fill( x, y );
06979    }
06980 
06981    TProfile* p2 = static_cast<TProfile*>( p1->Rebin(rebin, "testIntegerRebin") );
06982 
06983    bool ret = equals("TestIntegerRebinProf", p2, p3, cmpOptStats );
06984    delete p1;
06985    delete p2;
06986    return ret;
06987 }
06988 
06989 bool testIntegerRebinNoName()
06990 {
06991    // Tests rebin method with an integer as input and without name for 1D Histogram
06992 
06993    const int rebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
06994    UInt_t seed = r.GetSeed();
06995    TH1D* h1 = new TH1D("h2","Original Histogram", TMath::Nint( r.Uniform(1, 5) ) * rebin, minRange, maxRange);
06996    r.SetSeed(seed);
06997    for ( Int_t i = 0; i < nEvents; ++i )
06998       h1->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ) );
06999 
07000    TH1D* h2 = dynamic_cast<TH1D*>( h1->Clone() );
07001    h2->Rebin(rebin);
07002 
07003    TH1D* h3 = new TH1D("testIntegerRebinNoName", "testIntegerRebinNoName", 
07004                        int(h1->GetNbinsX() / rebin + 0.1), minRange, maxRange);
07005    r.SetSeed(seed);
07006    for ( Int_t i = 0; i < nEvents; ++i )
07007       h3->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ) );
07008 
07009    bool ret = equals("TestIntRebinNoName", h2, h3, cmpOptStats );
07010    delete h1;
07011    delete h2;
07012    return ret;
07013 }
07014 
07015 bool testIntegerRebinNoNameProfile()
07016 {
07017    // Tests rebin method with an integer as input and without name for 1D Profile
07018 
07019    const int rebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
07020    TProfile* p1 = new TProfile("p1","p1-Title", TMath::Nint( r.Uniform(1, 5) ) * rebin, minRange, maxRange);
07021    TProfile* p3 = new TProfile("testIntRebNNProf", "testIntRebNNProf", int(p1->GetNbinsX() / rebin + 0.1), minRange, maxRange);
07022 
07023    for ( Int_t i = 0; i < nEvents; ++i ) {
07024       Double_t x = r.Uniform( minRange * .9 , maxRange * 1.1 );
07025       Double_t y = r.Uniform( minRange * .9 , maxRange * 1.1 );
07026       p1->Fill( x, y );
07027       p3->Fill( x, y );
07028    }
07029 
07030    TProfile* p2 = dynamic_cast<TProfile*>( p1->Clone() );
07031    p2->Rebin(rebin);
07032    bool ret = equals("TestIntRebNoNamProf", p2, p3, cmpOptStats);
07033    delete p1;
07034    delete p2;
07035    return ret;
07036 }
07037 
07038 bool testArrayRebin()
07039 {
07040    // Tests rebin method with an array as input for 1D Histogram
07041 
07042    const int rebin = TMath::Nint( r.Uniform(minRebin, maxRebin) ) + 1;
07043    UInt_t seed = r.GetSeed();
07044    TH1D* h1 = new TH1D("h3","Original Histogram", TMath::Nint( r.Uniform(1, 5) ) * rebin * 2, minRange, maxRange);
07045    r.SetSeed(seed);
07046    for ( Int_t i = 0; i < nEvents; ++i )
07047       h1->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ) );
07048 
07049    // Create vector - generate bin edges ( nbins is always > 2)
07050    // ignore fact that array may contains bins with zero size 
07051    Double_t * rebinArray = new Double_t[rebin];
07052    r.RndmArray(rebin, rebinArray);
07053    std::sort(rebinArray, rebinArray + rebin);
07054    for ( Int_t i = 0; i < rebin; ++i ) {
07055       rebinArray[i] = TMath::Nint( rebinArray[i] * ( h1->GetNbinsX() - 2 ) + 2 );
07056       rebinArray[i] = h1->GetBinLowEdge( (Int_t) rebinArray[i] );
07057    }
07058    
07059 
07060 //    rebinArray[0] = minRange;
07061 //    rebinArray[rebin-1] = maxRange;
07062 
07063 #ifdef __DEBUG__
07064    std::cout << "min range = " << minRange << " max range " << maxRange << std::endl;
07065    for ( Int_t i = 0; i < rebin; ++i ) 
07066       cout << rebinArray[i] << endl;
07067    cout << "rebin: " << rebin << endl;
07068 #endif
07069 
07070    TH1D* h2 = static_cast<TH1D*>( h1->Rebin(rebin - 1, "testArrayRebin", rebinArray) );
07071 
07072    TH1D* h3 = new TH1D("testArrayRebin2", "testArrayRebin2", rebin - 1, rebinArray );
07073    r.SetSeed(seed);
07074    for ( Int_t i = 0; i < nEvents; ++i )
07075       h3->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ) );
07076 
07077    delete [] rebinArray;
07078       
07079    bool ret = equals("TestArrayRebin", h2, h3, cmpOptStats);
07080    delete h1;
07081    delete h2;
07082    return ret;
07083 }
07084 
07085 bool testArrayRebinProfile()
07086 {
07087    // Tests rebin method with an array as input for 1D Profile
07088 
07089    const int rebin = TMath::Nint( r.Uniform(minRebin, maxRebin) ) + 1;
07090    UInt_t seed = r.GetSeed();
07091    TProfile* p1 = new TProfile("p3","Original Histogram", TMath::Nint( r.Uniform(1, 5) ) * rebin * 2, minRange, maxRange);
07092    r.SetSeed(seed);
07093    for ( Int_t i = 0; i < nEvents; ++i ) {
07094       Double_t x = r.Uniform( minRange * .9 , maxRange * 1.1 );
07095       Double_t y = r.Uniform( minRange * .9 , maxRange * 1.1 ); 
07096       p1->Fill( x, y );
07097    }
07098 
07099    // Create vector - generate bin edges ( nbins is always > 2)
07100    // ignore fact that array may contains bins with zero size 
07101    Double_t * rebinArray = new Double_t[rebin];
07102    r.RndmArray(rebin, rebinArray);
07103    std::sort(rebinArray, rebinArray + rebin);
07104    for ( Int_t i = 0; i < rebin; ++i ) {
07105       rebinArray[i] = TMath::Nint( rebinArray[i] * ( p1->GetNbinsX() - 2 ) + 2 );
07106       rebinArray[i] = p1->GetBinLowEdge( (Int_t) rebinArray[i] );
07107    }
07108 
07109 //    rebinArray[0] = minRange;
07110 //    rebinArray[rebin-1] = maxRange;
07111 
07112    #ifdef __DEBUG__
07113    for ( Int_t i = 0; i < rebin; ++i ) 
07114       cout << rebinArray[i] << endl;
07115    cout << "rebin: " << rebin << endl;
07116    #endif
07117 
07118    TProfile* p2 = static_cast<TProfile*>( p1->Rebin(rebin - 1, "testArrayRebinProf", rebinArray) );
07119 
07120    TProfile* p3 = new TProfile("testArrayRebinProf2", "testArrayRebinProf2", rebin - 1, rebinArray );
07121    r.SetSeed(seed);
07122    for ( Int_t i = 0; i < nEvents; ++i ) {
07123       Double_t x = r.Uniform( minRange * .9 , maxRange * 1.1 );
07124       Double_t y = r.Uniform( minRange * .9 , maxRange * 1.1 );
07125       p3->Fill( x, y );
07126    }
07127 
07128    delete [] rebinArray;
07129       
07130    bool ret = equals("TestArrayRebinProf", p2, p3, cmpOptStats );
07131    delete p1;
07132    delete p2;
07133    return ret;
07134 }
07135 
07136 bool test2DRebin()
07137 {
07138    // Tests rebin method for 2D Histogram
07139 
07140    Int_t xrebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
07141    Int_t yrebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
07142    // make the bins of the orginal histo not an exact divider to leave an extra bin
07143    TH2D* h2d = new TH2D("h2d","Original Histogram", 
07144                        xrebin * TMath::Nint( r.Uniform(1, 5) ), minRange, maxRange, 
07145                        yrebin * TMath::Nint( r.Uniform(1, 5) ), minRange, maxRange);
07146 
07147    UInt_t seed = r.GetSeed();
07148    r.SetSeed(seed);
07149    for ( Int_t i = 0; i < nEvents; ++i )
07150       h2d->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ), r.Uniform( minRange * .9 , maxRange * 1.1 ));
07151 
07152    TH2D* h2d2 = (TH2D*) h2d->Rebin2D(xrebin,yrebin, "p2d2");
07153 
07154    // range of rebinned histogram may be different than original one
07155    TH2D* h3 = new TH2D("test2DRebin", "test2DRebin", 
07156                        h2d->GetNbinsX() / xrebin, h2d2->GetXaxis()->GetXmin(), h2d2->GetXaxis()->GetXmax(),
07157                        h2d->GetNbinsY() / yrebin, h2d2->GetYaxis()->GetXmin(), h2d2->GetYaxis()->GetXmax() );
07158    r.SetSeed(seed);
07159    for ( Int_t i = 0; i < nEvents; ++i )
07160       h3->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ), r.Uniform( minRange * .9 , maxRange * 1.1 ) );
07161 
07162    bool ret = equals("TestIntRebin2D", h2d2, h3, cmpOptStats); // | cmpOptDebug);
07163    delete h2d;
07164    delete h2d2;
07165    return ret;
07166 }
07167 
07168 bool test2DRebinProfile()
07169 {
07170    // Tests rebin method for 2D Profile Histogram
07171 
07172    Int_t xrebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
07173    Int_t yrebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
07174    TProfile2D* h2d = new TProfile2D("p2d","Original Profile Histogram", 
07175                        xrebin * TMath::Nint( r.Uniform(1, 5) ), minRange, maxRange, 
07176                        yrebin * TMath::Nint( r.Uniform(1, 5) ), minRange, maxRange);
07177 
07178    UInt_t seed = r.GetSeed();
07179    r.SetSeed(seed);
07180    for ( Int_t i = 0; i < nEvents; ++i )
07181       h2d->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ), r.Uniform( minRange * .9 , maxRange * 1.1 ), r.Uniform(0,10) );
07182 
07183    TProfile2D* h2d2 = (TProfile2D*) h2d->Rebin2D(xrebin,yrebin, "p2d2");
07184 
07185    TProfile2D* h3 = new TProfile2D("test2DRebinProfile", "test2DRebin", 
07186                                    h2d->GetNbinsX() / xrebin, h2d2->GetXaxis()->GetXmin(), h2d2->GetXaxis()->GetXmax(), 
07187                                    h2d->GetNbinsY() / yrebin, h2d2->GetYaxis()->GetXmin(), h2d2->GetYaxis()->GetXmax() );
07188    r.SetSeed(seed);
07189    for ( Int_t i = 0; i < nEvents; ++i )
07190       h3->Fill( r.Uniform( minRange * .9 , maxRange * 1.1 ), r.Uniform( minRange * .9 , maxRange * 1.1 ), r.Uniform(0,10) );
07191 
07192    bool ret = equals("TestIntRebin2DProfile", h2d2, h3, cmpOptStats);
07193    delete h2d;
07194    delete h2d2;
07195    return ret;
07196 }
07197 
07198 bool testSparseRebin1() 
07199 {
07200    // Tests rebin method for Sparse Histogram
07201 
07202    const int rebin = TMath::Nint( r.Uniform(minRebin, maxRebin) );
07203 
07204    Int_t bsizeRebin[] = { TMath::Nint( r.Uniform(1, 5) ),
07205                           TMath::Nint( r.Uniform(1, 5) ),
07206                           TMath::Nint( r.Uniform(1, 5) )};
07207 
07208    Int_t bsize[] = { bsizeRebin[0] * rebin,
07209                      bsizeRebin[1] * rebin,
07210                      bsizeRebin[2] * rebin};
07211                     
07212    Double_t xmin[] = {minRange, minRange, minRange};
07213    Double_t xmax[] = {maxRange, maxRange, maxRange};
07214    THnSparseD* s1 = new THnSparseD("rebin1-s1","s1-Title", 3, bsize, xmin, xmax);
07215    THnSparseD* s2 = new THnSparseD("rebin1-s2","s2-Title", 3, bsizeRebin, xmin, xmax);
07216 
07217    for ( Int_t i = 0; i < nEvents; ++i ) {
07218       Double_t points[3];
07219       points[0] = r.Uniform( minRange * .9 , maxRange * 1.1 );
07220       points[1] = r.Uniform( minRange * .9 , maxRange * 1.1 );
07221       points[2] = r.Uniform( minRange * .9 , maxRange * 1.1 );
07222       s1->Fill(points);
07223       s2->Fill(points);
07224    }
07225 
07226    THnSparse* s3 = s1->Rebin(rebin);
07227 
07228    bool ret = equals("THnSparse Rebin 1", s2, s3);
07229    delete s1;
07230    delete s2;
07231    return ret;
07232 }
07233 
07234 bool testTH2toTH1()
07235 {
07236    const double centre_deviation = 0.3;
07237 
07238    const unsigned int binsizeX =  10;
07239    const unsigned int binsizeY =  11;
07240    static const unsigned int minbinX = 2;
07241    static const unsigned int maxbinX = 5;
07242    static const unsigned int minbinY = 3;
07243    static const unsigned int maxbinY = 8;
07244    const int lower_limit = 0;
07245    const int upper_limit = 10;
07246    
07247    r.SetSeed(10);
07248 
07249    TH2D* h2XY = new TH2D("h2XY", "h2XY", binsizeX, lower_limit, upper_limit, 
07250                                          binsizeY, lower_limit, upper_limit);
07251 
07252    TH1::StatOverflows(kTRUE);
07253 
07254    TH1D* h1X = new TH1D("h1X", "h1X", binsizeX, lower_limit, upper_limit);
07255    TH1D* h1Y = new TH1D("h1Y", "h1Y", binsizeY, lower_limit, upper_limit);
07256 
07257    TH1D* h1XOR = new TH1D("h1XOR", "h1XOR", binsizeX, lower_limit, upper_limit);
07258    TH1D* h1YOR = new TH1D("h1YOR", "h1YOR", binsizeY, lower_limit, upper_limit);
07259 
07260    TH1D* h1XR = new TH1D("h1XR", "h1XR",
07261                          maxbinX - minbinX + 1, 
07262                          h1X->GetXaxis()->GetBinLowEdge(minbinX), 
07263                          h1X->GetXaxis()->GetBinUpEdge(maxbinX) );
07264    TH1D* h1YR = new TH1D("h1YR", "h1YR",
07265                          maxbinY - minbinY + 1, 
07266                          h1Y->GetXaxis()->GetBinLowEdge(minbinY),
07267                          h1Y->GetXaxis()->GetBinUpEdge(maxbinY) );
07268 
07269    TProfile* pe1XY  = new TProfile("pe1XY",  "pe1XY",  binsizeX, lower_limit, upper_limit);
07270    TProfile* pe1XYOR  = new TProfile("pe1XYOR",  "pe1XYOR",  binsizeX, lower_limit, upper_limit);
07271    TProfile* pe1XYR = new TProfile("pe1XYR", "pe1XYR", 
07272                                    maxbinX - minbinX + 1, 
07273                                    h1X->GetXaxis()->GetBinLowEdge(minbinX), 
07274                                    h1X->GetXaxis()->GetBinUpEdge(maxbinX) );
07275 
07276    TProfile* pe1YX  = new TProfile("pe1YX",  "pe1YX", binsizeY, lower_limit, upper_limit);
07277    TProfile* pe1YXOR  = new TProfile("pe1YXOR",  "pe1YXOR", binsizeY, lower_limit, upper_limit);
07278    TProfile* pe1YXR = new TProfile("pe1YXR", "pe1YXR", 
07279                                   maxbinY - minbinY + 1, 
07280                                   h1Y->GetXaxis()->GetBinLowEdge(minbinY), 
07281                                   h1Y->GetXaxis()->GetBinUpEdge(maxbinY));
07282    
07283    for ( int ix = 0; ix <= h2XY->GetXaxis()->GetNbins() + 1; ++ix ) {
07284       double xc = h2XY->GetXaxis()->GetBinCenter(ix);
07285       double x = xc + centre_deviation * h2XY->GetXaxis()->GetBinWidth(ix); 
07286       for ( int iy = 0; iy <= h2XY->GetYaxis()->GetNbins() + 1; ++iy ) {
07287          double yc = h2XY->GetYaxis()->GetBinCenter(iy);
07288          double y = yc + centre_deviation * h2XY->GetYaxis()->GetBinWidth(iy);
07289 
07290          Double_t w = (Double_t) r.Uniform(1,3);
07291          
07292          h2XY->Fill(x,y,w);
07293                
07294          h1X->Fill(x,w);
07295          h1Y->Fill(y,w);
07296 
07297          pe1XY->Fill(xc,yc,w);
07298          pe1YX->Fill(yc,xc,w);
07299          if ( x >= h1X->GetXaxis()->GetBinLowEdge(minbinX) &&
07300               x <= h1X->GetXaxis()->GetBinUpEdge(maxbinX)  && 
07301               y >= h1Y->GetXaxis()->GetBinLowEdge(minbinY) &&
07302               y <= h1Y->GetXaxis()->GetBinUpEdge(maxbinY) ) 
07303          {
07304             h1XOR->Fill(x,w);
07305             h1YOR->Fill(y,w);
07306             h1XR->Fill(x,w);
07307             h1YR->Fill(y,w);
07308             pe1XYR->Fill(xc,yc,w);
07309             pe1YXR->Fill(yc,xc,w);
07310             pe1XYOR->Fill(xc,yc,w);
07311             pe1YXOR->Fill(yc,xc,w);
07312          }
07313 
07314       }
07315    }
07316    
07317    int status = 0;
07318    int options = cmpOptStats;
07319 
07320    // TH1 derived from h2XY
07321    status += equals("TH2XY    -> X", h1X, (TH1D*) h2XY->ProjectionX("x"), options);
07322    status += equals("TH2XY    -> Y", h1Y, (TH1D*) h2XY->ProjectionY("y"), options);
07323 
07324    status += equals("TH2XYO  -> X", h1X, (TH1D*) h2XY->ProjectionX("ox", 0, -1, "o"), options);
07325    status += equals("TH2XYO  -> Y", h1Y, (TH1D*) h2XY->ProjectionY("oy", 0, -1, "o"), options);
07326 
07327    status += equals("TH2XY -> PX", pe1XY, (TH1D*) h2XY->ProfileX("PX", 0,h2XY->GetYaxis()->GetNbins()+1), options);
07328    status += equals("TH2XY -> PY", pe1YX, (TH1D*) h2XY->ProfileY("PY", 0,h2XY->GetXaxis()->GetNbins()+1), options);
07329 
07330    status += equals("TH2XYO -> PX", pe1XY, (TH1D*) h2XY->ProfileX("OPX", 0,h2XY->GetYaxis()->GetNbins()+1,"o"), options);
07331    status += equals("TH2XYO -> PY", pe1YX, (TH1D*) h2XY->ProfileY("OPY", 0,h2XY->GetXaxis()->GetNbins()+1,"o"), options);
07332 
07333    h2XY->GetXaxis()->SetRange(minbinX, maxbinX);
07334    h2XY->GetYaxis()->SetRange(minbinY, maxbinY);
07335 
07336    h1X->GetXaxis()->SetRange(minbinX, maxbinX);
07337    h1Y->GetXaxis()->SetRange(minbinY, maxbinY);
07338 
07339    pe1XY->GetXaxis()->SetRange(minbinX, maxbinX);
07340    pe1YX->GetXaxis()->SetRange(minbinY, maxbinY);
07341 
07342    // This two, the statistics should work!
07343    options = 0;
07344 
07345    status += equals("TH2XYR  -> X", h1XR, (TH1D*) h2XY->ProjectionX("x"), options);
07346    status += equals("TH2XYR  -> Y", h1YR, (TH1D*) h2XY->ProjectionY("y"), options);
07347 
07348    status += equals("TH2XYRO -> X", h1XOR, (TH1D*) h2XY->ProjectionX("ox", 0, -1, "o"), options);
07349    status += equals("TH2XYRO -> Y", h1YOR, (TH1D*) h2XY->ProjectionY("oy", 0, -1, "o"), options);
07350 
07351    status += equals("TH2XYR -> PX", pe1XYR, (TH1D*) h2XY->ProfileX("PX"), options);
07352    status += equals("TH2XYR -> PY", pe1YXR, (TH1D*) h2XY->ProfileY("PY"), options);
07353    
07354    status += equals("TH2XYRO -> PX", pe1XYOR, (TH1D*) h2XY->ProfileX("OPX", 0,-1,"o"), options);
07355    status += equals("TH2XYRO -> PY", pe1YXOR, (TH1D*) h2XY->ProfileY("OPY", 0,-1,"o"), options);
07356 
07357    options = 0;
07358 
07359    delete h2XY;
07360    delete h1X;
07361    delete h1Y;
07362    delete h1XOR;
07363    delete h1YOR;
07364 
07365    delete h1XR;
07366    delete h1YR;
07367 
07368    delete pe1XY;
07369    delete pe1XYOR;
07370    delete pe1XYR;
07371 
07372    delete pe1YX;
07373    delete pe1YXOR;
07374    delete pe1YXR;
07375 
07376    return static_cast<bool>(status);
07377 }
07378 
07379 bool testTH3toTH1()
07380 {
07381    const double centre_deviation = 0.3;
07382 
07383    const unsigned int binsizeX =  10;
07384    const unsigned int binsizeY =  11;
07385    const unsigned int binsizeZ =  12;
07386    static const unsigned int minbinX = 2;
07387    static const unsigned int maxbinX = 5;
07388    static const unsigned int minbinY = 3;
07389    static const unsigned int maxbinY = 8;
07390    static const unsigned int minbinZ = 4;
07391    static const unsigned int maxbinZ = 10;
07392    const int lower_limit = 0;
07393    const int upper_limit = 10;
07394 
07395    r.SetSeed(10);
07396 
07397    TH3D* h3 = new TH3D("h3","h3", binsizeX, lower_limit, upper_limit, 
07398                                   binsizeY, lower_limit, upper_limit, 
07399                                   binsizeZ, lower_limit, upper_limit);
07400 
07401 
07402    TH1::StatOverflows(kTRUE);
07403 
07404    TH1D* h1X = new TH1D("h1X", "h1X", binsizeX, lower_limit, upper_limit);
07405    TH1D* h1Y = new TH1D("h1Y", "h1Y", binsizeY, lower_limit, upper_limit);
07406    TH1D* h1Z = new TH1D("h1Z", "h1Z", binsizeZ, lower_limit, upper_limit);
07407 
07408    TH1D* h1XR = new TH1D("h1XR", "h1XR",
07409                          maxbinX - minbinX + 1, 
07410                          h1X->GetXaxis()->GetBinLowEdge(minbinX), 
07411                          h1X->GetXaxis()->GetBinUpEdge(maxbinX) );
07412    TH1D* h1YR = new TH1D("h1YR", "h1YR",
07413                          maxbinY - minbinY + 1, 
07414                          h1Y->GetXaxis()->GetBinLowEdge(minbinY),
07415                          h1Y->GetXaxis()->GetBinUpEdge(maxbinY) );
07416    TH1D* h1ZR = new TH1D("h1ZR", "h1ZR",
07417                          maxbinZ - minbinZ + 1, 
07418                          h1Z->GetXaxis()->GetBinLowEdge(minbinZ),
07419                          h1Z->GetXaxis()->GetBinUpEdge(maxbinZ) );
07420 
07421    TH1D* h1XOR = new TH1D("h1XOR", "h1XOR", binsizeX, lower_limit, upper_limit);
07422    TH1D* h1YOR = new TH1D("h1YOR", "h1YOR", binsizeY, lower_limit, upper_limit);
07423    TH1D* h1ZOR = new TH1D("h1ZOR", "h1ZOR", binsizeZ, lower_limit, upper_limit);
07424 
07425    h3->Sumw2();
07426 
07427    for ( int ix = 0; ix <= h3->GetXaxis()->GetNbins() + 1; ++ix ) {
07428          double x = centre_deviation * h3->GetXaxis()->GetBinWidth(ix) + h3->GetXaxis()->GetBinCenter(ix);
07429          for ( int iy = 0; iy <= h3->GetYaxis()->GetNbins() + 1; ++iy ) {
07430             double y = centre_deviation * h3->GetYaxis()->GetBinWidth(iy) + h3->GetYaxis()->GetBinCenter(iy);
07431             for ( int iz = 0; iz <= h3->GetZaxis()->GetNbins() + 1; ++iz ) {
07432                double z = centre_deviation * h3->GetZaxis()->GetBinWidth(iz) + h3->GetZaxis()->GetBinCenter(iz);
07433                Double_t w = (Double_t) r.Uniform(1,3);
07434          
07435                h3->Fill(x,y,z,w);
07436                
07437                h1X->Fill(x,w);
07438                h1Y->Fill(y,w);
07439                h1Z->Fill(z,w);
07440                
07441                if ( x >= h1X->GetXaxis()->GetBinLowEdge(minbinX) &&
07442                     x <= h1X->GetXaxis()->GetBinUpEdge(maxbinX)  && 
07443                     y >= h1Y->GetXaxis()->GetBinLowEdge(minbinY) &&
07444                     y <= h1Y->GetXaxis()->GetBinUpEdge(maxbinY)  &&
07445                     z >= h1Z->GetXaxis()->GetBinLowEdge(minbinZ) &&
07446                     z <= h1Z->GetXaxis()->GetBinUpEdge(maxbinZ) ) 
07447                {
07448                   h1XR->Fill(x,w);
07449                   h1YR->Fill(y,w);
07450                   h1ZR->Fill(z,w);
07451                   h1XOR->Fill(x,w);
07452                   h1YOR->Fill(y,w);
07453                   h1ZOR->Fill(z,w);
07454                }
07455                
07456             }
07457          }
07458    }
07459 
07460    int status = 0;
07461    int options = cmpOptStats;
07462 
07463    TH1D* tmp1 = 0;
07464 
07465    options = cmpOptStats;
07466    status += equals("TH3 -> X", h1X, (TH1D*) h3->Project3D("x"), options);
07467    tmp1 = h3->ProjectionX("x335");
07468    status += equals("TH3 -> X(x2)", tmp1, (TH1D*) h3->Project3D("x2"), options);
07469    delete tmp1; tmp1 = 0;
07470    status += equals("TH3 -> Y", h1Y, (TH1D*) h3->Project3D("y"), options);
07471    tmp1 = h3->ProjectionY("y335");
07472    status += equals("TH3 -> Y(x2)", tmp1, (TH1D*) h3->Project3D("y2"), options);
07473    delete tmp1; tmp1 = 0;
07474    status += equals("TH3 -> Z", h1Z, (TH1D*) h3->Project3D("z"), options);
07475    tmp1 = h3->ProjectionZ("z335");
07476    status += equals("TH3 -> Z(x2)", tmp1, (TH1D*) h3->Project3D("z2"), options);
07477    delete tmp1; tmp1 = 0;
07478 
07479 
07480    options = cmpOptStats;
07481    status += equals("TH3O -> X", h1X, (TH1D*) h3->Project3D("ox"), options);
07482    tmp1 = h3->ProjectionX("x1335");
07483    status += equals("TH3O -> X(x2)", tmp1, (TH1D*) h3->Project3D("ox2"), options);
07484    delete tmp1; tmp1 = 0;
07485    status += equals("TH3O -> Y", h1Y, (TH1D*) h3->Project3D("oy"), options);
07486    tmp1 = h3->ProjectionY("y1335");
07487    status += equals("TH3O -> Y(x2)", tmp1, (TH1D*) h3->Project3D("oy2"), options);
07488    delete tmp1; tmp1 = 0;
07489    status += equals("TH3O -> Z", h1Z, (TH1D*) h3->Project3D("oz"), options);
07490    tmp1 = h3->ProjectionZ("z1335");
07491    status += equals("TH3O -> Z(x2)", tmp1, (TH1D*) h3->Project3D("oz2"), options);
07492    delete tmp1; tmp1 = 0;
07493 
07494    h3->GetXaxis()->SetRange(minbinX, maxbinX);
07495    h3->GetYaxis()->SetRange(minbinY, maxbinY);
07496    h3->GetZaxis()->SetRange(minbinZ, maxbinZ);
07497 
07498    h1X->GetXaxis()->SetRange(minbinX, maxbinX);
07499    h1Y->GetXaxis()->SetRange(minbinY, maxbinY);
07500    h1Z->GetXaxis()->SetRange(minbinZ, maxbinZ);
07501    
07502    //Statistics are no longer conserved if the center_deviation != 0.0
07503    options = 0;
07504    status += equals("TH3R -> X", h1XR, (TH1D*) h3->Project3D("x34"), options );
07505    tmp1 = h3->ProjectionX("x3335", minbinY, maxbinY, minbinZ, maxbinZ);
07506    status += equals("TH3R -> X(x2)", tmp1, (TH1D*) h3->Project3D("x22"), options);
07507    delete tmp1; tmp1 = 0;
07508    status += equals("TH3R -> Y", h1YR, (TH1D*) h3->Project3D("y34"), options);
07509    tmp1 = h3->ProjectionY("y3335", minbinX, maxbinX, minbinZ, maxbinZ);
07510    status += equals("TH3R -> Y(x2)", tmp1, (TH1D*) h3->Project3D("y22"), options);
07511    delete tmp1; tmp1 = 0;
07512    status += equals("TH3R -> Z", h1ZR, (TH1D*) h3->Project3D("z34"), options);
07513    tmp1 = h3->ProjectionZ("z3335", minbinX, maxbinX, minbinY, maxbinY);
07514    status += equals("TH3R -> Z(x2)", tmp1, (TH1D*) h3->Project3D("z22"), options);
07515    delete tmp1; tmp1 = 0;
07516 
07517    options = 0;
07518    status += equals("TH3RO -> X", h1XOR, (TH1D*) h3->Project3D("ox"), options);
07519    tmp1 = h3->ProjectionX("x1335", minbinY, maxbinY, minbinZ, maxbinZ,"o");
07520    status += equals("TH3RO-> X(x2)", tmp1, (TH1D*) h3->Project3D("ox2"), options );
07521    delete tmp1; tmp1 = 0;
07522    status += equals("TH3RO -> Y", h1YOR, (TH1D*) h3->Project3D("oy"), options);
07523    tmp1 = h3->ProjectionY("y1335", minbinX, maxbinX, minbinZ, maxbinZ,"o");
07524    status += equals("TH3RO-> Y(x2)", tmp1, (TH1D*) h3->Project3D("oy2"), options);
07525    delete tmp1; tmp1 = 0;
07526    status += equals("TH3RO-> Z", h1ZOR, (TH1D*) h3->Project3D("oz"), options);
07527    tmp1 = h3->ProjectionZ("z1335", minbinX, maxbinX, minbinY, maxbinY,"o");
07528    status += equals("TH3RO-> Z(x2)", tmp1, (TH1D*) h3->Project3D("oz2"), options);
07529    delete tmp1; tmp1 = 0;
07530 
07531    options = 0;
07532 
07533    delete h3;
07534 
07535    delete h1X;
07536    delete h1Y;
07537    delete h1Z;
07538 
07539    delete h1XR;
07540    delete h1YR;
07541    delete h1ZR;
07542 
07543    delete h1XOR;
07544    delete h1YOR;
07545    delete h1ZOR;
07546 
07547    return status;
07548 }
07549 
07550 bool testTH3toTH2()
07551 {
07552    const double centre_deviation = 0.3;
07553 
07554    const unsigned int binsizeX =  10;
07555    const unsigned int binsizeY =  11;
07556    const unsigned int binsizeZ =  12;
07557    static const unsigned int minbinX = 2;
07558    static const unsigned int maxbinX = 5;
07559    static const unsigned int minbinY = 3;
07560    static const unsigned int maxbinY = 8;
07561    static const unsigned int minbinZ = 4;
07562    static const unsigned int maxbinZ = 10;
07563    const int lower_limit = 0;
07564    const int upper_limit = 10;
07565 
07566    r.SetSeed(10);
07567 
07568    TH3D* h3 = new TH3D("h3","h3", binsizeX, lower_limit, upper_limit, 
07569                                   binsizeY, lower_limit, upper_limit, 
07570                                   binsizeZ, lower_limit, upper_limit);
07571 
07572 
07573    TH1::StatOverflows(kTRUE);
07574 
07575    TH2D* h2XY = new TH2D("h2XY", "h2XY", binsizeX, lower_limit, upper_limit, 
07576                                          binsizeY, lower_limit, upper_limit);
07577    TH2D* h2XZ = new TH2D("h2XZ", "h2XZ", binsizeX, lower_limit, upper_limit, 
07578                                          binsizeZ, lower_limit, upper_limit);
07579    TH2D* h2YX = new TH2D("h2YX", "h2YX", binsizeY, lower_limit, upper_limit, 
07580                                          binsizeX, lower_limit, upper_limit);
07581    TH2D* h2YZ = new TH2D("h2YZ", "h2YZ", binsizeY, lower_limit, upper_limit, 
07582                                          binsizeZ, lower_limit, upper_limit);
07583    TH2D* h2ZX = new TH2D("h2ZX", "h2ZX", binsizeZ, lower_limit, upper_limit, 
07584                                          binsizeX, lower_limit, upper_limit);
07585    TH2D* h2ZY = new TH2D("h2ZY", "h2ZY", binsizeZ, lower_limit, upper_limit, 
07586                                          binsizeY, lower_limit, upper_limit);
07587 
07588    TH2D* h2XYR = new TH2D("h2XYR", "h2XYR", 
07589                           maxbinX - minbinX + 1, h3->GetXaxis()->GetBinLowEdge(minbinX), h3->GetXaxis()->GetBinUpEdge(maxbinX), 
07590                           maxbinY - minbinY + 1, h3->GetYaxis()->GetBinLowEdge(minbinY), h3->GetYaxis()->GetBinUpEdge(maxbinY) );
07591    TH2D* h2XZR = new TH2D("h2XZR", "h2XZR",
07592                           maxbinX - minbinX + 1, h3->GetXaxis()->GetBinLowEdge(minbinX), h3->GetXaxis()->GetBinUpEdge(maxbinX), 
07593                           maxbinZ - minbinZ + 1, h3->GetZaxis()->GetBinLowEdge(minbinZ), h3->GetZaxis()->GetBinUpEdge(maxbinZ) );
07594    TH2D* h2YXR = new TH2D("h2YXR", "h2YXR",
07595                           maxbinY - minbinY + 1, h3->GetYaxis()->GetBinLowEdge(minbinY), h3->GetYaxis()->GetBinUpEdge(maxbinY),
07596                           maxbinX - minbinX + 1, h3->GetXaxis()->GetBinLowEdge(minbinX), h3->GetXaxis()->GetBinUpEdge(maxbinX) );
07597    TH2D* h2YZR = new TH2D("h2YZR", "h2YZR",
07598                           maxbinY - minbinY + 1, h3->GetYaxis()->GetBinLowEdge(minbinY), h3->GetYaxis()->GetBinUpEdge(maxbinY),
07599                           maxbinZ - minbinZ + 1, h3->GetZaxis()->GetBinLowEdge(minbinZ), h3->GetZaxis()->GetBinUpEdge(maxbinZ) );
07600    TH2D* h2ZXR = new TH2D("h2ZXR", "h2ZXR", 
07601                           maxbinZ - minbinZ + 1, h3->GetZaxis()->GetBinLowEdge(minbinZ), h3->GetZaxis()->GetBinUpEdge(maxbinZ),
07602                           maxbinX - minbinX + 1, h3->GetXaxis()->GetBinLowEdge(minbinX), h3->GetXaxis()->GetBinUpEdge(maxbinX) );
07603    TH2D* h2ZYR = new TH2D("h2ZYR", "h2ZYR", 
07604                           maxbinZ - minbinZ + 1, h3->GetZaxis()->GetBinLowEdge(minbinZ), h3->GetZaxis()->GetBinUpEdge(maxbinZ),
07605                           maxbinY - minbinY + 1, h3->GetYaxis()->GetBinLowEdge(minbinY), h3->GetYaxis()->GetBinUpEdge(maxbinY) );
07606 
07607    TH2D* h2XYOR = new TH2D("h2XYOR", "h2XYOR", binsizeX, lower_limit, upper_limit, 
07608                                                binsizeY, lower_limit, upper_limit);
07609    TH2D* h2XZOR = new TH2D("h2XZOR", "h2XZOR", binsizeX, lower_limit, upper_limit, 
07610                                                binsizeZ, lower_limit, upper_limit);
07611    TH2D* h2YXOR = new TH2D("h2YXOR", "h2YXOR", binsizeY, lower_limit, upper_limit, 
07612                                                binsizeX, lower_limit, upper_limit);
07613    TH2D* h2YZOR = new TH2D("h2YZOR", "h2YZOR", binsizeY, lower_limit, upper_limit, 
07614                                                binsizeZ, lower_limit, upper_limit);
07615    TH2D* h2ZXOR = new TH2D("h2ZXOR", "h2ZXOR", binsizeZ, lower_limit, upper_limit, 
07616                                                binsizeX, lower_limit, upper_limit);
07617    TH2D* h2ZYOR = new TH2D("h2ZYOR", "h2ZYOR", binsizeZ, lower_limit, upper_limit, 
07618                                                binsizeY, lower_limit, upper_limit);
07619 
07620    TProfile2D* pe2XY = new TProfile2D("pe2XY", "pe2XY", binsizeX, lower_limit, upper_limit, 
07621                                                         binsizeY, lower_limit, upper_limit);
07622    TProfile2D* pe2XZ = new TProfile2D("pe2XZ", "pe2XZ", binsizeX, lower_limit, upper_limit, 
07623                                                         binsizeZ, lower_limit, upper_limit);
07624    TProfile2D* pe2YX = new TProfile2D("pe2YX", "pe2YX", binsizeY, lower_limit, upper_limit, 
07625                                                         binsizeX, lower_limit, upper_limit);
07626    TProfile2D* pe2YZ = new TProfile2D("pe2YZ", "pe2YZ", binsizeY, lower_limit, upper_limit, 
07627                                                         binsizeZ, lower_limit, upper_limit);
07628    TProfile2D* pe2ZX = new TProfile2D("pe2ZX", "pe2ZX", binsizeZ, lower_limit, upper_limit, 
07629                                                         binsizeX, lower_limit, upper_limit);
07630    TProfile2D* pe2ZY = new TProfile2D("pe2ZY", "pe2ZY", binsizeZ, lower_limit, upper_limit, 
07631                                                         binsizeY, lower_limit, upper_limit);
07632 
07633    TProfile2D* pe2XYR = new TProfile2D("pe2XYR", "pe2XYR", 
07634                             maxbinX - minbinX + 1, h3->GetXaxis()->GetBinLowEdge(minbinX), h3->GetXaxis()->GetBinUpEdge(maxbinX), 
07635                             maxbinY - minbinY + 1, h3->GetYaxis()->GetBinLowEdge(minbinY), h3->GetYaxis()->GetBinUpEdge(maxbinY) );
07636    TProfile2D* pe2XZR = new TProfile2D("pe2XZR", "pe2XZR", 
07637                             maxbinX - minbinX + 1, h3->GetXaxis()->GetBinLowEdge(minbinX), h3->GetXaxis()->GetBinUpEdge(maxbinX), 
07638                             maxbinZ - minbinZ + 1, h3->GetZaxis()->GetBinLowEdge(minbinZ), h3->GetZaxis()->GetBinUpEdge(maxbinZ) );
07639    TProfile2D* pe2YXR = new TProfile2D("pe2YXR", "pe2YXR", 
07640                             maxbinY - minbinY + 1, h3->GetYaxis()->GetBinLowEdge(minbinY), h3->GetYaxis()->GetBinUpEdge(maxbinY),
07641                             maxbinX - minbinX + 1, h3->GetXaxis()->GetBinLowEdge(minbinX), h3->GetXaxis()->GetBinUpEdge(maxbinX) );
07642    TProfile2D* pe2YZR = new TProfile2D("pe2YZR", "pe2YZR",
07643                             maxbinY - minbinY + 1, h3->GetYaxis()->GetBinLowEdge(minbinY), h3->GetYaxis()->GetBinUpEdge(maxbinY),
07644                             maxbinZ - minbinZ + 1, h3->GetZaxis()->GetBinLowEdge(minbinZ), h3->GetZaxis()->GetBinUpEdge(maxbinZ) );
07645    TProfile2D* pe2ZXR = new TProfile2D("pe2ZXR", "pe2ZXR",
07646                             maxbinZ - minbinZ + 1, h3->GetZaxis()->GetBinLowEdge(minbinZ), h3->GetZaxis()->GetBinUpEdge(maxbinZ),
07647                             maxbinX - minbinX + 1, h3->GetXaxis()->GetBinLowEdge(minbinX), h3->GetXaxis()->GetBinUpEdge(maxbinX) );
07648    TProfile2D* pe2ZYR = new TProfile2D("pe2ZYR", "pe2ZYR", 
07649                             maxbinZ - minbinZ + 1, h3->GetZaxis()->GetBinLowEdge(minbinZ), h3->GetZaxis()->GetBinUpEdge(maxbinZ),
07650                             maxbinY - minbinY + 1, h3->GetYaxis()->GetBinLowEdge(minbinY), h3->GetYaxis()->GetBinUpEdge(maxbinY) );
07651 
07652    TProfile2D* pe2XYOR = new TProfile2D("pe2XYOR", "pe2XYOR", binsizeX, lower_limit, upper_limit, 
07653                                                               binsizeY, lower_limit, upper_limit);
07654    TProfile2D* pe2XZOR = new TProfile2D("pe2XZOR", "pe2XZOR", binsizeX, lower_limit, upper_limit, 
07655                                                               binsizeZ, lower_limit, upper_limit);
07656    TProfile2D* pe2YXOR = new TProfile2D("pe2YXOR", "pe2YXOR", binsizeY, lower_limit, upper_limit, 
07657                                                               binsizeX, lower_limit, upper_limit);
07658    TProfile2D* pe2YZOR = new TProfile2D("pe2YZOR", "pe2YZOR", binsizeY, lower_limit, upper_limit, 
07659                                                               binsizeZ, lower_limit, upper_limit);
07660    TProfile2D* pe2ZXOR = new TProfile2D("pe2ZXOR", "pe2ZXOR", binsizeZ, lower_limit, upper_limit, 
07661                                                               binsizeX, lower_limit, upper_limit);
07662    TProfile2D* pe2ZYOR = new TProfile2D("pe2ZYOR", "pe2ZYOR", binsizeZ, lower_limit, upper_limit, 
07663                                                               binsizeY, lower_limit, upper_limit);
07664 
07665    for ( int ix = 0; ix <= h3->GetXaxis()->GetNbins() + 1; ++ix ) {
07666       double xc = h3->GetXaxis()->GetBinCenter(ix);
07667       double x = xc + centre_deviation * h3->GetXaxis()->GetBinWidth(ix); 
07668       for ( int iy = 0; iy <= h3->GetYaxis()->GetNbins() + 1; ++iy ) {
07669          double yc = h3->GetYaxis()->GetBinCenter(iy);
07670          double y = yc + centre_deviation * h3->GetYaxis()->GetBinWidth(iy);
07671          for ( int iz = 0; iz <= h3->GetZaxis()->GetNbins() + 1; ++iz ) {
07672             double zc =  h3->GetZaxis()->GetBinCenter(iz);
07673             double z  = zc + centre_deviation * h3->GetZaxis()->GetBinWidth(iz);
07674             
07675 //    for ( int ix = 0; ix <= h3->GetXaxis()->GetNbins() + 1; ++ix ) {
07676 //       double x = centre_deviation * h3->GetXaxis()->GetBinWidth(ix) + h3->GetXaxis()->GetBinCenter(ix);
07677 //       for ( int iy = 0; iy <= h3->GetYaxis()->GetNbins() + 1; ++iy ) {
07678 //          double y = centre_deviation * h3->GetYaxis()->GetBinWidth(iy) + h3->GetYaxis()->GetBinCenter(iy);
07679 //          for ( int iz = 0; iz <= h3->GetZaxis()->GetNbins() + 1; ++iz ) {
07680 //             double z = centre_deviation * h3->GetZaxis()->GetBinWidth(iz) + h3->GetZaxis()->GetBinCenter(iz);
07681             Double_t w = (Double_t) r.Uniform(1,3);
07682          
07683             h3->Fill(x,y,z,w);
07684 
07685             h2XY->Fill(x,y,w);
07686             h2XZ->Fill(x,z,w);
07687             h2YX->Fill(y,x,w);
07688             h2YZ->Fill(y,z,w);
07689             h2ZX->Fill(z,x,w);
07690             h2ZY->Fill(z,y,w);
07691                
07692             pe2XY->Fill(xc,yc,zc,w);
07693             pe2XZ->Fill(xc,zc,yc,w);
07694             pe2YX->Fill(yc,xc,zc,w);
07695             pe2YZ->Fill(yc,zc,xc,w);
07696             pe2ZX->Fill(zc,xc,yc,w);
07697             pe2ZY->Fill(zc,yc,xc,w);
07698 
07699                if ( x >= h3->GetXaxis()->GetBinLowEdge(minbinX) &&
07700                     x <= h3->GetXaxis()->GetBinUpEdge(maxbinX)  && 
07701                     y >= h3->GetYaxis()->GetBinLowEdge(minbinY) &&
07702                     y <= h3->GetYaxis()->GetBinUpEdge(maxbinY)  &&
07703                     z >= h3->GetZaxis()->GetBinLowEdge(minbinZ) &&
07704                     z <= h3->GetZaxis()->GetBinUpEdge(maxbinZ) ) 
07705                {
07706                   h2XYR->Fill(x,y,w);
07707                   h2XZR->Fill(x,z,w);
07708                   h2YXR->Fill(y,x,w);
07709                   h2YZR->Fill(y,z,w);
07710                   h2ZXR->Fill(z,x,w);
07711                   h2ZYR->Fill(z,y,w);
07712 
07713                   h2XYOR->Fill(x,y,w);
07714                   h2XZOR->Fill(x,z,w);
07715                   h2YXOR->Fill(y,x,w);
07716                   h2YZOR->Fill(y,z,w);
07717                   h2ZXOR->Fill(z,x,w);
07718                   h2ZYOR->Fill(z,y,w);
07719 
07720                   pe2XYR->Fill(xc,yc,zc,w);
07721                   pe2XZR->Fill(xc,zc,yc,w);
07722                   pe2YXR->Fill(yc,xc,zc,w);
07723                   pe2YZR->Fill(yc,zc,xc,w);
07724                   pe2ZXR->Fill(zc,xc,yc,w);
07725                   pe2ZYR->Fill(zc,yc,xc,w);
07726 
07727                   pe2XYOR->Fill(xc,yc,zc,w);
07728                   pe2XZOR->Fill(xc,zc,yc,w);
07729                   pe2YXOR->Fill(yc,xc,zc,w);
07730                   pe2YZOR->Fill(yc,zc,xc,w);
07731                   pe2ZXOR->Fill(zc,xc,yc,w);
07732                   pe2ZYOR->Fill(zc,yc,xc,w);
07733                }
07734          }
07735       }
07736    }
07737    
07738    int status = 0;
07739    int options = cmpOptStats;
07740 
07741    options = cmpOptStats;
07742    status += equals("TH3 -> XY", h2XY, (TH2D*) h3->Project3D("yx"), options);
07743    status += equals("TH3 -> XZ", h2XZ, (TH2D*) h3->Project3D("zx"), options);
07744    status += equals("TH3 -> YX", h2YX, (TH2D*) h3->Project3D("XY"), options);
07745    status += equals("TH3 -> YZ", h2YZ, (TH2D*) h3->Project3D("ZY"), options);
07746    status += equals("TH3 -> ZX", h2ZX, (TH2D*) h3->Project3D("XZ"), options);
07747    status += equals("TH3 -> ZY", h2ZY, (TH2D*) h3->Project3D("YZ"), options);
07748    options = 0;
07749 
07750    options = cmpOptStats;
07751    status += equals("TH3O -> XY", h2XY, (TH2D*) h3->Project3D("oyx"), options);
07752    status += equals("TH3O -> XZ", h2XZ, (TH2D*) h3->Project3D("ozx"), options);
07753    status += equals("TH3O -> YX", h2YX, (TH2D*) h3->Project3D("oXY"), options);
07754    status += equals("TH3O -> YZ", h2YZ, (TH2D*) h3->Project3D("oZY"), options);
07755    status += equals("TH3O -> ZX", h2ZX, (TH2D*) h3->Project3D("oXZ"), options);
07756    status += equals("TH3O -> ZY", h2ZY, (TH2D*) h3->Project3D("oYZ"), options);
07757    options = 0; 
07758 
07759    options = cmpOptStats;
07760    status += equals("TH3 -> PXY", (TH2D*) pe2XY, (TH2D*) h3->Project3DProfile("yx  UF OF"), options);
07761    status += equals("TH3 -> PXZ", (TH2D*) pe2XZ, (TH2D*) h3->Project3DProfile("zx  UF OF"), options);
07762    status += equals("TH3 -> PYX", (TH2D*) pe2YX, (TH2D*) h3->Project3DProfile("xy  UF OF"), options);
07763    status += equals("TH3 -> PYZ", (TH2D*) pe2YZ, (TH2D*) h3->Project3DProfile("zy  UF OF"), options);
07764    status += equals("TH3 -> PZX", (TH2D*) pe2ZX, (TH2D*) h3->Project3DProfile("xz  UF OF"), options);
07765    status += equals("TH3 -> PZY", (TH2D*) pe2ZY, (TH2D*) h3->Project3DProfile("yz  UF OF"), options);
07766    options = 0;
07767 
07768    options = cmpOptStats;
07769    status += equals("TH3O -> PXY", (TH2D*) pe2XY, (TH2D*) h3->Project3DProfile("oyx  UF OF"), options);
07770    status += equals("TH3O -> PXZ", (TH2D*) pe2XZ, (TH2D*) h3->Project3DProfile("ozx  UF OF"), options);
07771    status += equals("TH3O -> PYX", (TH2D*) pe2YX, (TH2D*) h3->Project3DProfile("oxy  UF OF"), options);
07772    status += equals("TH3O -> PYZ", (TH2D*) pe2YZ, (TH2D*) h3->Project3DProfile("ozy  UF OF"), options);
07773    status += equals("TH3O -> PZX", (TH2D*) pe2ZX, (TH2D*) h3->Project3DProfile("oxz  UF OF"), options);
07774    status += equals("TH3O -> PZY", (TH2D*) pe2ZY, (TH2D*) h3->Project3DProfile("oyz  UF OF"), options);
07775    options = 0;   
07776 
07777    h3->GetXaxis()->SetRange(minbinX, maxbinX);
07778    h3->GetYaxis()->SetRange(minbinY, maxbinY);
07779    h3->GetZaxis()->SetRange(minbinZ, maxbinZ);
07780 
07781    // Stats won't work here, unless centre_deviation == 0.0
07782    options = 0;
07783    status += equals("TH3R -> XY", h2XYR, (TH2D*) h3->Project3D("yx"), options);
07784    status += equals("TH3R -> XZ", h2XZR, (TH2D*) h3->Project3D("zx"), options);
07785    status += equals("TH3R -> YX", h2YXR, (TH2D*) h3->Project3D("XY"), options);
07786    status += equals("TH3R -> YZ", h2YZR, (TH2D*) h3->Project3D("ZY"), options);
07787    status += equals("TH3R -> ZX", h2ZXR, (TH2D*) h3->Project3D("XZ"), options);
07788    status += equals("TH3R -> ZY", h2ZYR, (TH2D*) h3->Project3D("YZ"), options);
07789    options = 0;
07790 
07791    // Stats won't work here, unless centre_deviation == 0.0
07792    options = 0;
07793    status += equals("TH3OR -> XY", h2XYOR, (TH2D*) h3->Project3D("oyx"), options );
07794    status += equals("TH3OR -> XZ", h2XZOR, (TH2D*) h3->Project3D("ozx"), options);
07795    status += equals("TH3OR -> YX", h2YXOR, (TH2D*) h3->Project3D("oXY"), options);
07796    status += equals("TH3OR -> YZ", h2YZOR, (TH2D*) h3->Project3D("oZY"), options);
07797    status += equals("TH3OR -> ZX", h2ZXOR, (TH2D*) h3->Project3D("oXZ"), options);
07798    status += equals("TH3OR -> ZY", h2ZYOR, (TH2D*) h3->Project3D("oYZ"), options);
07799    options = 0;
07800 
07801    options = cmpOptStats;
07802    status += equals("TH3R -> PXY", (TH2D*) pe2XYR, (TH2D*) h3->Project3DProfile("yx  UF OF"), options);
07803    status += equals("TH3R -> PXZ", (TH2D*) pe2XZR, (TH2D*) h3->Project3DProfile("zx  UF OF"), options);
07804    status += equals("TH3R -> PYX", (TH2D*) pe2YXR, (TH2D*) h3->Project3DProfile("xy  UF OF"), options);
07805    status += equals("TH3R -> PYZ", (TH2D*) pe2YZR, (TH2D*) h3->Project3DProfile("zy  UF OF"), options);
07806    status += equals("TH3R -> PZX", (TH2D*) pe2ZXR, (TH2D*) h3->Project3DProfile("xz  UF OF"), options);
07807    status += equals("TH3R -> PZY", (TH2D*) pe2ZYR, (TH2D*) h3->Project3DProfile("yz  UF OF"), options);
07808    options = 0;
07809 
07810    options = cmpOptStats;
07811    status += equals("TH3OR -> PXY", (TH2D*) pe2XYOR, (TH2D*) h3->Project3DProfile("oyx  UF OF"), options);
07812    status += equals("TH3OR -> PXZ", (TH2D*) pe2XZOR, (TH2D*) h3->Project3DProfile("ozx  UF OF"), options);
07813    status += equals("TH3OR -> PYX", (TH2D*) pe2YXOR, (TH2D*) h3->Project3DProfile("oxy  UF OF"), options);
07814    status += equals("TH3OR -> PYZ", (TH2D*) pe2YZOR, (TH2D*) h3->Project3DProfile("ozy  UF OF"), options);
07815    status += equals("TH3OR -> PZX", (TH2D*) pe2ZXOR, (TH2D*) h3->Project3DProfile("oxz  UF OF"), options);
07816    status += equals("TH3OR -> PZY", (TH2D*) pe2ZYOR, (TH2D*) h3->Project3DProfile("oyz  UF OF"), options);
07817    options = 0;
07818 
07819    options = 0;
07820 
07821    delete h3;
07822 
07823    delete h2XY;
07824    delete h2XZ;
07825    delete h2YX;
07826    delete h2YZ;
07827    delete h2ZX;
07828    delete h2ZY;
07829 
07830    delete h2XYR;
07831    delete h2XZR;
07832    delete h2YXR;
07833    delete h2YZR;
07834    delete h2ZXR;
07835    delete h2ZYR;
07836 
07837    delete h2XYOR;
07838    delete h2XZOR;
07839    delete h2YXOR;
07840    delete h2YZOR;
07841    delete h2ZXOR;
07842    delete h2ZYOR;
07843 
07844    delete pe2XY;
07845    delete pe2XZ;
07846    delete pe2YX;
07847    delete pe2YZ;
07848    delete pe2ZX;
07849    delete pe2ZY;
07850 
07851    delete pe2XYR;
07852    delete pe2XZR;
07853    delete pe2YXR;
07854    delete pe2YZR;
07855    delete pe2ZXR;
07856    delete pe2ZYR;
07857 
07858    delete pe2XYOR;
07859    delete pe2XZOR;
07860    delete pe2YXOR;
07861    delete pe2YZOR;
07862    delete pe2ZXOR;
07863    delete pe2ZYOR;
07864 
07865    return status;
07866 }
07867 
07868 
07869 // In case of deviation, the profiles' content will not work anymore
07870 // try only for testing the statistics
07871 static const double centre_deviation = 0.3;
07872 
07873 
07874 class ProjectionTester {
07875    // This class implements the tests for all types of projections of
07876    // all the classes tested in this file.
07877 
07878 
07879 private:
07880    static const unsigned int binsizeX =  8;
07881    static const unsigned int binsizeY = 10;
07882    static const unsigned int binsizeZ = 12;
07883    static const int lower_limit = 0;
07884    static const int upper_limit = 10;
07885 
07886 
07887    TH3D* h3;
07888    TH2D* h2XY;
07889    TH2D* h2XZ;
07890    TH2D* h2YX;
07891    TH2D* h2YZ;
07892    TH2D* h2ZX;
07893    TH2D* h2ZY;
07894    TH1D* h1X;
07895    TH1D* h1Y;
07896    TH1D* h1Z;
07897 
07898    TH1D* h1XStats;
07899    TH1D* h1YStats;
07900    TH1D* h1ZStats;
07901    
07902    TProfile2D* pe2XY;
07903    TProfile2D* pe2XZ;
07904    TProfile2D* pe2YX;
07905    TProfile2D* pe2YZ;
07906    TProfile2D* pe2ZX;
07907    TProfile2D* pe2ZY;
07908    
07909    TH2D* h2wXY;
07910    TH2D* h2wXZ;
07911    TH2D* h2wYX;
07912    TH2D* h2wYZ;
07913    TH2D* h2wZX;
07914    TH2D* h2wZY;
07915    
07916    TProfile* pe1XY;
07917    TProfile* pe1XZ;
07918    TProfile* pe1YX;
07919    TProfile* pe1YZ;
07920    TProfile* pe1ZX;
07921    TProfile* pe1ZY;
07922 
07923    TH1D* hw1XZ;
07924    TH1D* hw1XY;
07925    TH1D* hw1YX;
07926    TH1D* hw1YZ;
07927    TH1D* hw1ZX;
07928    TH1D* hw1ZY;
07929    
07930    THnSparseD* s3;
07931 
07932    bool buildWithWeights;
07933 
07934    
07935 public:
07936    ProjectionTester()
07937    {
07938       CreateHistograms();
07939       buildWithWeights = false;
07940    }
07941    
07942    void CreateHistograms()
07943    {
07944       h3 = new TH3D("h3","h3", binsizeX, lower_limit, upper_limit, 
07945                                binsizeY, lower_limit, upper_limit, 
07946                                binsizeZ, lower_limit, upper_limit);
07947 
07948       h2XY = new TH2D("h2XY", "h2XY", binsizeX, lower_limit, upper_limit, 
07949                                       binsizeY, lower_limit, upper_limit);
07950       h2XZ = new TH2D("h2XZ", "h2XZ", binsizeX, lower_limit, upper_limit, 
07951                                       binsizeZ, lower_limit, upper_limit);
07952       h2YX = new TH2D("h2YX", "h2YX", binsizeY, lower_limit, upper_limit, 
07953                                       binsizeX, lower_limit, upper_limit);
07954       h2YZ = new TH2D("h2YZ", "h2YZ", binsizeY, lower_limit, upper_limit, 
07955                                       binsizeZ, lower_limit, upper_limit);
07956       h2ZX = new TH2D("h2ZX", "h2ZX", binsizeZ, lower_limit, upper_limit, 
07957                                       binsizeX, lower_limit, upper_limit);
07958       h2ZY = new TH2D("h2ZY", "h2ZY", binsizeZ, lower_limit, upper_limit, 
07959                                       binsizeY, lower_limit, upper_limit);
07960 
07961       // The bit is set for all the histograms (It's a statistic variable)
07962       TH1::StatOverflows(kTRUE);
07963 
07964       h1X = new TH1D("h1X", "h1X", binsizeX, lower_limit, upper_limit);
07965       h1Y = new TH1D("h1Y", "h1Y", binsizeY, lower_limit, upper_limit);
07966       h1Z = new TH1D("h1Z", "h1Z", binsizeZ, lower_limit, upper_limit);
07967 
07968       h1XStats = new TH1D("h1XStats", "h1XStats", binsizeX, lower_limit, upper_limit);
07969       h1YStats = new TH1D("h1YStats", "h1YStats", binsizeY, lower_limit, upper_limit);
07970       h1ZStats = new TH1D("h1ZStats", "h1ZStats", binsizeZ, lower_limit, upper_limit);
07971 
07972       pe2XY = new TProfile2D("pe2XY", "pe2XY", binsizeX, lower_limit, upper_limit, 
07973                                                binsizeY, lower_limit, upper_limit);
07974       pe2XZ = new TProfile2D("pe2XZ", "pe2XZ", binsizeX, lower_limit, upper_limit, 
07975                                                binsizeZ, lower_limit, upper_limit);
07976       pe2YX = new TProfile2D("pe2YX", "pe2YX", binsizeY, lower_limit, upper_limit, 
07977                                                binsizeX, lower_limit, upper_limit);
07978       pe2YZ = new TProfile2D("pe2YZ", "pe2YZ", binsizeY, lower_limit, upper_limit, 
07979                                                binsizeZ, lower_limit, upper_limit);
07980       pe2ZX = new TProfile2D("pe2ZX", "pe2ZX", binsizeZ, lower_limit, upper_limit, 
07981                                                binsizeX, lower_limit, upper_limit);
07982       pe2ZY = new TProfile2D("pe2ZY", "pe2ZY", binsizeZ, lower_limit, upper_limit, 
07983                                                binsizeY, lower_limit, upper_limit);
07984       
07985       h2wXY = new TH2D("h2wXY", "h2wXY", binsizeX, lower_limit, upper_limit, 
07986                                          binsizeY, lower_limit, upper_limit);
07987       h2wXZ = new TH2D("h2wXZ", "h2wXZ", binsizeX, lower_limit, upper_limit, 
07988                                          binsizeZ, lower_limit, upper_limit);
07989       h2wYX = new TH2D("h2wYX", "h2wYX", binsizeY, lower_limit, upper_limit, 
07990                                          binsizeX, lower_limit, upper_limit);
07991       h2wYZ = new TH2D("h2wYZ", "h2wYZ", binsizeY, lower_limit, upper_limit, 
07992                                          binsizeZ, lower_limit, upper_limit);
07993       h2wZX = new TH2D("h2wZX", "h2wZX", binsizeZ, lower_limit, upper_limit, 
07994                                          binsizeX, lower_limit, upper_limit);
07995       h2wZY = new TH2D("h2wZY", "h2wZY", binsizeZ, lower_limit, upper_limit, 
07996                                          binsizeY, lower_limit, upper_limit);
07997 
07998       h2wXY->Sumw2();
07999       h2wXZ->Sumw2();
08000       h2wYX->Sumw2();
08001       h2wYZ->Sumw2();
08002       h2wZX->Sumw2();
08003       h2wZY->Sumw2();
08004 
08005       pe1XY = new TProfile("pe1XY", "pe1XY", binsizeX, lower_limit, upper_limit);
08006       pe1XZ = new TProfile("pe1XZ", "pe1XZ", binsizeX, lower_limit, upper_limit);
08007       pe1YX = new TProfile("pe1YX", "pe1YX", binsizeY, lower_limit, upper_limit);
08008       pe1YZ = new TProfile("pe1YZ", "pe1YZ", binsizeY, lower_limit, upper_limit);
08009       pe1ZX = new TProfile("pe1ZX", "pe1ZX", binsizeZ, lower_limit, upper_limit);
08010       pe1ZY = new TProfile("pe1ZY", "pe1ZY", binsizeZ, lower_limit, upper_limit);
08011 
08012       hw1XY = new TH1D("hw1XY", "hw1XY", binsizeX, lower_limit, upper_limit);
08013       hw1XZ = new TH1D("hw1XZ", "hw1XZ", binsizeX, lower_limit, upper_limit);
08014       hw1YX = new TH1D("hw1YX", "hw1YX", binsizeY, lower_limit, upper_limit);
08015       hw1YZ = new TH1D("hw1YZ", "hw1YZ", binsizeY, lower_limit, upper_limit);
08016       hw1ZX = new TH1D("hw1ZX", "hw1ZX", binsizeZ, lower_limit, upper_limit);
08017       hw1ZY = new TH1D("hw1ZY", "hw1ZY", binsizeZ, lower_limit, upper_limit);
08018 
08019       hw1XZ->Sumw2();
08020       hw1XY->Sumw2();
08021       hw1YX->Sumw2();
08022       hw1YZ->Sumw2();
08023       hw1ZX->Sumw2();
08024       hw1ZY->Sumw2();
08025 
08026       Int_t bsize[] = {binsizeX, binsizeY, binsizeZ};
08027       Double_t xmin[] = {lower_limit, lower_limit, lower_limit};
08028       Double_t xmax[] = {upper_limit, upper_limit, upper_limit};
08029       s3 = new THnSparseD("s3","s3", 3, bsize, xmin, xmax);
08030 
08031    }
08032    
08033    void DeleteHistograms()
08034    {
08035       delete h3;
08036       
08037       delete h2XY;
08038       delete h2XZ;
08039       delete h2YX;
08040       delete h2YZ;
08041       delete h2ZX;
08042       delete h2ZY;
08043 
08044       delete h1X;
08045       delete h1Y;
08046       delete h1Z;
08047       
08048       delete h1XStats;
08049       delete h1YStats;
08050       delete h1ZStats;
08051 
08052       delete pe2XY;
08053       delete pe2XZ;
08054       delete pe2YX;
08055       delete pe2YZ;
08056       delete pe2ZX;
08057       delete pe2ZY;
08058       
08059       delete h2wXY;
08060       delete h2wXZ;
08061       delete h2wYX;
08062       delete h2wYZ;
08063       delete h2wZX;
08064       delete h2wZY;
08065 
08066       delete pe1XY;
08067       delete pe1XZ;
08068       delete pe1YX;
08069       delete pe1YZ;
08070       delete pe1ZY;
08071       delete pe1ZX;
08072 
08073       delete hw1XY;
08074       delete hw1XZ;
08075       delete hw1YX;
08076       delete hw1YZ;
08077       delete hw1ZX;
08078       delete hw1ZY;
08079 
08080       delete s3;
08081 
08082       // delete all histogram in gROOT
08083       TList * l = gROOT->GetList(); 
08084       TIter next(l);
08085       TObject * obj = 0; 
08086       while ((obj = next()))
08087          if (obj->InheritsFrom(TH1::Class()) ) delete obj; 
08088 
08089    }
08090    
08091    virtual ~ProjectionTester()
08092    {
08093       DeleteHistograms();
08094    }
08095    
08096    
08097    void buildHistograms()
08098    {
08099       if (h3->GetSumw2N() ) s3->Sumw2();
08100 
08101       for ( int ix = 0; ix <= h3->GetXaxis()->GetNbins() + 1; ++ix ) {
08102          double xc = h3->GetXaxis()->GetBinCenter(ix);
08103          double x = xc + centre_deviation * h3->GetXaxis()->GetBinWidth(ix); 
08104          for ( int iy = 0; iy <= h3->GetYaxis()->GetNbins() + 1; ++iy ) {
08105             double yc = h3->GetYaxis()->GetBinCenter(iy);
08106             double y = yc + centre_deviation * h3->GetYaxis()->GetBinWidth(iy);
08107             for ( int iz = 0; iz <= h3->GetZaxis()->GetNbins() + 1; ++iz ) {
08108                double zc =  h3->GetZaxis()->GetBinCenter(iz);
08109                double z  = zc + centre_deviation * h3->GetZaxis()->GetBinWidth(iz);
08110                for ( int i = 0; i < (int) r.Uniform(1,3); ++i )
08111                {
08112                   h3->Fill(x,y,z);
08113 
08114                   Double_t points[] = {x,y,z};
08115                   s3->Fill(points);
08116                   
08117                   h2XY->Fill(x,y);
08118                   h2XZ->Fill(x,z);
08119                   h2YX->Fill(y,x);
08120                   h2YZ->Fill(y,z);
08121                   h2ZX->Fill(z,x);
08122                   h2ZY->Fill(z,y);
08123                   
08124                   h1X->Fill(x);
08125                   h1Y->Fill(y);
08126                   h1Z->Fill(z);
08127 
08128                   if ( ix > 0 && ix < h3->GetXaxis()->GetNbins() + 1 &&
08129                        iy > 0 && iy < h3->GetYaxis()->GetNbins() + 1 &&
08130                        iz > 0 && iz < h3->GetZaxis()->GetNbins() + 1 )
08131                   {
08132                      h1XStats->Fill(x);
08133                      h1YStats->Fill(y);
08134                      h1ZStats->Fill(z);
08135                   }
08136 
08137                   // for filling reference profile need to use bin center 
08138                   // because projection from histogram can use only bin center 
08139                   pe2XY->Fill(xc,yc,zc);
08140                   pe2XZ->Fill(xc,zc,yc);
08141                   pe2YX->Fill(yc,xc,zc);
08142                   pe2YZ->Fill(yc,zc,xc);
08143                   pe2ZX->Fill(zc,xc,yc);
08144                   pe2ZY->Fill(zc,yc,xc);
08145                   
08146                   // reference histogram to test with option W. 
08147                   // need to use bin center for the weight
08148                   h2wXY->Fill(x,y,zc);
08149                   h2wXZ->Fill(x,z,yc);
08150                   h2wYX->Fill(y,x,zc);
08151                   h2wYZ->Fill(y,z,xc);
08152                   h2wZX->Fill(z,x,yc);
08153                   h2wZY->Fill(z,y,xc);
08154 
08155                   pe1XY->Fill(xc,yc);
08156                   pe1XZ->Fill(xc,zc);
08157                   pe1YX->Fill(yc,xc);
08158                   pe1YZ->Fill(yc,zc);
08159                   pe1ZX->Fill(zc,xc);
08160                   pe1ZY->Fill(zc,yc);
08161 
08162                   hw1XY->Fill(x,yc);
08163                   hw1XZ->Fill(x,zc);
08164                   hw1YX->Fill(y,xc);
08165                   hw1YZ->Fill(y,zc);
08166                   hw1ZX->Fill(z,xc);
08167                   hw1ZY->Fill(z,yc);
08168                }
08169             }
08170          }
08171       }
08172 
08173       buildWithWeights = false;
08174    }
08175 
08176    void buildHistogramsWithWeights()
08177    {
08178       s3->Sumw2();
08179 
08180       for ( int ix = 0; ix <= h3->GetXaxis()->GetNbins() + 1; ++ix ) {
08181          double xc = h3->GetXaxis()->GetBinCenter(ix);
08182          double x = xc + centre_deviation * h3->GetXaxis()->GetBinWidth(ix); 
08183          for ( int iy = 0; iy <= h3->GetYaxis()->GetNbins() + 1; ++iy ) {
08184             double yc = h3->GetYaxis()->GetBinCenter(iy);
08185             double y = yc + centre_deviation * h3->GetYaxis()->GetBinWidth(iy);
08186             for ( int iz = 0; iz <= h3->GetZaxis()->GetNbins() + 1; ++iz ) {
08187                double zc =  h3->GetZaxis()->GetBinCenter(iz);
08188                double z  = zc + centre_deviation * h3->GetZaxis()->GetBinWidth(iz);
08189 
08190                Double_t w = (Double_t) r.Uniform(1,3);
08191 
08192                h3->Fill(x,y,z,w);
08193 
08194                Double_t points[] = {x,y,z};
08195                s3->Fill(points,w);
08196                
08197                h2XY->Fill(x,y,w);
08198                h2XZ->Fill(x,z,w);
08199                h2YX->Fill(y,x,w);
08200                h2YZ->Fill(y,z,w);
08201                h2ZX->Fill(z,x,w);
08202                h2ZY->Fill(z,y,w);
08203                
08204                h1X->Fill(x,w);
08205                h1Y->Fill(y,w);
08206                h1Z->Fill(z,w);
08207                    
08208                if ( ix > 0 && ix < h3->GetXaxis()->GetNbins() + 1 &&
08209                     iy > 0 && iy < h3->GetYaxis()->GetNbins() + 1 &&
08210                     iz > 0 && iz < h3->GetZaxis()->GetNbins() + 1 )
08211                {
08212                   h1XStats->Fill(x,w);
08213                   h1YStats->Fill(y,w);
08214                   h1ZStats->Fill(z,w);
08215                }              
08216 
08217                pe2XY->Fill(xc,yc,zc,w);
08218                pe2XZ->Fill(xc,zc,yc,w);
08219                pe2YX->Fill(yc,xc,zc,w);
08220                pe2YZ->Fill(yc,zc,xc,w);
08221                pe2ZX->Fill(zc,xc,yc,w);
08222                pe2ZY->Fill(zc,yc,xc,w);
08223                
08224                h2wXY->Fill(x,y,zc*w);
08225                h2wXZ->Fill(x,z,yc*w);
08226                h2wYX->Fill(y,x,zc*w);
08227                h2wYZ->Fill(y,z,xc*w);
08228                h2wZX->Fill(z,x,yc*w);
08229                h2wZY->Fill(z,y,xc*w);
08230                
08231                pe1XY->Fill(xc,yc,w);
08232                pe1XZ->Fill(xc,zc,w);
08233                pe1YX->Fill(yc,xc,w);
08234                pe1YZ->Fill(yc,zc,w);
08235                pe1ZX->Fill(zc,xc,w);
08236                pe1ZY->Fill(zc,yc,w);
08237                
08238                hw1XY->Fill(x,yc*w);
08239                hw1XZ->Fill(x,zc*w);
08240                hw1YX->Fill(y,xc*w);
08241                hw1YZ->Fill(y,zc*w);
08242                hw1ZX->Fill(z,xc*w);
08243                hw1ZY->Fill(z,yc*w);
08244             }
08245          }
08246       }
08247 
08248       buildWithWeights = true;
08249    }
08250    
08251    void buildHistograms(int xmin, int xmax,
08252                         int ymin, int ymax,
08253                         int zmin, int zmax)
08254    {
08255       for ( int ix = 0; ix <= h3->GetXaxis()->GetNbins() + 1; ++ix ) {
08256          double xc = h3->GetXaxis()->GetBinCenter(ix);
08257          double x = xc + centre_deviation * h3->GetXaxis()->GetBinWidth(ix); 
08258          for ( int iy = 0; iy <= h3->GetYaxis()->GetNbins() + 1; ++iy ) {
08259             double yc = h3->GetYaxis()->GetBinCenter(iy);
08260             double y = yc + centre_deviation * h3->GetYaxis()->GetBinWidth(iy);
08261             for ( int iz = 0; iz <= h3->GetZaxis()->GetNbins() + 1; ++iz ) {
08262                double zc =  h3->GetZaxis()->GetBinCenter(iz);
08263                double z  = zc + centre_deviation * h3->GetZaxis()->GetBinWidth(iz);
08264 
08265                for ( int i = 0; i < (int) r.Uniform(1,3); ++i )
08266                {
08267                   h3->Fill(x,y,z);
08268 
08269                   Double_t points[] = {x,y,z};
08270                   s3->Fill(points);
08271                   
08272                   if ( h3->GetXaxis()->FindBin(x) >= xmin && h3->GetXaxis()->FindBin(x) <= xmax &&
08273                        h3->GetYaxis()->FindBin(y) >= ymin && h3->GetYaxis()->FindBin(y) <= ymax &&
08274                        h3->GetZaxis()->FindBin(z) >= zmin && h3->GetZaxis()->FindBin(z) <= zmax )
08275                   {
08276                      if ( defaultEqualOptions & cmpOptPrint )
08277                         cout << "Filling (" << x << "," << y << "," << z << ")!" << endl;
08278                      
08279                      h2XY->Fill(x,y);
08280                      h2XZ->Fill(x,z);
08281                      h2YX->Fill(y,x);
08282                      h2YZ->Fill(y,z);
08283                      h2ZX->Fill(z,x);
08284                      h2ZY->Fill(z,y);
08285                      
08286                      h1X->Fill(x);
08287                      h1Y->Fill(y);
08288                      h1Z->Fill(z);
08289                      
08290                      pe2XY->Fill(xc,yc,zc);
08291                      pe2XZ->Fill(xc,zc,yc);
08292                      pe2YX->Fill(yc,xc,zc);
08293                      pe2YZ->Fill(yc,zc,xc);
08294                      pe2ZX->Fill(zc,xc,yc);
08295                      pe2ZY->Fill(zc,yc,xc);
08296                      
08297                      h2wXY->Fill(x,y,z);
08298                      h2wXZ->Fill(x,z,y);
08299                      h2wYX->Fill(y,x,z);
08300                      h2wYZ->Fill(y,z,x);
08301                      h2wZX->Fill(z,x,y);
08302                      h2wZY->Fill(z,y,x);
08303 
08304                      pe1XY->Fill(xc,yc);
08305                      pe1XZ->Fill(xc,zc);
08306                      pe1YX->Fill(yc,xc);
08307                      pe1YZ->Fill(yc,zc);
08308                      pe1ZX->Fill(zc,xc);
08309                      pe1ZY->Fill(zc,yc);
08310                      
08311                      hw1XY->Fill(x,y);
08312                      hw1XZ->Fill(x,z);
08313                      hw1YX->Fill(y,x);
08314                      hw1YZ->Fill(y,z);
08315                      hw1ZX->Fill(z,x);
08316                      hw1ZY->Fill(z,y);
08317                   }
08318                }
08319             }
08320          }
08321       }
08322       
08323       h3->GetXaxis()->SetRange(xmin, xmax);
08324       h3->GetYaxis()->SetRange(ymin, ymax);
08325       h3->GetZaxis()->SetRange(zmin, zmax);
08326       
08327       h2XY->GetXaxis()->SetRange(xmin, xmax);
08328       h2XY->GetYaxis()->SetRange(ymin, ymax);
08329       
08330       h2XZ->GetXaxis()->SetRange(xmin, xmax);
08331       h2XZ->GetZaxis()->SetRange(zmin, zmax);
08332       
08333       h2YX->GetYaxis()->SetRange(ymin, ymax);
08334       h2YX->GetXaxis()->SetRange(xmin, xmax);
08335       
08336       h2YZ->GetYaxis()->SetRange(ymin, ymax);
08337       h2YZ->GetZaxis()->SetRange(zmin, zmax);
08338       
08339       h2ZX->GetZaxis()->SetRange(zmin, zmax);
08340       h2ZX->GetXaxis()->SetRange(xmin, xmax);
08341       
08342       h2ZY->GetZaxis()->SetRange(zmin, zmax);
08343       h2ZY->GetYaxis()->SetRange(ymin, ymax);
08344       
08345       h1X->GetXaxis()->SetRange(xmin, xmax);
08346       h1Y->GetXaxis()->SetRange(ymin, ymax);
08347       h1Z->GetXaxis()->SetRange(zmin, zmax);
08348 
08349       // Neet to set up the rest of the ranges!
08350 
08351       s3->GetAxis(1)->SetRange(xmin, xmax);
08352       s3->GetAxis(2)->SetRange(ymin, ymax);
08353       s3->GetAxis(3)->SetRange(zmin, zmax);
08354 
08355       buildWithWeights = false;
08356    }
08357    
08358    int compareHistograms()
08359    {
08360       int status = 0;
08361       int options = 0;
08362       
08363       // TH2 derived from TH3
08364       options = cmpOptStats;
08365       status += equals("TH3 -> XY", h2XY, (TH2D*) h3->Project3D("yx"), options);
08366       status += equals("TH3 -> XZ", h2XZ, (TH2D*) h3->Project3D("zx"), options);
08367       status += equals("TH3 -> YX", h2YX, (TH2D*) h3->Project3D("XY"), options);
08368       status += equals("TH3 -> YZ", h2YZ, (TH2D*) h3->Project3D("ZY"), options);
08369       status += equals("TH3 -> ZX", h2ZX, (TH2D*) h3->Project3D("XZ"), options);
08370       status += equals("TH3 -> ZY", h2ZY, (TH2D*) h3->Project3D("YZ"), options);
08371       options = 0;
08372       if ( defaultEqualOptions & cmpOptPrint )
08373          cout << "----------------------------------------------" << endl;
08374       
08375       // TH1 derived from TH3
08376       options = cmpOptStats;
08377       TH1D* tmp1 = 0;
08378       status += equals("TH3 -> X", h1X, (TH1D*) h3->Project3D("x"), options);
08379       tmp1 = h3->ProjectionX("x335");
08380       status += equals("TH3 -> X(x2)", tmp1, (TH1D*) h3->Project3D("x2"), options);
08381       delete tmp1; tmp1 = 0;
08382       status += equals("TH3 -> Y", h1Y, (TH1D*) h3->Project3D("y"), options);
08383       tmp1 = h3->ProjectionY("y335");
08384       status += equals("TH3 -> Y(x2)", tmp1, (TH1D*) h3->Project3D("y2"), options);
08385       delete tmp1; tmp1 = 0;
08386       status += equals("TH3 -> Z", h1Z, (TH1D*) h3->Project3D("z"), options);
08387       tmp1 = h3->ProjectionZ("z335");
08388       status += equals("TH3 -> Z(x2)", tmp1, (TH1D*) h3->Project3D("z2"), options);
08389       delete tmp1; tmp1 = 0;
08390 
08391       options = 0;
08392       if ( defaultEqualOptions & cmpOptPrint )
08393          cout << "----------------------------------------------" << endl;
08394       
08395       // TH1 derived from h2XY
08396       options = cmpOptStats;
08397       status += equals("TH2XY -> X", h1X, (TH1D*) h2XY->ProjectionX("x"), options);
08398       status += equals("TH2XY -> Y", h1Y, (TH1D*) h2XY->ProjectionY("y"), options);
08399       // TH1 derived from h2XZ
08400       status += equals("TH2XZ -> X", h1X, (TH1D*) h2XZ->ProjectionX("x"), options);
08401       status += equals("TH2XZ -> Z", h1Z, (TH1D*) h2XZ->ProjectionY("z"), options);
08402       // TH1 derived from h2YX
08403       status += equals("TH2YX -> Y", h1Y, (TH1D*) h2YX->ProjectionX("y"), options);
08404       status += equals("TH2YX -> X", h1X, (TH1D*) h2YX->ProjectionY("x"), options);
08405       // TH1 derived from h2YZ
08406       status += equals("TH2YZ -> Y", h1Y, (TH1D*) h2YZ->ProjectionX("y"), options);
08407       status += equals("TH2YZ -> Z", h1Z, (TH1D*) h2YZ->ProjectionY("z"), options);
08408       // TH1 derived from h2ZX
08409       status += equals("TH2ZX -> Z", h1Z, (TH1D*) h2ZX->ProjectionX("z"), options);
08410       status += equals("TH2ZX -> X", h1X, (TH1D*) h2ZX->ProjectionY("x"), options);
08411       // TH1 derived from h2ZY
08412       status += equals("TH2ZY -> Z", h1Z, (TH1D*) h2ZY->ProjectionX("z"), options);
08413       status += equals("TH2ZY -> Y", h1Y, (TH1D*) h2ZY->ProjectionY("y"), options);
08414       options = 0;
08415       if ( defaultEqualOptions & cmpOptPrint )
08416          cout << "----------------------------------------------" << endl;
08417 
08418       // in the following comparison with profiles we need to re-calculate statistics using bin centers 
08419       // on the reference histograms
08420       if (centre_deviation != 0) { 
08421          h2XY->ResetStats();      
08422          h2YX->ResetStats();
08423          h2XZ->ResetStats();      
08424          h2ZX->ResetStats();
08425          h2YZ->ResetStats();      
08426          h2ZY->ResetStats();
08427 
08428          h1X->ResetStats(); 
08429          h1Y->ResetStats(); 
08430          h1Z->ResetStats(); 
08431       }
08432       
08433       // Now the histograms comming from the Profiles!
08434       options = cmpOptStats;
08435       status += equals("TH3 -> PBXY", h2XY, (TH2D*) h3->Project3DProfile("yx UF OF")->ProjectionXY("1", "B"), options  );
08436       status += equals("TH3 -> PBXZ", h2XZ, (TH2D*) h3->Project3DProfile("zx UF OF")->ProjectionXY("2", "B"), options);
08437       status += equals("TH3 -> PBYX", h2YX, (TH2D*) h3->Project3DProfile("xy UF OF")->ProjectionXY("3", "B"), options);
08438       status += equals("TH3 -> PBYZ", h2YZ, (TH2D*) h3->Project3DProfile("zy UF OF")->ProjectionXY("4", "B"), options);
08439       status += equals("TH3 -> PBZX", h2ZX, (TH2D*) h3->Project3DProfile("xz UF OF")->ProjectionXY("5", "B"), options);
08440       status += equals("TH3 -> PBZY", h2ZY, (TH2D*) h3->Project3DProfile("yz UF OF")->ProjectionXY("6", "B"), options);
08441       options = 0;
08442       if ( defaultEqualOptions & cmpOptPrint )
08443          cout << "----------------------------------------------" << endl;
08444       
08445       // test directly project3dprofile
08446       options = cmpOptStats;
08447       status += equals("TH3 -> PXY", (TH2D*) pe2XY, (TH2D*) h3->Project3DProfile("yx  UF OF"), options);
08448       status += equals("TH3 -> PXZ", (TH2D*) pe2XZ, (TH2D*) h3->Project3DProfile("zx  UF OF"), options);
08449       status += equals("TH3 -> PYX", (TH2D*) pe2YX, (TH2D*) h3->Project3DProfile("xy  UF OF"), options);
08450       status += equals("TH3 -> PYZ", (TH2D*) pe2YZ, (TH2D*) h3->Project3DProfile("zy  UF OF"), options);
08451       status += equals("TH3 -> PZX", (TH2D*) pe2ZX, (TH2D*) h3->Project3DProfile("xz  UF OF"), options);
08452       status += equals("TH3 -> PZY", (TH2D*) pe2ZY, (TH2D*) h3->Project3DProfile("yz  UF OF"), options);
08453       options = 0;
08454       if ( defaultEqualOptions & cmpOptPrint )
08455          cout << "----------------------------------------------" << endl;
08456       
08457       // test option E of ProjectionXY
08458       options = 0;
08459       status += equals("TH3 -> PEXY", (TH2D*) pe2XY, (TH2D*) h3->Project3DProfile("yx  UF OF")->ProjectionXY("1", "E"), options);
08460       status += equals("TH3 -> PEXZ", (TH2D*) pe2XZ, (TH2D*) h3->Project3DProfile("zx  UF OF")->ProjectionXY("2", "E"), options);
08461       status += equals("TH3 -> PEYX", (TH2D*) pe2YX, (TH2D*) h3->Project3DProfile("xy  UF OF")->ProjectionXY("3", "E"), options);
08462       status += equals("TH3 -> PEYZ", (TH2D*) pe2YZ, (TH2D*) h3->Project3DProfile("zy  UF OF")->ProjectionXY("4", "E"), options);
08463       status += equals("TH3 -> PEZX", (TH2D*) pe2ZX, (TH2D*) h3->Project3DProfile("xz  UF OF")->ProjectionXY("5", "E"), options);
08464       status += equals("TH3 -> PEZY", (TH2D*) pe2ZY, (TH2D*) h3->Project3DProfile("yz  UF OF")->ProjectionXY("6", "E"), options);
08465       options = 0;
08466       if ( defaultEqualOptions & cmpOptPrint )
08467          cout << "----------------------------------------------" << endl;
08468       
08469       // test option W of ProjectionXY
08470       
08471       // The error fails when built with weights. It is not properly calculated
08472       if ( buildWithWeights ) options = cmpOptNoError;
08473       status += equals("TH3 -> PWXY", (TH2D*) h2wXY, (TH2D*) h3->Project3DProfile("yx  UF OF")->ProjectionXY("1", "W"), options);
08474       status += equals("TH3 -> PWXZ", (TH2D*) h2wXZ, (TH2D*) h3->Project3DProfile("zx  UF OF")->ProjectionXY("2", "W"), options);
08475       status += equals("TH3 -> PWYX", (TH2D*) h2wYX, (TH2D*) h3->Project3DProfile("xy  UF OF")->ProjectionXY("3", "W"), options);
08476       status += equals("TH3 -> PWYZ", (TH2D*) h2wYZ, (TH2D*) h3->Project3DProfile("zy  UF OF")->ProjectionXY("4", "W"), options);
08477       status += equals("TH3 -> PWZX", (TH2D*) h2wZX, (TH2D*) h3->Project3DProfile("xz  UF OF")->ProjectionXY("5", "W"), options);
08478       status += equals("TH3 -> PWZY", (TH2D*) h2wZY, (TH2D*) h3->Project3DProfile("yz  UF OF")->ProjectionXY("6", "W"), options);
08479       options = 0;
08480       if ( defaultEqualOptions & cmpOptPrint )
08481          cout << "----------------------------------------------" << endl;
08482       
08483       // test 1D histograms
08484       options = cmpOptStats;
08485       // ProfileX re-use the same histo if sme name is given. 
08486       // need to give a diffrent name for each projectino (x,y,Z) otherwise we end-up in different bins
08487       // t.b.d: ProfileX make a new histo if non compatible
08488       status += equals("TH2XY -> PBX", h1X, (TH1D*) h2XY->ProfileX("PBX", 0,h2XY->GetYaxis()->GetNbins()+1)->ProjectionX("1", "B"),options  );
08489       status += equals("TH2XY -> PBY", h1Y, (TH1D*) h2XY->ProfileY("PBY", 0,h2XY->GetXaxis()->GetNbins()+1)->ProjectionX("1", "B"),options);
08490       status += equals("TH2XZ -> PBX", h1X, (TH1D*) h2XZ->ProfileX("PBX", 0,h2XZ->GetYaxis()->GetNbins()+1)->ProjectionX("1", "B"),options);
08491       status += equals("TH2XZ -> PBZ", h1Z, (TH1D*) h2XZ->ProfileY("PBZ", 0,h2XZ->GetXaxis()->GetNbins()+1)->ProjectionX("1", "B"),options,1E-12);
08492       status += equals("TH2YX -> PBY", h1Y, (TH1D*) h2YX->ProfileX("PBY", 0,h2YX->GetYaxis()->GetNbins()+1)->ProjectionX("1", "B"),options);
08493       status += equals("TH2YX -> PBX", h1X, (TH1D*) h2YX->ProfileY("PBX", 0,h2YX->GetXaxis()->GetNbins()+1)->ProjectionX("1", "B"),options);
08494       status += equals("TH2YZ -> PBY", h1Y, (TH1D*) h2YZ->ProfileX("PBY", 0,h2YZ->GetYaxis()->GetNbins()+1)->ProjectionX("1", "B"),options);
08495       status += equals("TH2YZ -> PBZ", h1Z, (TH1D*) h2YZ->ProfileY("PBZ", 0,h2YZ->GetXaxis()->GetNbins()+1)->ProjectionX("1", "B"),options,1E-12);
08496       status += equals("TH2ZX -> PBZ", h1Z, (TH1D*) h2ZX->ProfileX("PBZ", 0,h2ZX->GetYaxis()->GetNbins()+1)->ProjectionX("1", "B"),options,1E-12);
08497       status += equals("TH2ZX -> PBX", h1X, (TH1D*) h2ZX->ProfileY("PBX", 0,h2ZX->GetXaxis()->GetNbins()+1)->ProjectionX("1", "B"),options);
08498       status += equals("TH2ZY -> PBZ", h1Z, (TH1D*) h2ZY->ProfileX("PBZ", 0,h2ZY->GetYaxis()->GetNbins()+1)->ProjectionX("1", "B"),options,1E-12);
08499       status += equals("TH2ZY -> PBY", h1Y, (TH1D*) h2ZY->ProfileY("PBY", 0,h2ZY->GetXaxis()->GetNbins()+1)->ProjectionX("1", "B"),options);
08500       options = 0;
08501       if ( defaultEqualOptions & cmpOptPrint )
08502          cout << "----------------------------------------------" << endl;
08503 
08504       // 1D testing direct profiles 
08505       options = cmpOptStats;
08506       status += equals("TH2XY -> PX", pe1XY, (TH1D*) h2XY->ProfileX("PX", 0,h2XY->GetYaxis()->GetNbins()+1), options);
08507       status += equals("TH2XY -> PY", pe1YX, (TH1D*) h2XY->ProfileY("PY", 0,h2XY->GetXaxis()->GetNbins()+1), options);
08508       status += equals("TH2XZ -> PX", pe1XZ, (TH1D*) h2XZ->ProfileX("PX", 0,h2XZ->GetYaxis()->GetNbins()+1), options);
08509       status += equals("TH2XZ -> PZ", pe1ZX, (TH1D*) h2XZ->ProfileY("PZ", 0,h2XZ->GetXaxis()->GetNbins()+1), options);
08510       status += equals("TH2YX -> PY", pe1YX, (TH1D*) h2YX->ProfileX("PY", 0,h2YX->GetYaxis()->GetNbins()+1), options);
08511       status += equals("TH2YX -> PX", pe1XY, (TH1D*) h2YX->ProfileY("PX", 0,h2YX->GetXaxis()->GetNbins()+1), options);
08512       status += equals("TH2YZ -> PY", pe1YZ, (TH1D*) h2YZ->ProfileX("PY", 0,h2YZ->GetYaxis()->GetNbins()+1), options);
08513       status += equals("TH2YZ -> PZ", pe1ZY, (TH1D*) h2YZ->ProfileY("PZ", 0,h2YZ->GetXaxis()->GetNbins()+1), options);
08514       status += equals("TH2ZX -> PZ", pe1ZX, (TH1D*) h2ZX->ProfileX("PZ", 0,h2ZX->GetYaxis()->GetNbins()+1), options);
08515       status += equals("TH2ZX -> PX", pe1XZ, (TH1D*) h2ZX->ProfileY("PX", 0,h2ZX->GetXaxis()->GetNbins()+1), options);
08516       status += equals("TH2ZY -> PZ", pe1ZY, (TH1D*) h2ZY->ProfileX("PZ", 0,h2ZY->GetYaxis()->GetNbins()+1), options);
08517       status += equals("TH2ZY -> PY", pe1YZ, (TH1D*) h2ZY->ProfileY("PY", 0,h2ZY->GetXaxis()->GetNbins()+1), options);
08518       options = 0;
08519       if ( defaultEqualOptions & cmpOptPrint )
08520          cout << "----------------------------------------------" << endl;
08521 
08522       // 1D testing e profiles
08523       options = 0;
08524       status += equals("TH2XY -> PEX", pe1XY, 
08525                        (TH1D*) h2XY->ProfileX("PEX", 0,h2XY->GetYaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08526       status += equals("TH2XY -> PEY", pe1YX, 
08527                        (TH1D*) h2XY->ProfileY("PEY", 0,h2XY->GetXaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08528       status += equals("TH2XZ -> PEX", pe1XZ, 
08529                        (TH1D*) h2XZ->ProfileX("PEX", 0,h2XZ->GetYaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08530       status += equals("TH2XZ -> PEZ", pe1ZX, 
08531                        (TH1D*) h2XZ->ProfileY("PEZ", 0,h2XZ->GetXaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08532       status += equals("TH2YX -> PEY", pe1YX, 
08533                        (TH1D*) h2YX->ProfileX("PEY", 0,h2YX->GetYaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08534       status += equals("TH2YX -> PEX", pe1XY, 
08535                        (TH1D*) h2YX->ProfileY("PEX", 0,h2YX->GetXaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08536       status += equals("TH2YZ -> PEY", pe1YZ, 
08537                        (TH1D*) h2YZ->ProfileX("PEY", 0,h2YZ->GetYaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08538       status += equals("TH2YZ -> PEZ", pe1ZY, 
08539                        (TH1D*) h2YZ->ProfileY("PEZ", 0,h2YZ->GetXaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08540       status += equals("TH2ZX -> PEZ", pe1ZX, 
08541                        (TH1D*) h2ZX->ProfileX("PEZ", 0,h2ZX->GetYaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08542       status += equals("TH2ZX -> PEX", pe1XZ, 
08543                        (TH1D*) h2ZX->ProfileY("PEX", 0,h2ZX->GetXaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08544       status += equals("TH2ZY -> PEZ", pe1ZY, 
08545                        (TH1D*) h2ZY->ProfileX("PEZ", 0,h2ZY->GetYaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08546       status += equals("TH2ZY -> PEY", pe1YZ, 
08547                        (TH1D*) h2ZY->ProfileY("PEY", 0,h2ZY->GetXaxis()->GetNbins()+1)->ProjectionX("1", "E"), options);
08548       options = 0;
08549       if ( defaultEqualOptions & cmpOptPrint )
08550          cout << "----------------------------------------------" << endl;
08551 
08552       // 1D testing w profiles
08553       // The error is not properly propagated when build with weights :S
08554       if ( buildWithWeights ) options = cmpOptNoError;
08555       status += equals("TH2XY -> PWX", hw1XY, 
08556                        (TH1D*) h2XY->ProfileX("PWX", 0,h2XY->GetYaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08557       status += equals("TH2XY -> PWY", hw1YX, 
08558                        (TH1D*) h2XY->ProfileY("PWY", 0,h2XY->GetXaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08559       status += equals("TH2XZ -> PWX", hw1XZ, 
08560                        (TH1D*) h2XZ->ProfileX("PWX", 0,h2XZ->GetYaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08561       status += equals("TH2XZ -> PWZ", hw1ZX, 
08562                        (TH1D*) h2XZ->ProfileY("PWZ", 0,h2XZ->GetXaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08563       status += equals("TH2YX -> PWY", hw1YX, 
08564                        (TH1D*) h2YX->ProfileX("PWY", 0,h2YX->GetYaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08565       status += equals("TH2YX -> PWX", hw1XY, 
08566                        (TH1D*) h2YX->ProfileY("PWX", 0,h2YX->GetXaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08567       status += equals("TH2YZ -> PWY", hw1YZ, 
08568                        (TH1D*) h2YZ->ProfileX("PWY", 0,h2YZ->GetYaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08569       status += equals("TH2YZ -> PWZ", hw1ZY, 
08570                        (TH1D*) h2YZ->ProfileY("PWZ", 0,h2YZ->GetXaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08571       status += equals("TH2ZX -> PWZ", hw1ZX, 
08572                        (TH1D*) h2ZX->ProfileX("PWZ", 0,h2ZX->GetYaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08573       status += equals("TH2ZX -> PWX", hw1XZ, 
08574                        (TH1D*) h2ZX->ProfileY("PWX", 0,h2ZX->GetXaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08575       status += equals("TH2ZY -> PWZ", hw1ZY, 
08576                        (TH1D*) h2ZY->ProfileX("PWZ", 0,h2ZY->GetYaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08577       status += equals("TH2ZY -> PWY", hw1YZ, 
08578                        (TH1D*) h2ZY->ProfileY("PWY", 0,h2ZY->GetXaxis()->GetNbins()+1)->ProjectionX("1", "W"), options);
08579 
08580       options = 0;
08581       if ( defaultEqualOptions & cmpOptPrint )
08582          cout << "----------------------------------------------" << endl;
08583       
08584       // TH2 derived from STH3
08585       options = cmpOptStats;
08586       status += equals("STH3 -> XY", h2XY, (TH2D*) s3->Projection(1,0), options);
08587       status += equals("STH3 -> XZ", h2XZ, (TH2D*) s3->Projection(2,0), options);
08588       status += equals("STH3 -> YX", h2YX, (TH2D*) s3->Projection(0,1), options);
08589       status += equals("STH3 -> YZ", h2YZ, (TH2D*) s3->Projection(2,1), options);
08590       status += equals("STH3 -> ZX", h2ZX, (TH2D*) s3->Projection(0,2), options); 
08591       status += equals("STH3 -> ZY", h2ZY, (TH2D*) s3->Projection(1,2), options); 
08592       options = 0;
08593       if ( defaultEqualOptions & cmpOptPrint )
08594          cout << "----------------------------------------------" << endl;
08595 
08596       // TH1 derived from STH3
08597       options = cmpOptStats;
08598       status += equals("STH3 -> X", h1X, (TH1D*) s3->Projection(0), options);
08599       status += equals("STH3 -> Y", h1Y, (TH1D*) s3->Projection(1), options);
08600       status += equals("STH3 -> Z", h1Z, (TH1D*) s3->Projection(2), options);
08601       options = 0;
08602       if ( defaultEqualOptions & cmpOptPrint )
08603          cout << "----------------------------------------------" << endl;
08604 
08605       return status;
08606    }
08607    
08608 };
08609 
08610 int stressHistogram()
08611 {
08612 #ifdef R__WIN32
08613    // On windows there is an order of initialization problem that lead to 
08614    // 'Int_t not being in the list of types when TProfile's TClass is 
08615    // initialized (via a call to IsA()->InheritsFrom(); on linux this is
08616    // not a problem because G__Base1 is initialized early; on windows with
08617    // root.exe this is not a problem because GetListOfType(kTRUE) is called
08618    // via a call to TClass::GetClass induces by the initialization of the 
08619    // plugin manager.
08620    gROOT->GetListOfTypes(kTRUE);
08621 #endif
08622    r.SetSeed(initialSeed);
08623 
08624    int GlobalStatus = false;
08625    int status = false;
08626 
08627    TBenchmark bm;
08628    bm.Start("stressHistogram");
08629 
08630    cout << "****************************************************************************" <<endl;
08631    cout << "*  Starting  stress  H I S T O G R A M                                     *" <<endl;
08632    cout << "****************************************************************************" <<endl;
08633 
08634    // Test 1
08635    if ( defaultEqualOptions & cmpOptPrint )
08636       cout << "**********************************\n"
08637            << "       Test without weights       \n" 
08638            << "**********************************\n"
08639            << endl;
08640 
08641 
08642    TH1::SetDefaultSumw2(); 
08643    // to avoid cases in chi2-test of profiles when error is zero  
08644    TProfile::Approximate();
08645    TProfile2D::Approximate();
08646    TProfile3D::Approximate();
08647 
08648 
08649    
08650    ProjectionTester* ht = new ProjectionTester();
08651    ht->buildHistograms();
08652    //Ht->buildHistograms(2,4,5,6,8,10);
08653    status = ht->compareHistograms();
08654    GlobalStatus += status;
08655    printResult("Testing Projections without weights..............................", status);
08656    delete ht;
08657 
08658    // Test 2
08659    if ( defaultEqualOptions & cmpOptPrint )
08660       cout << "**********************************\n"
08661            << "        Test with weights         \n" 
08662            << "**********************************\n"
08663            << endl;
08664    
08665    ProjectionTester* ht2 = new ProjectionTester();
08666    ht2->buildHistogramsWithWeights();
08667    status = ht2->compareHistograms();
08668    GlobalStatus += status;
08669    printResult("Testing Projections with weights.................................", status);
08670    delete ht2;
08671    
08672    // Test 3
08673    // Range Tests
08674    const unsigned int numberOfRange = 3;
08675    pointer2Test rangeTestPointer[numberOfRange] = { testTH2toTH1,
08676                                                     testTH3toTH1,
08677                                                     testTH3toTH2
08678    };
08679    struct TTestSuite rangeTestSuite = { numberOfRange, 
08680                                         "Projection with Range for Histograms and Profiles................",
08681                                         rangeTestPointer };
08682 
08683   // Test 4
08684    const unsigned int numberOfRebin = 9;
08685    pointer2Test rebinTestPointer[numberOfRebin] = { testIntegerRebin,       testIntegerRebinProfile,
08686                                                     testIntegerRebinNoName, testIntegerRebinNoNameProfile,
08687                                                     testArrayRebin,         testArrayRebinProfile,
08688                                                     test2DRebin, test2DRebinProfile,
08689                                                     testSparseRebin1};
08690    struct TTestSuite rebinTestSuite = { numberOfRebin, 
08691                                         "Histogram Rebinning..............................................",
08692                                         rebinTestPointer };
08693 
08694    // Test 5
08695    // Add Tests
08696    const unsigned int numberOfAdds = 20;
08697    pointer2Test addTestPointer[numberOfAdds] = { testAdd1,    testAddProfile1, 
08698                                                  testAdd2,    testAddProfile2,
08699                                                  testAdd3,   
08700                                                  testAddVar1, testAddVarProf1, 
08701                                                  testAddVar2, testAddVarProf2,
08702                                                  testAdd2D3,
08703                                                  testAdd3D3,
08704                                                  testAdd2D1,  testAdd2DProfile1,
08705                                                  testAdd2D2,  testAdd2DProfile2,
08706                                                  testAdd3D1,  testAdd3DProfile1,
08707                                                  testAdd3D2,  testAdd3DProfile2,
08708                                                  testAddSparse
08709    };
08710    struct TTestSuite addTestSuite = { numberOfAdds, 
08711                                       "Add tests for 1D, 2D and 3D Histograms and Profiles..............",
08712                                       addTestPointer };
08713 
08714    // Test 6
08715    // Multiply Tests
08716    const unsigned int numberOfMultiply = 17;
08717    pointer2Test multiplyTestPointer[numberOfMultiply] = { testMul1,      testMul2,
08718                                                           testMulVar1,   testMulVar2,
08719                                                           testMul2D1,    testMul2D2,
08720                                                           testMul3D1,    testMul3D2,
08721                                                           testMulSparse,
08722                                                           testMulF1D,    testMulF1D2,
08723                                                           testMulF2D,    testMulF2D2,
08724                                                           testMulF3D,    testMulF3D2,
08725                                                           testMulFND,    testMulFND2
08726    };
08727    struct TTestSuite multiplyTestSuite = { numberOfMultiply, 
08728                                            "Multiply tests for 1D, 2D and 3D Histograms......................",
08729                                            multiplyTestPointer };
08730 
08731    // Test 7
08732    // Divide Tests
08733    const unsigned int numberOfDivide = 10;
08734    pointer2Test divideTestPointer[numberOfDivide] = { testDivide1,     testDivide2,
08735                                                       testDivideVar1,  testDivideVar2,
08736                                                       testDivide2D1,   testDivide2D2,
08737                                                       testDivide3D1,   testDivide3D2,
08738                                                       testDivSparse1,  testDivSparse2
08739    };
08740    struct TTestSuite divideTestSuite = { numberOfDivide, 
08741                                          "Divide tests for 1D, 2D and 3D Histograms........................",
08742                                          divideTestPointer };
08743 
08744    // Still to do: Division for profiles
08745 
08746    // The division methods for the profiles have to be changed to
08747    // calculate the errors correctly.
08748 
08749    // Test 8
08750    // Copy Tests
08751    const unsigned int numberOfCopy = 25;
08752    pointer2Test copyTestPointer[numberOfCopy] = { testAssign1D,             testAssignProfile1D, 
08753                                                   testAssignVar1D,          testAssignProfileVar1D, 
08754                                                   testCopyConstructor1D,    testCopyConstructorProfile1D, 
08755                                                   testCopyConstructorVar1D, testCopyConstructorProfileVar1D, 
08756                                                   testClone1D,              testCloneProfile1D,
08757                                                   testCloneVar1D,           testCloneProfileVar1D,
08758                                                   testAssign2D,             testAssignProfile2D,
08759                                                   testCopyConstructor2D,    testCopyConstructorProfile2D,
08760                                                   testClone2D,              testCloneProfile2D,
08761                                                   testAssign3D,             testAssignProfile3D,
08762                                                   testCopyConstructor3D,    testCopyConstructorProfile3D,
08763                                                   testClone3D,              testCloneProfile3D,
08764                                                   testCloneSparse
08765    };
08766    struct TTestSuite copyTestSuite = { numberOfCopy, 
08767                                        "Copy tests for 1D, 2D and 3D Histograms and Profiles.............",
08768                                        copyTestPointer };
08769 
08770    // Test 9
08771    // WriteRead Tests
08772    const unsigned int numberOfReadwrite = 9;
08773    pointer2Test readwriteTestPointer[numberOfReadwrite] = { testWriteRead1D,     testWriteReadProfile1D,
08774                                                             testWriteReadVar1D,  testWriteReadProfileVar1D,
08775                                                             testWriteRead2D,     testWriteReadProfile2D,
08776                                                             testWriteRead3D,     testWriteReadProfile3D, 
08777                                                             testWriteReadSparse
08778    };
08779    struct TTestSuite readwriteTestSuite = { numberOfReadwrite, 
08780                                             "Read/Write tests for 1D, 2D and 3D Histograms and Profiles.......",
08781                                             readwriteTestPointer };
08782 
08783    // Test 10
08784    // Merge Tests
08785    const unsigned int numberOfMerge = 34;
08786    pointer2Test mergeTestPointer[numberOfMerge] = { testMerge1D,                 testMergeProf1D,
08787                                                     testMergeVar1D,              testMergeProfVar1D,
08788                                                     testMerge2D,                 testMergeProf2D,
08789                                                     testMerge3D,                 testMergeProf3D,
08790                                                     testMergeSparse,
08791                                                     testMerge1DLabelSame,        testMergeProf1DLabelSame,
08792                                                     testMerge2DLabelSame,        testMergeProf2DLabelSame,
08793                                                     testMerge3DLabelSame,        testMergeProf3DLabelSame,
08794 
08795                                                     /*testMerge1DLabelDiff,*/    testMergeProf1DLabelDiff,
08796                                                     testMerge2DLabelDiff,        testMergeProf2DLabelDiff,
08797                                                     testMerge3DLabelDiff,        testMergeProf3DLabelDiff,
08798                                                     testMerge1DLabelAll,         testMergeProf1DLabelAll,
08799                                                     testMerge2DLabelAll,         testMergeProf2DLabelAll,
08800                                                     testMerge3DLabelAll,         testMergeProf3DLabelAll,
08801                                                     /*testMerge1DLabelAllDiff*/  testMergeProf1DLabelAllDiff,
08802                                                     testMerge2DLabelAllDiff,     testMergeProf2DLabelAllDiff,
08803                                                     testMerge3DLabelAllDiff,     testMergeProf3DLabelAllDiff,
08804                                                     testMerge1DDiff,             testMergeProf1DDiff,
08805                                                     testMerge2DDiff/*,             testMergeProf2DDiff,*/
08806                                                     /*testMerge3DDiff,*/         /*testMergeProf3DDiff*/
08807    };
08808    struct TTestSuite mergeTestSuite = { numberOfMerge, 
08809                                         "Merge tests for 1D, 2D and 3D Histograms and Profiles............",
08810                                         mergeTestPointer };
08811    // Test 11
08812    // Label Tests
08813    const unsigned int numberOfLabel = 2;
08814    pointer2Test labelTestPointer[numberOfLabel] = { testLabel,
08815                                                     testLabelsInflateProf1D
08816    };
08817    struct TTestSuite labelTestSuite = { numberOfLabel, 
08818                                         "Label tests for 1D Histograms (TAxis)............................",
08819                                         labelTestPointer };
08820 
08821    // Test 12
08822    // Interpolation Tests
08823    const unsigned int numberOfInterpolation = 4;
08824    pointer2Test interpolationTestPointer[numberOfInterpolation] = { testInterpolation1D,
08825                                                                     testInterpolationVar1D,
08826                                                                     testInterpolation2D, 
08827                                                                     testInterpolation3D
08828    };
08829    struct TTestSuite interpolationTestSuite = { numberOfInterpolation, 
08830                                                 "Interpolation tests for Histograms...............................",
08831                                                 interpolationTestPointer };
08832 
08833    // Test 13
08834    // Scale Tests
08835    const unsigned int numberOfScale = 3;
08836    pointer2Test scaleTestPointer[numberOfScale] = { testScale1DProf,
08837                                                     testScale2DProf,
08838                                                     testScale3DProf
08839    };
08840    struct TTestSuite scaleTestSuite = { numberOfScale, 
08841                                         "Scale tests for Profiles.........................................",
08842                                         scaleTestPointer };
08843 
08844    // Test 14
08845    // Integral Tests
08846    const unsigned int numberOfIntegral = 3;
08847    pointer2Test integralTestPointer[numberOfIntegral] = { testH1Integral,
08848                                                           testH2Integral,
08849                                                           testH3Integral
08850    };
08851    struct TTestSuite integralTestSuite = { numberOfIntegral, 
08852                                            "Integral tests for Histograms....................................",
08853                                            integralTestPointer };
08854 
08855    // Test 15
08856    // TH1-THnSparse Conversions Tests
08857    const unsigned int numberOfConversions = 3;
08858    pointer2Test conversionsTestPointer[numberOfConversions] = { testConversion1D,
08859                                                                 testConversion2D,
08860                                                                 testConversion3D,
08861    };
08862    struct TTestSuite conversionsTestSuite = { numberOfConversions, 
08863                                               "TH1-THnSparse Conversion tests...................................",
08864                                               conversionsTestPointer };
08865 
08866    // Test 16
08867    // FillData Tests
08868    const unsigned int numberOfFillData = 12;
08869    pointer2Test fillDataTestPointer[numberOfFillData] = { testSparseData1DFull,  testSparseData1DSparse,
08870                                                           testSparseData2DFull,  testSparseData2DSparse,
08871                                                           testSparseData3DFull,  testSparseData3DSparse,
08872                                                           testBinDataData1D, 
08873                                                           testBinDataData2D,
08874                                                           testBinDataData3D,
08875                                                           testBinDataData1DInt,
08876                                                           testBinDataData2DInt,
08877                                                           testBinDataData3DInt,
08878    };
08879    struct TTestSuite fillDataTestSuite = { numberOfFillData, 
08880                                            "FillData tests for Histograms and Sparses........................",
08881                                            fillDataTestPointer };
08882 
08883 
08884    // Combination of tests
08885    const unsigned int numberOfSuits = 14;
08886    struct TTestSuite* testSuite[numberOfSuits];
08887    testSuite[ 0] = &rangeTestSuite;
08888    testSuite[ 1] = &rebinTestSuite;
08889    testSuite[ 2] = &addTestSuite;
08890    testSuite[ 3] = &multiplyTestSuite;
08891    testSuite[ 4] = &divideTestSuite;
08892    testSuite[ 5] = &copyTestSuite;
08893    testSuite[ 6] = &readwriteTestSuite;
08894    testSuite[ 7] = &mergeTestSuite;
08895    testSuite[ 8] = &labelTestSuite;
08896    testSuite[ 9] = &interpolationTestSuite;
08897    testSuite[10] = &scaleTestSuite;
08898    testSuite[11] = &integralTestSuite;
08899    testSuite[12] = &conversionsTestSuite;
08900    testSuite[13] = &fillDataTestSuite;
08901 
08902    status = 0;
08903    for ( unsigned int i = 0; i < numberOfSuits; ++i ) {
08904       bool internalStatus = false;
08905 //       #pragma omp parallel
08906 //       #pragma omp for reduction(|: internalStatus)
08907       for ( unsigned int j = 0; j < testSuite[i]->nTests; ++j ) {
08908          internalStatus |= testSuite[i]->tests[j]();
08909       }
08910       printResult( testSuite[i]->suiteName, internalStatus);
08911       status += internalStatus;
08912    }
08913    GlobalStatus += status;
08914 
08915    // Test 17
08916    // Reference Tests
08917    const unsigned int numberOfRefRead = 7;
08918    pointer2Test refReadTestPointer[numberOfRefRead] = { testRefRead1D,  testRefReadProf1D,
08919                                                         testRefRead2D,  testRefReadProf2D,
08920                                                         testRefRead3D,  testRefReadProf3D,
08921                                                         testRefReadSparse
08922    };
08923    struct TTestSuite refReadTestSuite = { numberOfRefRead, 
08924                                           "Reference File Read for Histograms and Profiles..................",
08925                                           refReadTestPointer };
08926    
08927 
08928    if ( refFileOption == refFileWrite ) {
08929       refFile = TFile::Open(refFileName, "RECREATE");
08930    }
08931    else {
08932       refFile = TFile::Open(refFileName);
08933    }
08934 
08935    if ( refFile != 0 ) {
08936       r.SetSeed(8652);
08937       status = 0;
08938       for ( unsigned int j = 0; j < refReadTestSuite.nTests; ++j ) {
08939          status += refReadTestSuite.tests[j]();
08940       }
08941       printResult( refReadTestSuite.suiteName, status);
08942       GlobalStatus += status;
08943    } else {
08944       Warning("stressHistogram", "No reference file found");
08945    }
08946 
08947    bm.Stop("stressHistogram");
08948    std::cout <<"****************************************************************************\n";
08949    bm.Print("stressHistogram");
08950    const double reftime = 123; // needs to be updated // ref time on  pcbrun4
08951    double rootmarks = 900 * reftime / bm.GetCpuTime("stressHistogram");
08952    std::cout << " ROOTMARKS = " << rootmarks << " ROOT version: " << gROOT->GetVersion() << "\t" 
08953              << gROOT->GetSvnBranch() << "@" << gROOT->GetSvnRevision() << std::endl;
08954    std::cout <<"****************************************************************************\n";
08955 
08956    return GlobalStatus;
08957 }
08958 
08959 ostream& operator<<(ostream& out, TH1D* h)
08960 {
08961    out << h->GetName() << ": [" << h->GetBinContent(1);
08962    for ( Int_t i = 1; i < h->GetNbinsX(); ++i )
08963       out << ", " << h->GetBinContent(i);
08964    out << "] ";
08965 
08966    return out;
08967 }
08968 
08969 void printResult(const char* msg, bool status)
08970 {
08971    static int counter = 1;
08972    cout << "Test ";
08973    cout.width(2);
08974    cout<< counter << ": "
08975        << msg
08976        << (status?"FAILED":"OK") << endl;
08977    counter += 1;
08978 }
08979 
08980 void FillVariableRange(Double_t v[numberOfBins+1])
08981 {
08982    //Double_t v[numberOfBins+1];
08983    Double_t minLimit = (maxRange-minRange)  / (numberOfBins*2);
08984    Double_t maxLimit = (maxRange-minRange)*4/ (numberOfBins);   
08985    v[0] = 0;
08986    for ( Int_t i = 1; i < numberOfBins + 1; ++i )
08987    {
08988       Double_t limit = r.Uniform(minLimit, maxLimit);
08989       v[i] = v[i-1] + limit;
08990    }
08991    
08992    Double_t k = (maxRange-minRange)/v[numberOfBins];
08993    for ( Int_t i = 0; i < numberOfBins + 1; ++i )
08994    {
08995       v[i] = v[i] * k + minRange;
08996    }
08997 }
08998 
08999 void FillHistograms(TH1D* h1, TH1D* h2, Double_t c1, Double_t c2)
09000 {
09001    for ( Int_t e = 0; e < nEvents; ++e ) {
09002       Double_t value = r.Uniform(0.9 * minRange, 1.1 * maxRange);
09003       h1->Fill(value, c1);
09004       h2->Fill(value, c2);
09005    }
09006 }
09007 
09008 void FillProfiles(TProfile* p1, TProfile* p2, Double_t c1, Double_t c2)
09009 {
09010    for ( Int_t e = 0; e < nEvents; ++e ) {
09011       Double_t x = r.Uniform(0.9 * minRange, 1.1 * maxRange);
09012       Double_t y = r.Uniform(0.9 * minRange, 1.1 * maxRange);
09013       p1->Fill(x, y, c1);
09014       p2->Fill(x, y, c2);
09015    }
09016 }
09017 
09018 // Methods for histogram comparisions
09019 
09020 int equals(const char* msg, THnSparse* h1, THnSparse* h2, int options, double ERRORLIMIT)
09021 {
09022    options = options | defaultEqualOptions;
09023    bool print = options & cmpOptPrint;
09024    bool debug = options & cmpOptDebug;
09025    bool compareError = ! (options & cmpOptNoError);
09026    
09027    int differents = 0;
09028    
09029    for ( int i = 0; i <= h1->GetAxis(0)->GetNbins() + 1; ++i )
09030       for ( int j = 0; j <= h1->GetAxis(1)->GetNbins() + 1; ++j )
09031          for ( int h = 0; h <= h1->GetAxis(2)->GetNbins() + 1; ++h )
09032          {
09033             Double_t x = h1->GetAxis(0)->GetBinCenter(i);
09034             Double_t y = h1->GetAxis(1)->GetBinCenter(j);
09035             Double_t z = h1->GetAxis(2)->GetBinCenter(h);
09036             
09037             Int_t bin[3] = {i, j, h};
09038             
09039             if (debug) {
09040                cout << equals(x, h2->GetAxis(0)->GetBinCenter(i), ERRORLIMIT) << " "
09041                     << equals(y, h2->GetAxis(1)->GetBinCenter(j), ERRORLIMIT) << " "
09042                     << equals(z, h2->GetAxis(2)->GetBinCenter(h), ERRORLIMIT) << " "
09043                     << "[" << x << "," << y << "," << z << "]: " 
09044                     << h1->GetBinContent(bin) << " +/- " << h1->GetBinError(bin) << " | "
09045                     << h2->GetBinContent(bin) << " +/- " << h2->GetBinError(bin)
09046                     << " | " << equals(h1->GetBinContent(bin), h2->GetBinContent(bin), ERRORLIMIT)
09047                     << " "   << equals(h1->GetBinError(bin)  , h2->GetBinError(bin),   ERRORLIMIT)
09048                     << " "   << differents
09049                     << " "   << (fabs(h1->GetBinContent(bin) - h2->GetBinContent(bin)))
09050                     << endl;
09051             }
09052             differents += equals(x, h2->GetAxis(0)->GetBinCenter(i), ERRORLIMIT);
09053             differents += equals(y, h2->GetAxis(1)->GetBinCenter(j), ERRORLIMIT);
09054             differents += equals(z, h2->GetAxis(2)->GetBinCenter(h), ERRORLIMIT);
09055             differents += equals(h1->GetBinContent(bin), h2->GetBinContent(bin), ERRORLIMIT);
09056             if ( compareError )
09057                differents += equals(h1->GetBinError(bin)  , h2->GetBinError(bin), ERRORLIMIT);
09058          }
09059    
09060    // Statistical tests:
09061    // No statistical tests possible for THnSparse so far...
09062 //    if ( compareStats )
09063 //       differents += compareStatistics( h1, h2, debug, ERRORLIMIT);
09064    
09065    if ( print || debug ) cout << msg << ": \t" << (differents?"FAILED":"OK") << endl;
09066    
09067    delete h2;
09068    
09069    return differents;
09070 }
09071 
09072 int equals(const char* msg, THnSparse* s, TH1* h2, int options, double ERRORLIMIT)
09073 {
09074    options = options | defaultEqualOptions;
09075    bool print = options & cmpOptPrint;
09076    bool debug = options & cmpOptDebug;
09077    bool compareError = ! (options & cmpOptNoError);
09078    
09079    int differents = 0;
09080 
09081    const int dim ( s->GetNdimensions() );
09082    if ( dynamic_cast<TH3*>(h2) ) {
09083       if ( dim != 3 )
09084          return 1;
09085    } else if ( dynamic_cast<TH2*>(h2) ) {
09086       if ( dim != 2 )
09087          return 1;
09088    } else if ( dim != 1 )
09089       return 1;
09090               
09091    TArray* array = dynamic_cast<TArray*>(h2);
09092    if ( !array )
09093       Fatal( "equals(const char* msg, THnSparse* s, TH1* h2, int options, double ERRORLIMIT)" ,"NO ARRAY!");
09094 
09095    Int_t* coord = new Int_t[3];
09096    for (Long64_t i = 0; i < s->GetNbins(); ++i) 
09097    {
09098       Double_t v1 = s->GetBinContent(i, coord);
09099       Double_t err1 = s->GetBinError(coord);
09100 
09101       int bin  = h2->GetBin(coord[0], coord[1], coord[2]);
09102       Double_t v2 = h2->GetBinContent(bin);
09103       Double_t err2 = h2->GetBinError(bin);
09104 
09105       differents += equals(v1, v2, ERRORLIMIT);
09106       if ( compareError )
09107          differents += equals(err1  , err2, ERRORLIMIT);
09108    }
09109 
09110    for (Long64_t i = 0; i < array->GetSize(); ++i) 
09111    {
09112       h2->GetBinXYZ(i, coord[0], coord[1], coord[2]);
09113       
09114       Double_t v1 = s->GetBinContent(coord);
09115       Double_t err1 = s->GetBinError(coord);
09116       
09117       Double_t v2 = h2->GetBinContent(i);
09118       Double_t err2 = h2->GetBinError(i);
09119 
09120       differents += equals(v1, v2, ERRORLIMIT);
09121       if ( compareError )
09122          differents += equals(err1  , err2, ERRORLIMIT);
09123    }
09124 
09125    if ( print || debug ) cout << msg << ": \t" << (differents?"FAILED":"OK") << endl;
09126    
09127    delete h2;
09128    
09129    return differents;  
09130 }
09131 
09132 int equals(const char* msg, TH3D* h1, TH3D* h2, int options, double ERRORLIMIT)
09133 {
09134    options = options | defaultEqualOptions;
09135    bool print = options & cmpOptPrint;
09136    bool debug = options & cmpOptDebug;
09137    bool compareError = ! (options & cmpOptNoError);
09138    bool compareStats = options & cmpOptStats;
09139    
09140    int differents = ( h1 == h2 ); // Check they are not the same histogram!
09141    if (debug) {
09142       cout << static_cast<void*>(h1) << " " << static_cast<void*>(h2) << " "
09143            << (h1 == h2 ) << " " << differents << endl;
09144    }
09145    
09146    for ( int i = 0; i <= h1->GetNbinsX() + 1; ++i )
09147       for ( int j = 0; j <= h1->GetNbinsY() + 1; ++j )
09148          for ( int h = 0; h <= h1->GetNbinsY() + 1; ++h )
09149       {
09150          Double_t x = h1->GetXaxis()->GetBinCenter(i);
09151          Double_t y = h1->GetYaxis()->GetBinCenter(j);
09152          Double_t z = h1->GetZaxis()->GetBinCenter(h);
09153          
09154          if (debug)
09155          {
09156             cout << equals(x, h2->GetXaxis()->GetBinCenter(i), ERRORLIMIT) << " "
09157                  << equals(y, h2->GetYaxis()->GetBinCenter(j), ERRORLIMIT) << " "
09158                  << equals(z, h2->GetZaxis()->GetBinCenter(h), ERRORLIMIT) << " "
09159                  << "[" << x << "," << y << "," << z << "]: " 
09160                  << h1->GetBinContent(i,j,h) << " +/- " << h1->GetBinError(i,j,h) << " | "
09161                  << h2->GetBinContent(i,j,h) << " +/- " << h2->GetBinError(i,j,h)
09162                  << " | " << equals(h1->GetBinContent(i,j,h), h2->GetBinContent(i,j,h), ERRORLIMIT)
09163                  << " "   << equals(h1->GetBinError(i,j,h)  , h2->GetBinError(i,j,h),   ERRORLIMIT)
09164                  << " "   << differents
09165                  << " "   << (fabs(h1->GetBinContent(i,j,h) - h2->GetBinContent(i,j,h)))
09166                  << endl;
09167          }
09168          differents += (bool) equals(x, h2->GetXaxis()->GetBinCenter(i), ERRORLIMIT);
09169          differents += (bool) equals(y, h2->GetYaxis()->GetBinCenter(j), ERRORLIMIT);
09170          differents += (bool) equals(z, h2->GetZaxis()->GetBinCenter(h), ERRORLIMIT);
09171          differents += (bool) equals(h1->GetBinContent(i,j,h), h2->GetBinContent(i,j,h), ERRORLIMIT);
09172          if ( compareError )
09173             differents += (bool) equals(h1->GetBinError(i,j,h)  , h2->GetBinError(i,j,h), ERRORLIMIT);
09174       }
09175    
09176    // Statistical tests:
09177    if ( compareStats )
09178       differents += compareStatistics( h1, h2, debug, ERRORLIMIT);
09179    
09180    if ( print || debug ) cout << msg << ": \t" << (differents?"FAILED":"OK") << endl;
09181    
09182    delete h2;
09183    
09184    return differents;
09185 }
09186 
09187 int equals(const char* msg, TH2D* h1, TH2D* h2, int options, double ERRORLIMIT)
09188 {
09189    options = options | defaultEqualOptions;
09190    bool print = options & cmpOptPrint;
09191    bool debug = options & cmpOptDebug;
09192    bool compareError = ! (options & cmpOptNoError);
09193    bool compareStats = options & cmpOptStats;
09194    
09195    int differents = ( h1 == h2 ); // Check they are not the same histogram!
09196    if (debug) {
09197       cout << static_cast<void*>(h1) << " " << static_cast<void*>(h2) << " "
09198            << (h1 == h2 ) << " " << differents << endl;
09199    }
09200 
09201    for ( int i = 0; i <= h1->GetNbinsX() + 1; ++i )
09202       for ( int j = 0; j <= h1->GetNbinsY() + 1; ++j )
09203       {
09204          Double_t x = h1->GetXaxis()->GetBinCenter(i);
09205          Double_t y = h1->GetYaxis()->GetBinCenter(j);
09206          
09207          if (debug)
09208          {
09209             cout << equals(x, h2->GetXaxis()->GetBinCenter(i), ERRORLIMIT) << " "
09210                  << equals(y, h2->GetYaxis()->GetBinCenter(j), ERRORLIMIT) << " "
09211                  << "[" << x << "," << y << "]: " 
09212                  << h1->GetBinContent(i,j) << " +/- " << h1->GetBinError(i,j) << " | "
09213                  << h2->GetBinContent(i,j) << " +/- " << h2->GetBinError(i,j)
09214                  << " | " << equals(h1->GetBinContent(i,j), h2->GetBinContent(i,j), ERRORLIMIT)
09215                  << " "   << equals(h1->GetBinError(i,j)  , h2->GetBinError(i,j),   ERRORLIMIT)
09216                  << " "   << differents
09217                  << " "   << (fabs(h1->GetBinContent(i,j) - h2->GetBinContent(i,j)))
09218                  << endl;
09219          }
09220          differents += (bool) equals(x, h2->GetXaxis()->GetBinCenter(i), ERRORLIMIT);
09221          differents += (bool) equals(y, h2->GetYaxis()->GetBinCenter(j), ERRORLIMIT);
09222          differents += (bool) equals(h1->GetBinContent(i,j), h2->GetBinContent(i,j), ERRORLIMIT);
09223          if ( compareError )
09224             differents += (bool) equals(h1->GetBinError(i,j)  , h2->GetBinError(i,j), ERRORLIMIT);
09225       }
09226    
09227    // Statistical tests:
09228    if ( compareStats )
09229       differents += compareStatistics( h1, h2, debug, ERRORLIMIT);
09230    
09231    if ( print || debug ) cout << msg << ": \t" << (differents?"FAILED":"OK") << endl;
09232    
09233    delete h2;
09234    
09235    return differents;
09236 }
09237 
09238 int equals(const char* msg, TH1D* h1, TH1D* h2, int options, double ERRORLIMIT)
09239 {
09240    options = options | defaultEqualOptions;
09241    bool print = options & cmpOptPrint;
09242    bool debug = options & cmpOptDebug;
09243    bool compareError = ! (options & cmpOptNoError);
09244    bool compareStats = options & cmpOptStats;
09245    
09246 
09247    if (debug) { 
09248       cout << "Nbins  = " << h1->GetXaxis()->GetNbins() << " ,  " <<  h2->GetXaxis()->GetNbins() << endl;
09249    }
09250 
09251    int differents = ( h1 == h2 ); // Check they are not the same histogram!
09252    if (debug) {
09253       cout << static_cast<void*>(h1) << " " << static_cast<void*>(h2) << " "
09254            << (h1 == h2 ) << " " << differents << endl;
09255    }
09256 
09257    for ( int i = 0; i <= h1->GetNbinsX() + 1; ++i )
09258    {
09259       Double_t x = h1->GetXaxis()->GetBinCenter(i);
09260       if ( debug )
09261       {
09262          cout << equals(x, h2->GetXaxis()->GetBinCenter(i), ERRORLIMIT)
09263               << " [" << x << "]: " 
09264               << h1->GetBinContent(i) << " +/- " << h1->GetBinError(i) << " | "
09265               << h2->GetBinContent(i) << " +/- " << h2->GetBinError(i)
09266               << " | " << equals(h1->GetBinContent(i), h2->GetBinContent(i), ERRORLIMIT)
09267               << " "   << equals(h1->GetBinError(i),   h2->GetBinError(i),   ERRORLIMIT)
09268               << " "   << differents
09269               << endl;
09270       }
09271       differents += (bool) equals(x, h2->GetXaxis()->GetBinCenter(i), ERRORLIMIT);
09272       differents += (bool) equals(h1->GetBinContent(i), h2->GetBinContent(i), ERRORLIMIT);
09273       
09274       if ( compareError )
09275          differents += (bool) equals(h1->GetBinError(i),   h2->GetBinError(i), ERRORLIMIT);
09276    }
09277    
09278    // Statistical tests:
09279    if ( compareStats )
09280       differents += compareStatistics( h1, h2, debug, ERRORLIMIT);
09281    
09282    if ( print || debug ) cout << msg << ": \t" << (differents?"FAILED":"OK") << endl;
09283    
09284    delete h2;
09285    
09286    return differents;      
09287 }
09288 
09289 int equals(Double_t n1, Double_t n2, double ERRORLIMIT)
09290 {
09291    return fabs( n1 - n2 ) > ERRORLIMIT * fabs(n1);
09292 }
09293 
09294 int compareStatistics( TH1* h1, TH1* h2, bool debug, double ERRORLIMIT)
09295 {
09296    int differents = 0;
09297 
09298    int pr = std::cout.precision(12);
09299 
09300 
09301    int precLevel = gErrorIgnoreLevel; 
09302    // switch off Info mesaage from chi2 test
09303    if (!debug) gErrorIgnoreLevel = 1001; 
09304             
09305    if (debug) h2->Print(); 
09306    
09307    std::string option = "WW OF UF";
09308    const char * opt = option.c_str(); 
09309 
09310    double chi_12 = h1->Chi2Test(h2, opt);
09311    double chi_21 = h2->Chi2Test(h1, opt);
09312 
09313    differents += (bool) equals(chi_12, 1, ERRORLIMIT);
09314    differents += (bool) equals(chi_21, 1, ERRORLIMIT);  
09315    differents += (bool) equals(chi_12, chi_21, ERRORLIMIT);
09316    if ( debug )
09317       cout << "Chi2Test " << chi_12 << " " <<  chi_21 
09318            << " | " << differents
09319            << endl;
09320 
09321    if (!debug) gErrorIgnoreLevel = precLevel; 
09322 
09323    // Mean
09324    differents += (bool) equals(h1->GetMean(1), h2->GetMean(1), ERRORLIMIT);
09325    if ( debug )
09326       cout << "Mean: " << h1->GetMean(1) << " " << h2->GetMean(1) 
09327            << " | " << fabs( h1->GetMean(1) - h2->GetMean(1) ) 
09328            << " " << differents
09329            << endl;
09330    
09331    // RMS
09332    differents += (bool) equals( h1->GetRMS(1), h2->GetRMS(1), ERRORLIMIT);
09333    if ( debug )
09334       cout << "RMS: " << h1->GetRMS(1) << " " << h2->GetRMS(1) 
09335            << " | " << fabs( h1->GetRMS(1) - h2->GetRMS(1) ) 
09336            << " " << differents
09337            << endl;  
09338 
09339    // Number of Entries
09340    // check if is an unweighted histogram compare entries otherwise only effective entries
09341    if (h1->GetEntries() == h1->GetEffectiveEntries() ) { 
09342 
09343       differents += (bool) equals( h1->GetEntries(), h2->GetEntries(), 100*ERRORLIMIT);
09344       if ( debug )
09345          cout << "Entries: " << h1->GetEntries() << " " << h2->GetEntries() 
09346               << " | " << fabs( h1->GetEntries() - h2->GetEntries() ) 
09347               << " " << differents
09348               << endl;  
09349    }
09350 
09351    // Number of Effective Entries
09352    differents += (bool) equals( h1->GetEffectiveEntries(), h2->GetEffectiveEntries(), 100*ERRORLIMIT);
09353    if ( debug )
09354       cout << "Eff Entries: " << h1->GetEffectiveEntries() << " " << h2->GetEffectiveEntries() 
09355            << " | " << fabs( h1->GetEffectiveEntries() - h2->GetEffectiveEntries() ) 
09356            << " " << differents
09357            << endl;  
09358 
09359    std::cout.precision(pr);   
09360 
09361    return differents;
09362 }
09363 
09364 int main(int argc, char** argv)
09365 {
09366    TApplication* theApp = 0;
09367 
09368    TH1::SetDefaultSumw2();
09369 
09370    if ( __DRAW__ )
09371       theApp = new TApplication("App",&argc,argv);
09372 
09373    if (argc > 1) { 
09374       // for changing printing option (0 default, 1 print all test, 2 debug) 
09375       defaultEqualOptions = atoi(argv[1] );
09376    }
09377 
09378    int ret = stressHistogram();
09379 
09380    if ( __DRAW__ ) {
09381       theApp->Run();
09382       delete theApp;
09383       theApp = 0;
09384    }
09385 
09386    return ret;
09387 }

Generated on Tue Jul 5 15:15:19 2011 for ROOT_528-00b_version by  doxygen 1.5.1