stressLinear.cxx

Go to the documentation of this file.
00001 // @(#)root/test:$name:  $:$id: stressLinear.cxx,v 1.15 2002/10/25 10:47:51 rdm exp $
00002 // Authors: Fons Rademakers, Eddy Offermann  Jan 2004
00003 
00004 /////////////////////////////////////////////////////////////////
00005 //
00006 //    R O O T   LINEAR ALGEBRA T E S T  S U I T E  and  B E N C H M A R K S
00007 //    =====================================================================
00008 //
00009 // The suite of programs below tests many elements of the vector, matrix
00010 // and matrix decomposition classes.
00011 // To run in batch, do
00012 //   stressLinear      : with no parameters, run standard test with matrices upto 100x100
00013 //   stressLinear 30   : run test with matrices upto 30x30
00014 //   stressLinear 30 1 : run test with matrices upto 30x30 in verbose mode
00015 //
00016 // To run interactively, do
00017 // root -b
00018 //  Root > .x stressLinear.cxx(100)   run standard test with matrices upto 100x100
00019 //  Root > .x stressLinear.cxx(30)    run with matrices upto 30x30
00020 //  Root > .x stressLinear.cxx(30,1)  run with matrices upto 30x30 in verbose mode
00021 //
00022 // Several tests are run sequentially. Each test will produce one line (Test OK or Test FAILED) .
00023 // At the end of the test a table is printed showing the global results
00024 // Real Time and Cpu Time.
00025 // One single number (ROOTMARKS) is also calculated showing the relative
00026 // performance of your machine compared to a reference machine
00027 // a Pentium IV 2.4 Ghz) with 512 MBytes of memory
00028 // and 120 GBytes IDE disk.
00029 //
00030 // An example of output when all the tests run OK is shown below:
00031 
00032 //////////////////////////////////////////////////////////////////////////
00033 //                                                                      //
00034 // Linear Algebra Package -- Matrix Verifications.                      //
00035 //                                                                      //
00036 // This file implements a large set of TMat operation tests.            //
00037 // *******************************************************************  //
00038 // *  Linear Algebra - S T R E S S suite                             *  //
00039 // *******************************************************************  //
00040 // *******************************************************************  //
00041 // *  Starting  Matrix - S T R E S S                                 *  //
00042 // *******************************************************************  //
00043 // Test  1 : Allocation, Resizing.................................. OK  //
00044 // Test  2 : Filling, Inserting, Using............................. OK  //
00045 // Test  3 : Uniform matrix operations............................. OK  //
00046 // Test  4 : Binary Matrix element-by-element operations............OK  //
00047 // Test  5 : Matrix transposition...................................OK  //
00048 // Test  6 : Haar/Hilbert Matrix....................................OK  //
00049 // Test  7 : Matrix promises........................................OK  //
00050 // Test  8 : Matrix Norms...........................................OK  //
00051 // Test  9 : Matrix Determinant.....................................OK  //
00052 // Test 10 : General Matrix Multiplications.........................OK  //
00053 // Test 11 : Symmetric Matrix Multiplications.......................OK  //
00054 // Test 12 : Matrix Vector Multiplications..........................OK  //
00055 // Test 13 : Matrix Inversion.......................................OK  //
00056 // Test 14 : Matrix Persistence.....................................OK  //
00057 // ******************************************************************   //
00058 // *  Starting  Sparse Matrix - S T R E S S                         *   //
00059 // ******************************************************************   //
00060 // Test  1 : Allocation, Resizing...................................OK  //
00061 // Test  2 : Filling, Inserting, Using..............................OK  //
00062 // Test  3 : Uniform matrix operations..............................OK  //
00063 // Test  4 : Binary Matrix element-by-element operations............OK  //
00064 // Test  5 : Matrix transposition...................................OK  //
00065 // Test  6 : Matrix Norms...........................................OK  //
00066 // Test  7 : General Matrix Multiplications.........................OK  //
00067 // Test  8 : Matrix Vector Multiplications..........................OK  //
00068 // Test  9 : Matrix Slices to Vectors...............................OK  //
00069 // Test 10 : Matrix Persistence.....................................OK  //
00070 // *******************************************************************  //
00071 // *  Starting  Vector - S T R E S S                                 *  //
00072 // *******************************************************************  //
00073 // Test  1 : Allocation, Filling, Resizing......................... OK  //
00074 // Test  2 : Uniform vector operations............................. OK  //
00075 // Test  3 : Binary vector element-by-element operations............OK  //
00076 // Test  4 : Vector Norms...........................................OK  //
00077 // Test  5 : Matrix Slices to Vectors...............................OK  //
00078 // Test  6 : Vector Persistence.....................................OK  //
00079 // *******************************************************************  //
00080 // *  Starting  Linear Algebra - S T R E S S                         *  //
00081 // *******************************************************************  //
00082 // Test  1 : Decomposition / Reconstruction........................ OK  //
00083 // Test  2 : Linear Equations...................................... OK  //
00084 // Test  3 : Pseudo-Inverse, Moore-Penrose......................... OK  //
00085 // Test  4 : Eigen - Values/Vectors.................................OK  //
00086 // Test  5 : Decomposition Persistence..............................OK  //
00087 // *******************************************************************  //
00088 //                                                                      //
00089 //////////////////////////////////////////////////////////////////////////
00090 
00091 #include <stdlib.h>
00092 #include <Riostream.h>
00093 #include <TSystem.h>
00094 #include <TFile.h>
00095 #include <TBenchmark.h>
00096 #include <TArrayD.h>
00097 #include <TF1.h>
00098 #include <TGraph.h>
00099 #include <TROOT.h>
00100 #include "TMath.h"
00101 
00102 #include "TMatrixF.h"
00103 #include "TMatrixFSym.h"
00104 #include "TMatrixFSparse.h"
00105 #include "TMatrixFLazy.h"
00106 #include "TVectorF.h"
00107 
00108 #include "TMatrixD.h"
00109 #include "TMatrixDSym.h"
00110 #include "TMatrixDSparse.h"
00111 #include "TMatrixDLazy.h"
00112 #include "TMatrixDUtils.h"
00113 #include "TVectorD.h"
00114 
00115 #include "TDecompLU.h"
00116 #include "TDecompChol.h"
00117 #include "TDecompQRH.h"
00118 #include "TDecompSVD.h"
00119 #include "TDecompBK.h"
00120 #include "TMatrixDEigen.h"
00121 #include "TMatrixDSymEigen.h"
00122 
00123 void stressLinear                  (Int_t maxSizeReq=100,Int_t verbose=0);
00124 void StatusPrint                   (Int_t id,const TString &title,Bool_t status);
00125 
00126 void mstress_allocation            (Int_t msize);
00127 void mstress_matrix_fill           (Int_t rsize,Int_t csize);
00128 void mstress_element_op            (Int_t rsize,Int_t csize);
00129 void mstress_binary_ebe_op         (Int_t rsize, Int_t csize);
00130 void mstress_transposition         (Int_t msize);
00131 void mstress_special_creation      (Int_t dim);
00132 void mstress_matrix_fill           (Int_t rsize,Int_t csize);
00133 void mstress_matrix_promises       (Int_t dim);
00134 void mstress_norms                 (Int_t rsize,Int_t csize);
00135 void mstress_determinant           (Int_t msize);
00136 void mstress_mm_multiplications    ();
00137 void mstress_sym_mm_multiplications(Int_t msize);
00138 void mstress_vm_multiplications    ();
00139 void mstress_inversion             ();
00140 void mstress_matrix_io             ();
00141 
00142 void spstress_allocation           (Int_t msize);
00143 void spstress_matrix_fill          (Int_t rsize,Int_t csize);
00144 void spstress_element_op           (Int_t rsize,Int_t csize);
00145 void spstress_binary_ebe_op        (Int_t rsize, Int_t csize);
00146 void spstress_transposition        (Int_t msize);
00147 void spstress_norms                (Int_t rsize,Int_t csize);
00148 void spstress_mm_multiplications   ();
00149 void spstress_vm_multiplications   ();
00150 void spstress_matrix_slices        (Int_t vsize);
00151 void spstress_matrix_io            ();
00152 
00153 void vstress_allocation            (Int_t msize);
00154 void vstress_element_op            (Int_t vsize);
00155 void vstress_binary_op             (Int_t vsize);
00156 void vstress_norms                 (Int_t vsize);
00157 void vstress_matrix_slices         (Int_t vsize);
00158 void vstress_vector_io             ();
00159 
00160 Bool_t test_svd_expansion          (const TMatrixD &A);
00161 void   astress_decomp              ();
00162 void   astress_lineqn              ();
00163 void   astress_pseudo              ();
00164 void   astress_eigen               (Int_t msize);
00165 void   astress_decomp_io           (Int_t msize);
00166 
00167 void   stress_backward_io          ();
00168 
00169 void   cleanup                     ();
00170 
00171 //_____________________________batch only_____________________
00172 #ifndef __CINT__
00173 
00174 int main(int argc,const char *argv[])
00175 {
00176   Int_t maxSizeReq = 100;
00177   if (argc > 1)  maxSizeReq = atoi(argv[1]);
00178   Int_t verbose = 0;
00179   if (argc > 2)  verbose = (atoi(argv[2]) > 0 ? 1 : 0);
00180 
00181   gBenchmark = new TBenchmark();
00182   stressLinear(maxSizeReq,verbose);
00183 
00184   cleanup();
00185   return 0;
00186 }
00187 
00188 #endif
00189 
00190 #define EPSILON 1.0e-14
00191 
00192 Int_t gVerbose      = 0;
00193 Int_t gNrLoop;
00194 const Int_t nrSize  = 20;
00195 const Int_t gSizeA[] = {5,6,7,8,9,10,15,20,30,40,50,60,70,80,90,100,300,500,700,1000};
00196 
00197 //________________________________common part_________________________
00198 
00199 void stressLinear(Int_t maxSizeReq,Int_t verbose)
00200 {
00201   cout << "******************************************************************" <<endl;
00202   cout << "*  Starting  Linear Algebra - S T R E S S suite                  *" <<endl;
00203   cout << "******************************************************************" <<endl;
00204   cout << "******************************************************************" <<endl;
00205 
00206   gVerbose = verbose;
00207 
00208   gBenchmark->Start("stressLinear");
00209 
00210   gNrLoop = nrSize-1;
00211   while (gNrLoop > 0 && maxSizeReq < gSizeA[gNrLoop])
00212     gNrLoop--;
00213 
00214   const Int_t maxSize = gSizeA[gNrLoop];
00215 
00216   // Matrix
00217   {
00218     cout << "*  Starting  Matrix - S T R E S S                                *" <<endl;
00219     cout << "******************************************************************" <<endl;
00220     mstress_allocation(maxSize);
00221     mstress_matrix_fill(maxSize,maxSize/2);
00222     mstress_element_op(maxSize,maxSize/2);
00223     mstress_binary_ebe_op(maxSize/2,maxSize);
00224     mstress_transposition(maxSize);
00225     mstress_special_creation(maxSize);
00226 #ifndef __CINT__
00227     mstress_matrix_promises(maxSize);
00228 #endif
00229     mstress_norms(maxSize,maxSize/2);
00230     mstress_determinant(maxSize);
00231     mstress_mm_multiplications();
00232     mstress_sym_mm_multiplications(maxSize);
00233     mstress_vm_multiplications();
00234     mstress_inversion();
00235 
00236     mstress_matrix_io();
00237     cout << "******************************************************************" <<endl;
00238   }
00239 
00240   // Sparse Matrix
00241   {
00242     cout << "*  Starting  Sparse Matrix - S T R E S S                         *" <<endl;
00243     cout << "******************************************************************" <<endl;
00244     spstress_allocation(maxSize);
00245     spstress_matrix_fill(maxSize,maxSize/2);
00246     spstress_element_op(maxSize,maxSize/2);
00247     spstress_binary_ebe_op(maxSize/2,maxSize);
00248     spstress_transposition(maxSize);
00249     spstress_norms(maxSize,maxSize/2);
00250     spstress_mm_multiplications();
00251     spstress_vm_multiplications();
00252     spstress_matrix_slices(maxSize);
00253     spstress_matrix_io();
00254     cout << "******************************************************************" <<endl;
00255   }
00256 
00257   {
00258     cout << "*  Starting  Vector - S T R E S S                                *" <<endl;
00259     cout << "******************************************************************" <<endl;
00260     vstress_allocation(maxSize);
00261     vstress_element_op(maxSize);
00262     vstress_binary_op(maxSize);
00263     vstress_norms(maxSize);
00264     vstress_matrix_slices(maxSize);
00265     vstress_vector_io();
00266     cout << "******************************************************************" <<endl;
00267   }
00268 
00269   // Linear Algebra
00270   {
00271     cout << "*  Starting  Linear Algebra - S T R E S S                        *" <<endl;
00272     cout << "******************************************************************" <<endl;
00273     astress_decomp();
00274     astress_lineqn();
00275     astress_pseudo();
00276     astress_eigen(5);
00277     astress_decomp_io(10);
00278     cout << "******************************************************************" <<endl;
00279   }
00280 
00281   //Backward Compatibility of Streamers
00282   {
00283     cout << "*  Starting  Backward IO compatibility - S T R E S S             *" <<endl;
00284     cout << "******************************************************************" <<endl;
00285     stress_backward_io();
00286     cout << "******************************************************************" <<endl;
00287   }
00288 
00289   gBenchmark->Stop("stressLinear");
00290 
00291   //Print table with results
00292   Bool_t UNIX = strcmp(gSystem->GetName(), "Unix") == 0;
00293   printf("******************************************************************\n");
00294   if (UNIX) {
00295      TString sp = gSystem->GetFromPipe("uname -a");
00296      sp.Resize(60);
00297      printf("*  SYS: %s\n",sp.Data());
00298      if (strstr(gSystem->GetBuildNode(),"Linux")) {
00299         sp = gSystem->GetFromPipe("lsb_release -d -s");
00300         printf("*  SYS: %s\n",sp.Data());
00301      }
00302      if (strstr(gSystem->GetBuildNode(),"Darwin")) {
00303         sp  = gSystem->GetFromPipe("sw_vers -productVersion");
00304         sp += " Mac OS X ";
00305         printf("*  SYS: %s\n",sp.Data());
00306      }
00307   } else {
00308     const Char_t *os = gSystem->Getenv("OS");
00309     if (!os) printf("*  SYS: Windows 95\n");
00310     else     printf("*  SYS: %s %s \n",os,gSystem->Getenv("PROCESSOR_IDENTIFIER"));
00311   }
00312 
00313   printf("******************************************************************\n");
00314   gBenchmark->Print("stressLinear");
00315   const Int_t nr = 7;
00316   const Double_t x_b12[] = { 10.,   30.,   50.,   100.,  300.,  500.,    700.};
00317   const Double_t y_b12[] = {10.74, 15.72, 20.00, 35.79, 98.77, 415.34, 1390.33};
00318 
00319   TGraph gr(nr,x_b12,y_b12);
00320   Double_t ct = gBenchmark->GetCpuTime("stressLinear");
00321   const Double_t rootmarks = 600*gr.Eval(maxSize)/ct;
00322 
00323   printf("******************************************************************\n");
00324   printf("*  ROOTMARKS =%6.1f   *  Root%-8s  %d/%d\n",rootmarks,gROOT->GetVersion(),
00325          gROOT->GetVersionDate(),gROOT->GetVersionTime());
00326   printf("******************************************************************\n");
00327 }
00328 
00329 //------------------------------------------------------------------------
00330 void StatusPrint(Int_t id,const TString &title,Bool_t status)
00331 {
00332   // Print test program number and its title
00333   const Int_t kMAX = 65;
00334   Char_t number[4];
00335   sprintf(number,"%2d",id);
00336   TString header = TString("Test ")+number+" : "+title;
00337   const Int_t nch = header.Length();
00338   for (Int_t i = nch; i < kMAX; i++) header += '.';
00339   cout << header << (status ? "OK" : "FAILED") << endl;
00340 }
00341 
00342 //------------------------------------------------------------------------
00343 //          Test allocation functions and compatibility check
00344 //
00345 void mstress_allocation(Int_t msize)
00346 {
00347   if (gVerbose)
00348     cout << "\n\n---> Test allocation and compatibility check" << endl;
00349 
00350   Int_t i,j;
00351   Bool_t ok = kTRUE;
00352 
00353   TMatrixD m1(4,msize);
00354   for (i = m1.GetRowLwb(); i <= m1.GetRowUpb(); i++)
00355     for (j = m1.GetColLwb(); j <= m1.GetColUpb(); j++)
00356       m1(i,j) = TMath::Pi()*i+TMath::E()*j;
00357 
00358   TMatrixD m2(0,3,0,msize-1);
00359   TMatrixD m3(1,4,0,msize-1);
00360   TMatrixD m4(m1);
00361 
00362   if (gVerbose) {
00363     cout << "\nStatus information reported for matrix m3:" << endl;
00364     cout << "  Row lower bound ... " << m3.GetRowLwb() << endl;
00365     cout << "  Row upper bound ... " << m3.GetRowUpb() << endl;
00366     cout << "  Col lower bound ... " << m3.GetColLwb() << endl;
00367     cout << "  Col upper bound ... " << m3.GetColUpb() << endl;
00368     cout << "  No. rows ..........." << m3.GetNrows()  << endl;
00369     cout << "  No. cols ..........." << m3.GetNcols()  << endl;
00370     cout << "  No. of elements ...." << m3.GetNoElements() << endl;
00371   }
00372 
00373   if (gVerbose)
00374     cout << "\nCheck matrices 1 & 2 for compatibility" << endl;
00375   ok &= AreCompatible(m1,m2,gVerbose);
00376 
00377   if (gVerbose)
00378     cout << "Check matrices 1 & 4 for compatibility" << endl;
00379   ok &= AreCompatible(m1,m4,gVerbose);
00380 
00381   if (gVerbose)
00382     cout << "m2 has to be compatible with m3 after resizing to m3" << endl;
00383   m2.ResizeTo(m3);
00384   ok &= AreCompatible(m2,m3,gVerbose);
00385 
00386   TMatrixD m5(m1.GetNrows()+1,m1.GetNcols()+5);
00387   for (i = m5.GetRowLwb(); i <= m5.GetRowUpb(); i++)
00388     for (j = m5.GetColLwb(); j <= m5.GetColUpb(); j++)
00389       m5(i,j) = TMath::Pi()*i+TMath::E()*j;
00390 
00391   if (gVerbose)
00392     cout << "m1 has to be compatible with m5 after resizing to m5" << endl;
00393   m1.ResizeTo(m5.GetNrows(),m5.GetNcols());
00394   ok &= AreCompatible(m1,m5,gVerbose);
00395 
00396   if (gVerbose)
00397     cout << "m1 has to be equal to m4 after stretching and shrinking" << endl;
00398   m1.ResizeTo(m4.GetNrows(),m4.GetNcols());
00399   ok &= VerifyMatrixIdentity(m1,m4,gVerbose,EPSILON);
00400   if (gVerbose)
00401     cout << "m5 has to be equal to m1 after shrinking" << endl;
00402   m5.ResizeTo(m1.GetNrows(),m1.GetNcols());
00403   ok &= VerifyMatrixIdentity(m1,m5,gVerbose,EPSILON);
00404 
00405   if (gVerbose)
00406     cout << "stretching and shrinking for small matrices (stack)" << endl;
00407   if (gVerbose)
00408     cout << "m8 has to be equal to m7 after stretching and shrinking" << endl;
00409   TMatrixD m6(4,4);
00410   for (i = m6.GetRowLwb(); i <= m6.GetRowUpb(); i++)
00411     for (j = m6.GetColLwb(); j <= m6.GetColUpb(); j++)
00412       m6(i,j) = TMath::Pi()*i+TMath::E()*j;
00413   TMatrixD m8(3,3);
00414   for (i = m8.GetRowLwb(); i <= m8.GetRowUpb(); i++)
00415     for (j = m8.GetColLwb(); j <= m8.GetColUpb(); j++)
00416       m8(i,j) = TMath::Pi()*i+TMath::E()*j;
00417   TMatrixD m7(m8);
00418 
00419   m8.ResizeTo(4,4);
00420   m8.ResizeTo(3,3);
00421   ok &= VerifyMatrixIdentity(m7,m8,gVerbose,EPSILON);
00422 
00423   if (gVerbose)
00424     cout << "m6 has to be equal to m8 after shrinking" << endl;
00425   m6.ResizeTo(3,3);
00426   ok &= VerifyMatrixIdentity(m6,m8,gVerbose,EPSILON);
00427 
00428   if (gVerbose)
00429     cout << "\nDone\n" << endl;
00430 
00431   StatusPrint(1,"Allocation, Resizing",ok);
00432 }
00433 
00434 class FillMatrix : public TElementPosActionD {
00435    Int_t no_elems,no_cols;
00436    void Operation(Double_t &element) const
00437       { element = 4*TMath::Pi()/no_elems * (fI*no_cols+fJ); }
00438 public:
00439    FillMatrix() {}
00440    FillMatrix(const TMatrixD &m) :
00441          no_elems(m.GetNoElements()),no_cols(m.GetNcols()) { }
00442 };
00443 
00444 //
00445 //------------------------------------------------------------------------
00446 //          Test Filling of matrix
00447 //
00448 void mstress_matrix_fill(Int_t rsize,Int_t csize)
00449 {
00450   if (gVerbose)
00451     cout << "\n\n---> Test different matrix filling methods\n" << endl;
00452 
00453   Bool_t ok = kTRUE;
00454   if (gVerbose)
00455     cout << "Creating m  with Apply function..." << endl;
00456   TMatrixD m(-1,rsize-2,1,csize);
00457 #ifndef __CINT__
00458   FillMatrix f(m);
00459   m.Apply(f);
00460 #else
00461   for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00462     for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00463       m(i,j) = 4*TMath::Pi()/m.GetNoElements() * (i*m.GetNcols()+j);
00464 #endif
00465 
00466   {
00467     if (gVerbose)
00468       cout << "Check identity between m and matrix filled through (i,j)" << endl;
00469 
00470     TMatrixD m_overload1(-1,rsize-2,1,csize);
00471     TMatrixD m_overload2(-1,rsize-2,1,csize);
00472 
00473     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00474     {
00475       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00476       {
00477         const Double_t val = 4*TMath::Pi()/rsize/csize*(i*csize+j);
00478         m_overload1(i,j)  = val;
00479         m_overload2[i][j] = val;
00480       }
00481     }
00482 
00483     ok &= VerifyMatrixIdentity(m,m_overload1,gVerbose,EPSILON);
00484     if (gVerbose)
00485       cout << "Check identity between m and matrix filled through [i][j]" << endl;
00486     ok &= VerifyMatrixIdentity(m,m_overload2,gVerbose,EPSILON);
00487     if (gVerbose)
00488       cout << "Check identity between matrix filled through [i][j] and (i,j)" << endl;
00489     ok &= VerifyMatrixIdentity(m_overload1,m_overload2,gVerbose,EPSILON);
00490   }
00491 
00492   {
00493     TArrayD a_fortran(rsize*csize);
00494     TArrayD a_c      (rsize*csize);
00495     for (Int_t i = 0; i < rsize; i++)
00496     {
00497       for (Int_t j = 0; j < csize; j++)
00498       {
00499         a_c[i*csize+j]       = 4*TMath::Pi()/rsize/csize*((i-1)*csize+j+1);
00500         a_fortran[i+rsize*j] = a_c[i*csize+j];
00501       }
00502     }
00503 
00504     if (gVerbose)
00505       cout << "Creating m_fortran by filling with fortran stored matrix" << endl;
00506     TMatrixD m_fortran(-1,rsize-2,1,csize,a_fortran.GetArray(),"F");
00507     if (gVerbose)
00508       cout << "Check identity between m and m_fortran" << endl;
00509     ok &= VerifyMatrixIdentity(m,m_fortran,gVerbose,EPSILON);
00510 
00511     if (gVerbose)
00512       cout << "Creating m_c by filling with c stored matrix" << endl;
00513     TMatrixD m_c(-1,rsize-2,1,csize,a_c.GetArray());
00514     if (gVerbose)
00515       cout << "Check identity between m and m_c" << endl;
00516     ok &= VerifyMatrixIdentity(m,m_c,gVerbose,EPSILON);
00517   }
00518 
00519   {
00520     if (gVerbose)
00521       cout << "Check insertion/extraction of sub-matrices" << endl;
00522     {
00523       TMatrixD m_sub1 = m;
00524       m_sub1.ResizeTo(0,rsize-2,2,csize);
00525       TMatrixD m_sub2 = m.GetSub(0,rsize-2,2,csize,"");
00526       ok &= VerifyMatrixIdentity(m_sub1,m_sub2,gVerbose,EPSILON);
00527     }
00528 
00529     {
00530       TMatrixD m2(-1,rsize-2,1,csize);
00531       TMatrixD m_part1 = m.GetSub(0,rsize-2,2,csize,"");
00532       TMatrixD m_part2 = m.GetSub(0,rsize-2,1,1,"");
00533       TMatrixD m_part3 = m.GetSub(-1,-1,2,csize,"");
00534       TMatrixD m_part4 = m.GetSub(-1,-1,1,1,"");
00535       m2.SetSub(0,2,m_part1);
00536       m2.SetSub(0,1,m_part2);
00537       m2.SetSub(-1,2,m_part3);
00538       m2.SetSub(-1,1,m_part4);
00539       ok &= VerifyMatrixIdentity(m,m2,gVerbose,EPSILON);
00540     }
00541 
00542     {
00543       TMatrixD m2(-1,rsize-2,1,csize);
00544       TMatrixD m_part1 = m.GetSub(0,rsize-2,2,csize,"S");
00545       TMatrixD m_part2 = m.GetSub(0,rsize-2,1,1,"S");
00546       TMatrixD m_part3 = m.GetSub(-1,-1,2,csize,"S");
00547       TMatrixD m_part4 = m.GetSub(-1,-1,1,1,"S");
00548       m2.SetSub(0,2,m_part1);
00549       m2.SetSub(0,1,m_part2);
00550       m2.SetSub(-1,2,m_part3);
00551       m2.SetSub(-1,1,m_part4);
00552       ok &= VerifyMatrixIdentity(m,m2,gVerbose,EPSILON);
00553     }
00554   }
00555 
00556   {
00557     if (gVerbose)
00558       cout << "Check sub-matrix views" << endl;
00559     {
00560       TMatrixD m3(-1,rsize-2,1,csize);
00561       TMatrixDSub(m3,0,rsize-2,2,csize) = TMatrixDSub(m,0,rsize-2,2,csize);
00562       TMatrixDSub(m3,0,rsize-2,1,1)     = TMatrixDSub(m,0,rsize-2,1,1);
00563       TMatrixDSub(m3,-1,-1,2,csize)     = TMatrixDSub(m,-1,-1,2,csize);
00564       TMatrixDSub(m3,-1,-1,1,1)         = TMatrixDSub(m,-1,-1,1,1);
00565       ok &= VerifyMatrixIdentity(m,m3,gVerbose,EPSILON);
00566 
00567       TMatrixD unit(3,3);
00568       TMatrixDSub(m3,1,3,1,3)  = unit.UnitMatrix();
00569       TMatrixDSub(m3,1,3,1,3) *= m.GetSub(1,3,1,3);
00570       ok &= VerifyMatrixIdentity(m,m3,gVerbose,EPSILON);
00571 
00572       TMatrixDSub(m3,0,rsize-2,2,csize) = 1.0;
00573       TMatrixDSub(m3,0,rsize-2,1,1)     = 1.0;
00574       TMatrixDSub(m3,-1,-1,2,csize)     = 1.0;
00575       TMatrixDSub(m3,-1,-1,1,1)         = 1.0;
00576       ok &= (m3 == 1.0);
00577 
00578     }
00579   }
00580 
00581   {
00582     if (gVerbose)
00583       cout << "Check array Use" << endl;
00584     {
00585       TMatrixD *m1a = new TMatrixD(m);
00586       TMatrixD *m2a = new TMatrixD();
00587       m2a->Use(m1a->GetRowLwb(),m1a->GetRowUpb(),m1a->GetColLwb(),m1a->GetColUpb(),m1a->GetMatrixArray());
00588       ok &= VerifyMatrixIdentity(m,*m2a,gVerbose,EPSILON);
00589       m2a->Sqr();
00590       TMatrixD m4 = m; m4.Sqr();
00591       ok &= VerifyMatrixIdentity(m4,*m1a,gVerbose,EPSILON);
00592       delete m1a;
00593       delete m2a;
00594     }
00595   }
00596 
00597   if (gVerbose)
00598     cout << "\nDone\n" << endl;
00599 
00600   StatusPrint(2,"Filling, Inserting, Using",ok);
00601 }
00602 
00603 //
00604 //------------------------------------------------------------------------
00605 //                Test uniform element operations
00606 //
00607 typedef  Double_t (*dfunc)(Double_t);
00608 class ApplyFunction : public TElementActionD {
00609    dfunc fFunc;
00610    void Operation(Double_t &element) const { element = fFunc(Double_t(element)); }
00611 public:
00612    ApplyFunction(dfunc func) : fFunc(func) { }
00613 };
00614 
00615 void mstress_element_op(Int_t rsize,Int_t csize)
00616 {
00617   Bool_t ok = kTRUE;
00618   const Double_t pattern = 8.625;
00619 
00620   TMatrixD m(-1,rsize-2,1,csize);
00621 
00622   if (gVerbose)
00623     cout << "\nWriting zeros to m..." << endl;
00624   {
00625     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00626       for(Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00627         m(i,j) = 0;
00628     ok &= VerifyMatrixValue(m,0.,gVerbose,EPSILON);
00629   }
00630 
00631   if (gVerbose)
00632     cout << "Creating zero m1 ..." << endl;
00633   TMatrixD m1(TMatrixD::kZero, m);
00634   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
00635 
00636   if (gVerbose)
00637     cout << "Comparing m1 with 0 ..." << endl;
00638   R__ASSERT(m1 == 0);
00639   R__ASSERT(!(m1 != 0));
00640 
00641   if (gVerbose)
00642     cout << "Writing a pattern " << pattern << " by assigning to m(i,j)..." << endl;
00643   {
00644     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00645       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00646         m(i,j) = pattern;
00647     ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
00648   }
00649 
00650   if (gVerbose)
00651     cout << "Writing the pattern by assigning to m1 as a whole ..."  << endl;
00652   m1 = pattern;
00653   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00654 
00655   if (gVerbose)
00656     cout << "Comparing m and m1 ..." << endl;
00657   R__ASSERT(m == m1);
00658   if (gVerbose)
00659     cout << "Comparing (m=0) and m1 ..." << endl;
00660   R__ASSERT(!(m.Zero() == m1));
00661 
00662   if (gVerbose)
00663     cout << "Clearing m1 ..." << endl;
00664   m1.Zero();
00665   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
00666 
00667   if (gVerbose)
00668     cout << "\nClear m and add the pattern" << endl;
00669   m.Zero();
00670   m += pattern;
00671   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
00672   if (gVerbose)
00673     cout << "   add the doubled pattern with the negative sign" << endl;
00674   m += -2*pattern;
00675   ok &= VerifyMatrixValue(m,-pattern,gVerbose,EPSILON);
00676   if (gVerbose)
00677     cout << "   subtract the trippled pattern with the negative sign" << endl;
00678   m -= -3*pattern;
00679   ok &= VerifyMatrixValue(m,2*pattern,gVerbose,EPSILON);
00680 
00681   if (gVerbose)
00682     cout << "\nVerify comparison operations when all elems are the same" << endl;
00683   m = pattern;
00684   R__ASSERT( m == pattern && !(m != pattern) );
00685   R__ASSERT( m > 0 && m >= pattern && m <= pattern );
00686   R__ASSERT( m > -pattern && m >= -pattern );
00687   R__ASSERT( m <= pattern && !(m < pattern) );
00688   m -= 2*pattern;
00689   R__ASSERT( m  < -pattern/2 && m <= -pattern/2 );
00690   R__ASSERT( m  >= -pattern && !(m > -pattern) );
00691 
00692   if (gVerbose)
00693     cout << "\nVerify comparison operations when not all elems are the same" << endl;
00694   m = pattern; m(m.GetRowUpb(),m.GetColUpb()) = pattern-1;
00695   R__ASSERT( !(m == pattern) && !(m != pattern) );
00696   R__ASSERT( m != 0 );                   // none of elements are 0
00697   R__ASSERT( !(m >= pattern) && m <= pattern && !(m<pattern) );
00698   R__ASSERT( !(m <= pattern-1) && m >= pattern-1 && !(m>pattern-1) );
00699 
00700   if (gVerbose)
00701     cout << "\nAssign 2*pattern to m by repeating additions" << endl;
00702   m = 0; m += pattern; m += pattern;
00703   if (gVerbose)
00704     cout << "Assign 2*pattern to m1 by multiplying by two " << endl;
00705   m1 = pattern; m1 *= 2;
00706   ok &= VerifyMatrixValue(m1,2*pattern,gVerbose,EPSILON);
00707   R__ASSERT( m == m1 );
00708   if (gVerbose)
00709     cout << "Multiply m1 by one half returning it to the 1*pattern" << endl;
00710   m1 *= 1/2.;
00711   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00712 
00713   if (gVerbose)
00714     cout << "\nAssign -pattern to m and m1" << endl;
00715   m.Zero(); m -= pattern; m1 = -pattern;
00716   ok &= VerifyMatrixValue(m,-pattern,gVerbose,EPSILON);
00717   R__ASSERT( m == m1 );
00718   if (gVerbose)
00719     cout << "m = sqrt(sqr(m)); m1 = abs(m1); Now m and m1 have to be the same" << endl;
00720   m.Sqr();
00721   ok &= VerifyMatrixValue(m,pattern*pattern,gVerbose,EPSILON);
00722   m.Sqrt();
00723   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
00724   m1.Abs();
00725   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00726   ok &= VerifyMatrixIdentity(m1,m,gVerbose,EPSILON);
00727 
00728   if (gVerbose)
00729     cout << "\nCheck out to see that sin^2(x) + cos^2(x) = 1" << endl;
00730   {
00731 #ifndef __CINT__
00732     FillMatrix f(m);
00733     m.Apply(f);
00734 #else
00735     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00736       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00737         m(i,j) = 4*TMath::Pi()/m.GetNoElements() * (i*m.GetNcols()+j);
00738 #endif
00739   }
00740   m1 = m;
00741   {
00742 #ifndef __CINT__
00743     ApplyFunction s(&TMath::Sin);
00744     ApplyFunction c(&TMath::Cos);
00745     m.Apply(s);
00746     m1.Apply(c);
00747 #else
00748     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
00749       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++) {
00750         m(i,j)  = TMath::Sin(m(i,j));
00751         m1(i,j) = TMath::Cos(m1(i,j));
00752       }
00753     }
00754 #endif
00755   }
00756   m.Sqr();
00757   m1.Sqr();
00758   m += m1;
00759   ok &= VerifyMatrixValue(m,1.,gVerbose,EPSILON);
00760 
00761   if (gVerbose)
00762     cout << "\nDone\n" << endl;
00763 
00764   StatusPrint(3,"Uniform matrix operations",ok);
00765 }
00766 
00767 //
00768 //------------------------------------------------------------------------
00769 //        Test binary matrix element-by-element operations
00770 //
00771 void mstress_binary_ebe_op(Int_t rsize, Int_t csize)
00772 {
00773   if (gVerbose)
00774     cout << "\n---> Test Binary Matrix element-by-element operations" << endl;
00775 
00776   Bool_t ok = kTRUE;
00777   const Double_t pattern = 4.25;
00778 
00779   TMatrixD m(2,rsize+1,0,csize-1);
00780   TMatrixD m1(TMatrixD::kZero,m);
00781   TMatrixD mp(TMatrixD::kZero,m);
00782 
00783   {
00784     for (Int_t i = mp.GetRowLwb(); i <= mp.GetRowUpb(); i++)
00785       for (Int_t j = mp.GetColLwb(); j <= mp.GetColUpb(); j++)
00786         mp(i,j) = (i-m.GetNrows()/2.)*j*pattern;
00787   }
00788 
00789   if (gVerbose)
00790     cout << "\nVerify assignment of a matrix to the matrix" << endl;
00791   m = pattern;
00792   m1.Zero();
00793   m1 = m;
00794   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00795   R__ASSERT( m1 == m );
00796 
00797   if (gVerbose)
00798     cout << "\nAdding the matrix to itself, uniform pattern " << pattern << endl;
00799   m.Zero(); m = pattern;
00800   m1 = m; m1 += m1;
00801   ok &= VerifyMatrixValue(m1,2*pattern,gVerbose,EPSILON);
00802   if (gVerbose)
00803     cout << "  subtracting two matrices ..." << endl;
00804   m1 -= m;
00805   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00806   if (gVerbose)
00807     cout << "  subtracting the matrix from itself" << endl;
00808   m1 -= m1;
00809   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
00810   if (gVerbose)
00811     cout << "  adding two matrices together" << endl;
00812   m1 += m;
00813   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00814 
00815   if (gVerbose) {
00816     cout << "\nArithmetic operations on matrices with not the same elements" << endl;
00817     cout << "   adding mp to the zero matrix..." << endl;
00818   }
00819   m.Zero(); m += mp;
00820   ok &= VerifyMatrixIdentity(m,mp,gVerbose,EPSILON);
00821   m1 = m;
00822   if (gVerbose)
00823     cout << "   making m = 3*mp and m1 = 3*mp, via add() and succesive mult" << endl;
00824   Add(m,2.,mp);
00825   m1 += m1; m1 += mp;
00826   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00827   if (gVerbose)
00828     cout << "   clear both m and m1, by subtracting from itself and via add()" << endl;
00829   m1 -= m1;
00830   Add(m,-3.,mp);
00831   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00832 
00833   if (gVerbose) {
00834     cout << "\nTesting element-by-element multiplications and divisions" << endl;
00835     cout << "   squaring each element with sqr() and via multiplication" << endl;
00836   }
00837   m = mp; m1 = mp;
00838   m.Sqr();
00839   ElementMult(m1,m1);
00840   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00841   if (gVerbose)
00842     cout << "   compare (m = pattern^2)/pattern with pattern" << endl;
00843   m = pattern; m1 = pattern;
00844   m.Sqr();
00845   ElementDiv(m,m1);
00846   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
00847   if (gVerbose)
00848     Compare(m1,m);
00849 
00850   if (gVerbose)
00851     cout << "\nDone\n" << endl;
00852 
00853   StatusPrint(4,"Binary Matrix element-by-element operations",ok);
00854 }
00855 
00856 //
00857 //------------------------------------------------------------------------
00858 //              Verify matrix transposition
00859 //
00860 void mstress_transposition(Int_t msize)
00861 {
00862   if (gVerbose) {
00863     cout << "\n---> Verify matrix transpose "
00864             "for matrices of a characteristic size " << msize << endl;
00865   }
00866 
00867   Bool_t ok = kTRUE;
00868   {
00869     if (gVerbose)
00870       cout << "\nCheck to see that a square UnitMatrix stays the same";
00871     TMatrixD m(msize,msize);
00872     m.UnitMatrix();
00873     TMatrixD mt(TMatrixD::kTransposed,m);
00874     ok &= ( m == mt ) ? kTRUE : kFALSE;
00875   }
00876 
00877   {
00878     if (gVerbose)
00879       cout << "\nTest a non-square UnitMatrix";
00880     TMatrixD m(msize,msize+1);
00881     m.UnitMatrix();
00882     TMatrixD mt(TMatrixD::kTransposed,m);
00883     R__ASSERT(m.GetNrows() == mt.GetNcols() && m.GetNcols() == mt.GetNrows() );
00884     for (Int_t i = m.GetRowLwb(); i <= TMath::Min(m.GetRowUpb(),m.GetColUpb()); i++)
00885       for (Int_t j = m.GetColLwb(); j <= TMath::Min(m.GetRowUpb(),m.GetColUpb()); j++)
00886         ok &= ( m(i,j) == mt(i,j) ) ? kTRUE : kFALSE;
00887   }
00888 
00889   {
00890     if (gVerbose)
00891       cout << "\nCheck to see that a symmetric (Hilbert)Matrix stays the same";
00892     TMatrixD m = THilbertMatrixD(msize,msize);
00893     TMatrixD mt(TMatrixD::kTransposed,m);
00894     ok &= ( m == mt ) ? kTRUE : kFALSE;
00895   }
00896 
00897   {
00898     if (gVerbose)
00899       cout << "\nCheck transposing a non-symmetric matrix";
00900     TMatrixD m = THilbertMatrixD(msize+1,msize);
00901     m(1,2) = TMath::Pi();
00902     TMatrixD mt(TMatrixD::kTransposed,m);
00903     R__ASSERT(m.GetNrows() == mt.GetNcols() && m.GetNcols() == mt.GetNrows());
00904     R__ASSERT(mt(2,1)  == (Double_t)TMath::Pi() && mt(1,2)  != (Double_t)TMath::Pi());
00905     R__ASSERT(mt[2][1] == (Double_t)TMath::Pi() && mt[1][2] != (Double_t)TMath::Pi());
00906 
00907     if (gVerbose)
00908       cout << "\nCheck double transposing a non-symmetric matrix" << endl;
00909     TMatrixD mtt(TMatrixD::kTransposed,mt);
00910     ok &= ( m == mtt ) ? kTRUE : kFALSE;
00911   }
00912 
00913   if (gVerbose)
00914     cout << "\nDone\n" << endl;
00915 
00916   StatusPrint(5,"Matrix transposition",ok);
00917 }
00918 
00919 //
00920 //------------------------------------------------------------------------
00921 //           Test special matrix creation
00922 //
00923 class MakeHilbert : public TElementPosActionD {
00924   void Operation(Double_t &element) const { element = 1./(fI+fJ+1); }
00925 public:
00926   MakeHilbert() { }
00927 };
00928 
00929 #if !defined (__CINT__) || defined (__MAKECINT__)
00930 class TestUnit : public TElementPosActionD {
00931   mutable Int_t fIsUnit;
00932   void Operation(Double_t &element) const
00933       { if (fIsUnit)
00934           fIsUnit = ((fI==fJ) ? (element == 1.0) : (element == 0)); }
00935 public:
00936   TestUnit() : fIsUnit(0==0) { }
00937   Int_t is_indeed_unit() const { return fIsUnit; }
00938 };
00939 #else
00940   Bool_t is_indeed_unit(TMatrixD &m) {
00941     Bool_t isUnit = kTRUE;
00942     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00943       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++) {
00944         if (isUnit)
00945           isUnit = ((i==j) ? (m(i,j) == 1.0) : (m(i,j) == 0));
00946       }
00947     return isUnit;
00948   }
00949 #endif
00950 
00951 void mstress_special_creation(Int_t dim)
00952 {
00953   if (gVerbose)
00954     cout << "\n---> Check creating some special matrices of dimension " << dim << endl;
00955 
00956   Bool_t ok = kTRUE;
00957   {
00958     if (gVerbose)
00959       cout << "\ntest creating Hilbert matrices" << endl;
00960     TMatrixD m = THilbertMatrixD(dim+1,dim);
00961     TMatrixD m1(TMatrixD::kZero,m);
00962     ok &= ( !(m == m1) ) ? kTRUE : kFALSE;
00963     ok &= ( m != 0 ) ? kTRUE : kFALSE;
00964 #ifndef __CINT__
00965     MakeHilbert mh;
00966     m1.Apply(mh);
00967 #else
00968     for (Int_t i = m1.GetRowLwb(); i <= m1.GetRowUpb(); i++)
00969       for (Int_t j = m1.GetColLwb(); j <= m1.GetColUpb(); j++)
00970         m1(i,j) = 1./(i+j+1);
00971 #endif
00972     ok &= ( m1 != 0 ) ? kTRUE : kFALSE;
00973     ok &= ( m == m1 ) ? kTRUE : kFALSE;
00974   }
00975 
00976   {
00977     if (gVerbose)
00978       cout << "test creating zero matrix and copy constructor" << endl;
00979     TMatrixD m = THilbertMatrixD(dim,dim+1);
00980     ok &= ( m != 0 ) ? kTRUE : kFALSE;
00981     TMatrixD m1(m);               // Applying the copy constructor
00982     ok &= ( m1 == m ) ? kTRUE : kFALSE;
00983     TMatrixD m2(TMatrixD::kZero,m);
00984     ok &= ( m2 == 0 ) ? kTRUE : kFALSE;
00985     ok &= ( m != 0 ) ? kTRUE : kFALSE;
00986   }
00987 
00988   {
00989     if (gVerbose)
00990       cout << "test creating unit matrices" << endl;
00991     TMatrixD m(dim,dim);
00992 #ifndef __CINT__
00993     {
00994       TestUnit test_unit;
00995       m.Apply(test_unit);
00996       ok &= ( !test_unit.is_indeed_unit() ) ? kTRUE : kFALSE;
00997     }
00998 #else
00999     ok &= ( !is_indeed_unit(m) ) ? kTRUE : kFALSE;
01000 #endif
01001     m.UnitMatrix();
01002 #ifndef __CINT__
01003     {
01004       TestUnit test_unit;
01005        m.Apply(test_unit);
01006        ok &= ( test_unit.is_indeed_unit() ) ? kTRUE : kFALSE;
01007     }
01008 #else
01009     ok &= ( is_indeed_unit(m) ) ? kTRUE : kFALSE;
01010 #endif
01011     m.ResizeTo(dim-1,dim);
01012     TMatrixD m2(TMatrixD::kUnit,m);
01013 #ifndef __CINT__
01014     {
01015       TestUnit test_unit;
01016       m2.Apply(test_unit);
01017       ok &= ( test_unit.is_indeed_unit() ) ? kTRUE : kFALSE;
01018     }
01019 #else
01020     ok &= ( is_indeed_unit(m2) ) ? kTRUE : kFALSE;
01021 #endif
01022     m.ResizeTo(dim,dim-2);
01023     m.UnitMatrix();
01024 #ifndef __CINT__
01025     {
01026       TestUnit test_unit;
01027       m.Apply(test_unit);
01028       ok &= ( test_unit.is_indeed_unit() ) ? kTRUE : kFALSE;
01029     }
01030 #else
01031     ok &= ( is_indeed_unit(m) ) ? kTRUE : kFALSE;
01032 #endif
01033   }
01034 
01035   {
01036     if (gVerbose)
01037       cout << "check to see that Haar matrix has *exactly* orthogonal columns" << endl;
01038     Int_t j;
01039     const Int_t order = 5;
01040     const TMatrixD haar = THaarMatrixD(order);
01041     ok &= ( haar.GetNrows() == (1<<order) &&
01042                haar.GetNrows() == haar.GetNcols() ) ? kTRUE : kFALSE;
01043     TVectorD colj(1<<order);
01044     TVectorD coll(1<<order);
01045     for (j = haar.GetColLwb(); j <= haar.GetColUpb(); j++) {
01046       colj = TMatrixDColumn_const(haar,j);
01047       ok &= (TMath::Abs(colj*colj-1.0) <= 1.0e-15 ) ? kTRUE : kFALSE;
01048       for (Int_t l = j+1; l <= haar.GetColUpb(); l++) {
01049         coll = TMatrixDColumn_const(haar,l);
01050         const Double_t val = colj*coll;
01051         ok &= ( TMath::Abs(val) <= 1.0e-15 ) ? kTRUE : kFALSE;
01052       }
01053     }
01054 
01055     if (gVerbose)
01056       cout << "make Haar (sub)matrix and test it *is* a submatrix" << endl;
01057     const Int_t no_sub_cols = (1<<order) - 3;
01058     const TMatrixD haar_sub = THaarMatrixD(order,no_sub_cols);
01059     ok &= ( haar_sub.GetNrows() == (1<<order) &&
01060                haar_sub.GetNcols() == no_sub_cols ) ? kTRUE : kFALSE;
01061     for (j = haar_sub.GetColLwb(); j <= haar_sub.GetColUpb(); j++) {
01062       colj = TMatrixDColumn_const(haar,j);
01063       coll = TMatrixDColumn_const(haar_sub,j);
01064       ok &= VerifyVectorIdentity(colj,coll,gVerbose);
01065     }
01066   }
01067 
01068   if (gVerbose)
01069     cout << "\nDone\n" << endl;
01070 
01071   StatusPrint(6,"Haar/Hilbert Matrix",ok);
01072 }
01073 
01074 #ifndef __CINT__
01075 //
01076 //------------------------------------------------------------------------
01077 //           Test matrix promises
01078 //
01079 class hilbert_matrix_promise : public TMatrixDLazy {
01080   void FillIn(TMatrixD &m) const { m = THilbertMatrixD(m.GetRowLwb(),m.GetRowUpb(),
01081                                                    m.GetColLwb(),m.GetColUpb()); }
01082 
01083 public:
01084   hilbert_matrix_promise(Int_t nrows,Int_t ncols)
01085      : TMatrixDLazy(nrows,ncols) {}
01086   hilbert_matrix_promise(Int_t row_lwb,Int_t row_upb,
01087                          Int_t col_lwb,Int_t col_upb)
01088      : TMatrixDLazy(row_lwb,row_upb,col_lwb,col_upb) { }
01089 };
01090 
01091 void mstress_matrix_promises(Int_t dim)
01092 {
01093   if (gVerbose)
01094     cout << "\n---> Check making/forcing promises, (lazy)matrices of dimension " << dim << endl;
01095 
01096   Bool_t ok = kTRUE;
01097   {
01098     if (gVerbose)
01099       cout << "\nmake a promise and force it by a constructor" << endl;
01100     TMatrixD m  = hilbert_matrix_promise(dim,dim+1);
01101     TMatrixD m1 = THilbertMatrixD(dim,dim+1);
01102     ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
01103   }
01104 
01105   {
01106     if (gVerbose)
01107       cout << "make a promise and force it by an assignment" << endl;
01108     TMatrixD m(-1,dim,0,dim);
01109     m = hilbert_matrix_promise(-1,dim,0,dim);
01110     TMatrixD m1 = THilbertMatrixD(-1,dim,0,dim);
01111     ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
01112   }
01113 
01114   if (gVerbose)
01115     cout << "\nDone\n" << endl;
01116 
01117   StatusPrint(7,"Matrix promises",ok);
01118 }
01119 #endif
01120 
01121 //
01122 //------------------------------------------------------------------------
01123 //             Verify the norm calculation
01124 //
01125 void mstress_norms(Int_t rsize_req,Int_t csize_req)
01126 {
01127   if (gVerbose)
01128     cout << "\n---> Verify norm calculations" << endl;
01129 
01130   Bool_t ok = kTRUE;
01131   const Double_t pattern = 10.25;
01132 
01133   Int_t rsize = rsize_req;
01134   if (rsize%2 != 0)  rsize--;
01135   Int_t csize = csize_req;
01136   if (csize%2 != 0)  csize--;
01137   if (rsize%2 == 1 || csize%2 == 1) {
01138     cout << "rsize: " << rsize <<endl;
01139     cout << "csize: " << csize <<endl;
01140     Fatal("mstress_norms","Sorry, size of the matrix to test must be even for this test\n");
01141   }
01142 
01143   TMatrixD m(rsize,csize);
01144 
01145   if (gVerbose)
01146     cout << "\nAssign " << pattern << " to all the elements and check norms" << endl;
01147   m = pattern;
01148   if (gVerbose)
01149     cout << "  1. (col) norm should be pattern*nrows" << endl;
01150   ok &= ( m.Norm1() == pattern*m.GetNrows() ) ? kTRUE : kFALSE;
01151   ok &= ( m.Norm1() == m.ColNorm() ) ? kTRUE : kFALSE;
01152   if (gVerbose)
01153     cout << "  Inf (row) norm should be pattern*ncols" << endl;
01154   ok &= ( m.NormInf() == pattern*m.GetNcols() ) ? kTRUE : kFALSE;
01155   ok &= ( m.NormInf() == m.RowNorm() ) ? kTRUE : kFALSE;
01156   if (gVerbose)
01157     cout << "  Square of the Eucl norm has got to be pattern^2 * no_elems" << endl;
01158   ok &= ( m.E2Norm() == (pattern*pattern)*m.GetNoElements() ) ? kTRUE : kFALSE;
01159   TMatrixD m1(TMatrixD::kZero,m);
01160   ok &= ( m.E2Norm() == E2Norm(m,m1) ) ? kTRUE : kFALSE;
01161 
01162   if (gVerbose)
01163     cout << "\nDone\n" << endl;
01164 
01165   StatusPrint(8,"Matrix Norms",ok);
01166 }
01167 
01168 //
01169 //------------------------------------------------------------------------
01170 //              Verify the determinant evaluation
01171 //
01172 void mstress_determinant(Int_t msize)
01173 {
01174   if (gVerbose)
01175     cout << "\n---> Verify determinant evaluation for a square matrix of size " << msize << endl;
01176 
01177   Bool_t ok = kTRUE;
01178   TMatrixD m(msize,msize);
01179   const Double_t pattern = 2.5;
01180 
01181   {
01182     if (gVerbose)
01183       cout << "\nCheck to see that the determinant of the unit matrix is one" <<endl;
01184     m.UnitMatrix();
01185     Double_t d1,d2;
01186     m.Determinant(d1,d2);
01187     const Double_t det = d1*TMath::Power(2.,d2);
01188     if (gVerbose) {
01189       cout << "det = " << det << " deviation= " << TMath::Abs(det-1);
01190       cout << ( (TMath::Abs(det-1) < EPSILON) ? " OK" : " too large") <<endl;
01191     }
01192     ok &= (TMath::Abs(det-1) < EPSILON) ? kTRUE : kFALSE;
01193   }
01194 
01195   if (ok)
01196   {
01197     if (gVerbose)
01198       cout << "\nCheck the determinant for the matrix with " << pattern << " at the diagonal" << endl;
01199     {
01200       for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
01201         for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
01202           m(i,j) = ( i==j ? pattern : 0 );
01203     }
01204     Double_t d1,d2;
01205     m.Determinant(d1,d2);
01206     const Double_t d1_abs = TMath::Abs(d1);
01207     const Double_t log_det1 = d2*TMath::Log(2.)+TMath::Log(d1_abs);
01208     const Double_t log_det2 = ((Double_t)m.GetNrows())*TMath::Log(pattern);
01209     if (gVerbose) {
01210       cout << "log_det1 = " << log_det1 << " deviation= " << TMath::Abs(log_det1-log_det2);
01211       cout << ( (TMath::Abs(log_det1-log_det2) < msize*EPSILON) ? " OK" : " too large") <<endl;
01212     }
01213     ok &= ( TMath::Abs(log_det1-log_det2) < msize*EPSILON  ) ? kTRUE : kFALSE;
01214   }
01215 
01216   if (ok)
01217   {
01218     if (gVerbose)
01219       cout << "\nCheck the determinant of the transposed matrix" << endl;
01220     m.UnitMatrix();
01221     m(1,2) = pattern;
01222     TMatrixD m_tran(TMatrixD::kTransposed,m);
01223     ok &= ( !(m == m_tran) ) ? kTRUE : kFALSE;
01224     const Double_t det1 = m.Determinant();
01225     const Double_t det2 = m_tran.Determinant();
01226     if (gVerbose) {
01227       cout << "det1 = " << det1 << " deviation= " << TMath::Abs(det1-det2);
01228       cout << ( (TMath::Abs(det1-det2) < msize*EPSILON) ? " OK" : " too large") <<endl;
01229     }
01230     ok &= ( TMath::Abs(det1-det2) < msize*EPSILON ) ? kTRUE : kFALSE;
01231   }
01232 
01233   if (ok)
01234   {
01235     if (gVerbose)
01236       cout << "\nswap two rows/cols of a matrix through method 1 and watch det's sign" << endl;
01237     m.UnitMatrix();
01238     TMatrixDRow(m,3) = pattern;
01239     Double_t d1,d2;
01240     m.Determinant(d1,d2);
01241     TMatrixDRow row1(m,1);
01242     TVectorD vrow1(m.GetRowLwb(),m.GetRowUpb()); vrow1 = row1;
01243     TVectorD vrow3(m.GetRowLwb(),m.GetRowUpb()); vrow3 = TMatrixDRow(m,3);
01244     row1 = vrow3; TMatrixDRow(m,3) = vrow1;
01245     Double_t d1_p,d2_p;
01246     m.Determinant(d1_p,d2_p);
01247     if (gVerbose) {
01248       cout << "d1 = " << d1 << " deviation= " << TMath::Abs(d1+d1_p);
01249       cout << ( ( d1 == -d1_p ) ? " OK" : " too large") <<endl;
01250     }
01251     ok &= ( d1 == -d1_p ) ? kTRUE : kFALSE;
01252     TMatrixDColumn col2(m,2);
01253     TVectorD vcol2(m.GetRowLwb(),m.GetRowUpb()); vcol2 = col2;
01254     TVectorD vcol4(m.GetRowLwb(),m.GetRowUpb()); vcol4 = TMatrixDColumn(m,4);
01255     col2 = vcol4; TMatrixDColumn(m,4) = vcol2;
01256     m.Determinant(d1_p,d2_p);
01257     if (gVerbose) {
01258       cout << "d1 = " << d1 << " deviation= " << TMath::Abs(d1-d1_p);
01259       cout << ( ( d1 == d1_p ) ? " OK" : " too large") <<endl;
01260     }
01261     ok &= ( d1 == d1_p ) ? kTRUE : kFALSE;
01262   }
01263 
01264   if (ok)
01265   {
01266     if (gVerbose)
01267       cout << "\nswap two rows/cols of a matrix through method 2 and watch det's sign" << endl;
01268     m.UnitMatrix();
01269     TMatrixDRow(m,3) = pattern;
01270     Double_t d1,d2;
01271     m.Determinant(d1,d2);
01272 
01273     TMatrixD m_save( m);
01274     TMatrixDRow(m,1) = TMatrixDRow(m_save,3);
01275     TMatrixDRow(m,3) = TMatrixDRow(m_save,1);
01276     Double_t d1_p,d2_p;
01277     m.Determinant(d1_p,d2_p);
01278     if (gVerbose) {
01279       cout << "d1 = " << d1 << " deviation= " << TMath::Abs(d1+d1_p);
01280       cout << ( ( d1 == -d1_p ) ? " OK" : " too large") <<endl;
01281     }
01282     ok &= ( d1 == -d1_p ) ? kTRUE : kFALSE;
01283 
01284     m_save = m;
01285     TMatrixDColumn(m,2) = TMatrixDColumn(m_save,4);
01286     TMatrixDColumn(m,4) = TMatrixDColumn(m_save,2);
01287     m.Determinant(d1_p,d2_p);
01288     if (gVerbose) {
01289       cout << "d1 = " << d1 << " deviation= " << TMath::Abs(d1-d1_p);
01290       cout << ( ( d1 == d1_p ) ? " OK" : " too large") <<endl;
01291     }
01292     ok &= ( d1 == d1_p ) ? kTRUE : kFALSE;
01293   }
01294 
01295   if (ok)
01296   {
01297     if (gVerbose)
01298       cout << "\nCheck the determinant for the matrix with " << pattern << " at the anti-diagonal" << endl;
01299     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
01300       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
01301         m(i,j) = ( i==(m.GetColUpb()+m.GetColLwb()-j) ? pattern : 0 );
01302 
01303     Double_t d1,d2;
01304     m.Determinant(d1,d2);
01305     const Double_t d1_abs = TMath::Abs(d1);
01306     const Double_t log_det1 = d2*TMath::Log(2.)+TMath::Log(d1_abs);
01307     const Double_t log_det2 = ((Double_t)m.GetNrows())*TMath::Log(pattern);
01308     const Double_t sign     = ( m.GetNrows()*(m.GetNrows()-1)/2 & 1 ? -1 : 1 );
01309     if (gVerbose) {
01310       cout << "log_det1 = " << log_det1 << " deviation= " << TMath::Abs(log_det1-log_det2);
01311       cout << ( (TMath::Abs(log_det1-log_det2) < msize*EPSILON) ? " OK" : " too large") <<endl;
01312       cout << ( sign * d1 > 0. ? " OK sign" : " wrong sign") <<endl;
01313     }
01314     ok &= ( TMath::Abs(log_det1-log_det2) < msize*EPSILON  ) ? kTRUE : kFALSE;
01315     ok &= ( sign * d1 > 0. ) ? kTRUE : kFALSE;
01316   }
01317 
01318   // Next test disabled because it produces (of course) a Warning
01319   if (0) {
01320     if (gVerbose)
01321       cout << "\nCheck the determinant for the singular matrix"
01322               "\n       defined as above with zero first row" << endl;
01323     m.Zero();
01324     {
01325       for (Int_t i = m.GetRowLwb()+1; i <= m.GetRowUpb(); i++)
01326         for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
01327           m(i,j) = ( i==(m.GetColUpb()+m.GetColLwb()-j) ? pattern : 0 );
01328     }
01329     cout << "\n determinant is " << m.Determinant();
01330     ok &= ( m.Determinant() == 0 ) ? kTRUE : kFALSE;
01331   }
01332 
01333   if (gVerbose)
01334     cout << "\nCheck out the determinant of the Hilbert matrix";
01335   TMatrixDSym H = THilbertMatrixDSym(3);
01336   H.SetTol(1.0e-20);
01337   if (gVerbose) {
01338     cout << "\n    3x3 Hilbert matrix: exact determinant 1/2160 ";
01339     cout << "\n                              computed    1/"<< 1/H.Determinant();
01340   }
01341 
01342   H.ResizeTo(4,4);
01343   H = THilbertMatrixDSym(4);
01344   H.SetTol(1.0e-20);
01345   if (gVerbose) {
01346     cout << "\n    4x4 Hilbert matrix: exact determinant 1/6048000 ";
01347     cout << "\n                              computed    1/"<< 1/H.Determinant();
01348   }
01349 
01350   H.ResizeTo(5,5);
01351   H = THilbertMatrixDSym(5);
01352   H.SetTol(1.0e-20);
01353   if (gVerbose) {
01354     cout << "\n    5x5 Hilbert matrix: exact determinant 3.749295e-12";
01355     cout << "\n                              computed    "<< H.Determinant();
01356   }
01357 
01358   if (gVerbose) {
01359     TDecompQRH qrh(H);
01360     Double_t d1,d2;
01361     qrh.Det(d1,d2);
01362     cout  << "\n qrh det = " << d1*TMath::Power(2.0,d2) <<endl;
01363   }
01364 
01365   if (gVerbose) {
01366     TDecompChol chol(H);
01367     Double_t d1,d2;
01368     chol.Det(d1,d2);
01369     cout  << "\n chol det = " << d1*TMath::Power(2.0,d2) <<endl;
01370   }
01371 
01372   if (gVerbose) {
01373     TDecompSVD svd(H);
01374     Double_t d1,d2;
01375     svd.Det(d1,d2);
01376     cout  << "\n svd det = " << d1*TMath::Power(2.0,d2) <<endl;
01377   }
01378 
01379   H.ResizeTo(7,7);
01380   H = THilbertMatrixDSym(7);
01381   H.SetTol(1.0e-20);
01382   if (gVerbose) {
01383     cout << "\n    7x7 Hilbert matrix: exact determinant 4.8358e-25";
01384     cout << "\n                              computed    "<< H.Determinant();
01385   }
01386 
01387   H.ResizeTo(9,9);
01388   H = THilbertMatrixDSym(9);
01389   H.SetTol(1.0e-20);
01390   if (gVerbose) {
01391     cout << "\n    9x9 Hilbert matrix: exact determinant 9.72023e-43";
01392     cout << "\n                              computed    "<< H.Determinant();
01393   }
01394 
01395   H.ResizeTo(10,10);
01396   H = THilbertMatrixDSym(10);
01397   H.SetTol(1.0e-20);
01398   if (gVerbose) {
01399     cout << "\n    10x10 Hilbert matrix: exact determinant 2.16418e-53";
01400     cout << "\n                              computed    "<< H.Determinant();
01401   }
01402 
01403   if (gVerbose)
01404   cout << "\nDone\n" << endl;
01405 
01406   StatusPrint(9,"Matrix Determinant",ok);
01407 }
01408 
01409 //
01410 //------------------------------------------------------------------------
01411 //               Verify matrix multiplications
01412 //
01413 void mstress_mm_multiplications()
01414 {
01415   Bool_t ok = kTRUE;
01416 
01417   Int_t iloop = 0;
01418   Int_t nr    = 0;
01419   while (iloop <= gNrLoop) {
01420     const Int_t msize = gSizeA[iloop];
01421     const Double_t epsilon = EPSILON*msize/100;
01422 
01423     const Int_t verbose = (gVerbose && nr==0 && iloop==gNrLoop);
01424 
01425     Int_t i,j;
01426     if (msize <= 5) {
01427        iloop++;
01428        continue;  // some references to m(3,..)
01429     }
01430 
01431     if (verbose)
01432       cout << "\n---> Verify matrix multiplications "
01433               "for matrices of the characteristic size " << msize << endl;
01434 
01435     {
01436       if (verbose)
01437         cout << "\nTest inline multiplications of the UnitMatrix" << endl;
01438       TMatrixD m = THilbertMatrixD(-1,msize,-1,msize);
01439       TMatrixD u(TMatrixD::kUnit,m);
01440       m(3,1) = TMath::Pi();
01441       u *= m;
01442       ok &= VerifyMatrixIdentity(u,m,verbose,epsilon);
01443     }
01444 
01445     if (ok)
01446     {
01447       if (verbose)
01448         cout << "Test inline multiplications by a DiagMat" << endl;
01449       TMatrixD m = THilbertMatrixD(msize+3,msize);
01450       m(1,3) = TMath::Pi();
01451       TVectorD v(msize);
01452       for (i = v.GetLwb(); i <= v.GetUpb(); i++)
01453         v(i) = 1+i;
01454       TMatrixD diag(msize,msize);
01455       TMatrixDDiag d(diag);
01456       d = v;
01457       TMatrixD eth = m;
01458       for (i = eth.GetRowLwb(); i <= eth.GetRowUpb(); i++)
01459         for (j = eth.GetColLwb(); j <= eth.GetColUpb(); j++)
01460           eth(i,j) *= v(j);
01461       m *= diag;
01462       ok &= VerifyMatrixIdentity(m,eth,verbose,epsilon);
01463     }
01464 
01465     if (ok)
01466     {
01467       if (verbose)
01468         cout << "Test XPP = X where P is a permutation matrix" << endl;
01469       TMatrixD m = THilbertMatrixD(msize-1,msize);
01470       m(2,3) = TMath::Pi();
01471       TMatrixD eth = m;
01472       TMatrixD p(msize,msize);
01473       for (i = p.GetRowLwb(); i <= p.GetRowUpb(); i++)
01474         p(p.GetRowUpb()+p.GetRowLwb()-i,i) = 1;
01475       m *= p;
01476       m *= p;
01477       ok &= VerifyMatrixIdentity(m,eth,verbose,epsilon);
01478     }
01479 
01480     if (ok)
01481     {
01482       if (verbose)
01483         cout << "Test general matrix multiplication through inline mult" << endl;
01484       TMatrixD m = THilbertMatrixD(msize-2,msize);
01485       m(3,3) = TMath::Pi();
01486       TMatrixD mt(TMatrixD::kTransposed,m);
01487       TMatrixD p = THilbertMatrixD(msize,msize);
01488       TMatrixDDiag(p) += 1;
01489       TMatrixD mp(m,TMatrixD::kMult,p);
01490       TMatrixD m1 = m;
01491       m *= p;
01492       ok &= VerifyMatrixIdentity(m,mp,verbose,epsilon);
01493       TMatrixD mp1(mt,TMatrixD::kTransposeMult,p);
01494       VerifyMatrixIdentity(m,mp1,verbose,epsilon);
01495       ok &= ( !(m1 == m) );
01496       TMatrixD mp2(TMatrixD::kZero,m1);
01497       ok &= ( mp2 == 0 );
01498       mp2.Mult(m1,p);
01499       ok &= VerifyMatrixIdentity(m,mp2,verbose,epsilon);
01500 
01501       if (verbose)
01502         cout << "Test XP=X*P  vs XP=X;XP*=P" << endl;
01503       TMatrixD mp3 = m1*p;
01504       ok &= VerifyMatrixIdentity(m,mp3,verbose,epsilon);
01505     }
01506 
01507     if (ok)
01508     {
01509       if (verbose)
01510         cout << "Check n * m  == n * m_sym; m_sym * n == m * n; m_sym * m_sym == m * m" <<endl;
01511 
01512       const TMatrixD     n     = THilbertMatrixD(0,msize-1,0,msize-1);
01513       const TMatrixD     m     = n;
01514       const TMatrixDSym  m_sym = THilbertMatrixDSym(0,msize-1);
01515 
01516       const TMatrixD nm1 = n * m_sym;
01517       const TMatrixD nm2 = n * m;
01518       const TMatrixD mn1 = m_sym * n;
01519       const TMatrixD mn2 = m * n;
01520       const TMatrixD mm1 = m_sym * m_sym;
01521       const TMatrixD mm2 = m * m;
01522 
01523       ok &= VerifyMatrixIdentity(nm1,nm2,verbose,epsilon);
01524       ok &= VerifyMatrixIdentity(mn1,mn2,verbose,epsilon);
01525       ok &= VerifyMatrixIdentity(mm1,mm2,verbose,epsilon);
01526     }
01527 
01528 #ifndef __CINT__
01529     if (nr >= Int_t(1.0e+5/msize/msize)) {
01530 #else
01531     if (nr >= Int_t(1.0e+3/msize/msize)) {
01532 #endif
01533       nr = 0;
01534       iloop++;
01535     } else
01536       nr++;
01537 
01538     if (!ok) {
01539       if (gVerbose)
01540         cout << "General Matrix Multiplications failed for size " << msize << endl;
01541       break;
01542     }
01543   }
01544 
01545   if (ok)
01546   {
01547     if (gVerbose)
01548       cout << "Check to see UU' = U'U = E when U is the Haar matrix" << endl;
01549     const Int_t order = 5;
01550     const Int_t no_sub_cols = (1<<order)-5;
01551     TMatrixD haar_sub = THaarMatrixD(5,no_sub_cols);
01552     TMatrixD haar_sub_t(TMatrixD::kTransposed,haar_sub);
01553     TMatrixD hsths(haar_sub_t,TMatrixD::kMult,haar_sub);
01554     TMatrixD hsths1(TMatrixD::kZero,hsths); hsths1.Mult(haar_sub_t,haar_sub);
01555     TMatrixD hsths_eth(TMatrixD::kUnit,hsths);
01556     ok &= ( hsths.GetNrows() == no_sub_cols && hsths.GetNcols() == no_sub_cols );
01557     ok &= VerifyMatrixIdentity(hsths,hsths_eth,gVerbose,EPSILON);
01558     ok &= VerifyMatrixIdentity(hsths1,hsths_eth,gVerbose,EPSILON);
01559     TMatrixD haar = THaarMatrixD(order);
01560     TMatrixD unit(TMatrixD::kUnit,haar);
01561     TMatrixD haar_t(TMatrixD::kTransposed,haar);
01562     TMatrixD hth(haar,TMatrixD::kTransposeMult,haar);
01563     TMatrixD hht(haar,TMatrixD::kMult,haar_t);
01564     TMatrixD hht1 = haar; hht1 *= haar_t;
01565     TMatrixD hht2(TMatrixD::kZero,haar); hht2.Mult(haar,haar_t);
01566     ok &= VerifyMatrixIdentity(unit,hth,gVerbose,EPSILON);
01567     ok &= VerifyMatrixIdentity(unit,hht,gVerbose,EPSILON);
01568     ok &= VerifyMatrixIdentity(unit,hht1,gVerbose,EPSILON);
01569     ok &= VerifyMatrixIdentity(unit,hht2,gVerbose,EPSILON);
01570   }
01571 
01572   if (gVerbose)
01573     cout << "\nDone\n" << endl;
01574 
01575   StatusPrint(10,"General Matrix Multiplications",ok);
01576 }
01577 
01578 //
01579 //------------------------------------------------------------------------
01580 //               Verify symmetric matrix multiplications
01581 //
01582 void mstress_sym_mm_multiplications(Int_t msize)
01583 {
01584   if (gVerbose)
01585     cout << "\n---> Verify symmetric matrix multiplications "
01586             "for matrices of the characteristic size " << msize << endl;
01587 
01588   Int_t i,j;
01589   Bool_t ok = kTRUE;
01590 
01591   const Double_t epsilon = EPSILON*msize/100;
01592 
01593   {
01594     if (gVerbose)
01595       cout << "\nTest inline multiplications of the UnitMatrix" << endl;
01596     TMatrixD m = THilbertMatrixD(-1,msize,-1,msize);
01597     TMatrixDSym m_sym(-1,msize,m.GetMatrixArray());
01598     TMatrixDSym u(TMatrixDSym::kUnit,m_sym);
01599     TMatrixD u2 = u * m_sym;
01600     ok &= VerifyMatrixIdentity(u2,m_sym,gVerbose,epsilon);
01601   }
01602 
01603   if (ok)
01604   {
01605     if (gVerbose)
01606       cout << "\nTest symmetric multiplications" << endl;
01607     {
01608       if (gVerbose)
01609         cout << "\n  Test m * m_sym == m_sym * m == m_sym * m_sym  multiplications" << endl;
01610       TMatrixD m = THilbertMatrixD(-1,msize,-1,msize);
01611       TMatrixDSym m_sym(-1,msize,m.GetMatrixArray());
01612       TMatrixD mm      = m * m;
01613       TMatrixD mm_sym1 = m_sym * m_sym;
01614       TMatrixD mm_sym2 = m     * m_sym;
01615       TMatrixD mm_sym3 = m_sym * m;
01616       ok &= VerifyMatrixIdentity(mm,mm_sym1,gVerbose,epsilon);
01617       ok &= VerifyMatrixIdentity(mm,mm_sym2,gVerbose,epsilon);
01618       ok &= VerifyMatrixIdentity(mm,mm_sym3,gVerbose,epsilon);
01619     }
01620 
01621     {
01622       if (gVerbose)
01623         cout << "\n  Test m^T * m_sym == m_sym^T * m == m_sym^T * m_sym  multiplications" << endl;
01624       TMatrixD m = THilbertMatrixD(-1,msize,-1,msize);
01625       TMatrixDSym m_sym(-1,msize,m.GetMatrixArray());
01626       TMatrixD mtm      = TMatrixD(m    ,TMatrixD::kTransposeMult,m);
01627       TMatrixD mtm_sym1 = TMatrixD(m_sym,TMatrixD::kTransposeMult,m_sym);
01628       TMatrixD mtm_sym2 = TMatrixD(m    ,TMatrixD::kTransposeMult,m_sym);
01629       TMatrixD mtm_sym3 = TMatrixD(m_sym,TMatrixD::kTransposeMult,m);
01630       ok &= VerifyMatrixIdentity(mtm,mtm_sym1,gVerbose,epsilon);
01631       ok &= VerifyMatrixIdentity(mtm,mtm_sym2,gVerbose,epsilon);
01632       ok &= VerifyMatrixIdentity(mtm,mtm_sym3,gVerbose,epsilon);
01633     }
01634 
01635     {
01636       if (gVerbose)
01637         cout << "\n  Test m * m_sym^T == m_sym * m^T == m_sym * m_sym^T  multiplications" << endl;
01638       TMatrixD m = THilbertMatrixD(-1,msize,-1,msize);
01639       TMatrixDSym m_sym(-1,msize,m.GetMatrixArray());
01640       TMatrixD mmt      = TMatrixD(m    ,TMatrixD::kMultTranspose,m);
01641       TMatrixD mmt_sym1 = TMatrixD(m_sym,TMatrixD::kMultTranspose,m_sym);
01642       TMatrixD mmt_sym2 = TMatrixD(m    ,TMatrixD::kMultTranspose,m_sym);
01643       TMatrixD mmt_sym3 = TMatrixD(m_sym,TMatrixD::kMultTranspose,m);
01644       ok &= VerifyMatrixIdentity(mmt,mmt_sym1,gVerbose,epsilon);
01645       ok &= VerifyMatrixIdentity(mmt,mmt_sym2,gVerbose,epsilon);
01646       ok &= VerifyMatrixIdentity(mmt,mmt_sym3,gVerbose,epsilon);
01647     }
01648 
01649     {
01650       if (gVerbose)
01651         cout << "\n  Test n * m_sym == n * m multiplications" << endl;
01652       TMatrixD n = THilbertMatrixD(-1,msize,-1,msize);
01653       TMatrixD m = n;
01654       n(1,3) = TMath::Pi();
01655       n(3,1) = TMath::Pi();
01656       TMatrixDSym m_sym(-1,msize,m.GetMatrixArray());
01657       TMatrixD nm1 = n * m_sym;
01658       TMatrixD nm2 = n * m;
01659       ok &= VerifyMatrixIdentity(nm1,nm2,gVerbose,epsilon);
01660     }
01661   }
01662 
01663   if (ok)
01664   {
01665     if (gVerbose)
01666       cout << "Test inline multiplications by a DiagMatrix" << endl;
01667     TMatrixDSym ms = THilbertMatrixDSym(msize);
01668     ms(1,3) = TMath::Pi();
01669     ms(3,1) = TMath::Pi();
01670     TVectorD v(msize);
01671     for (i = v.GetLwb(); i <= v.GetUpb(); i++)
01672       v(i) = 1+i;
01673     TMatrixDSym diag(msize);
01674     TMatrixDDiag d(diag); d = v;
01675     TMatrixDSym eth = ms;
01676     for (i = eth.GetRowLwb(); i <= eth.GetRowUpb(); i++)
01677       for (j = eth.GetColLwb(); j <= eth.GetColUpb(); j++)
01678         eth(i,j) *= v(j);
01679     TMatrixD m2 = ms * diag;
01680     ok &= VerifyMatrixIdentity(m2,eth,gVerbose,epsilon);
01681   }
01682 
01683   if (ok)
01684   {
01685     if (gVerbose)
01686       cout << "Test XPP = X where P is a permutation matrix" << endl;
01687     TMatrixDSym ms = THilbertMatrixDSym(msize);
01688     ms(2,3) = TMath::Pi();
01689     ms(3,2) = TMath::Pi();
01690     TMatrixDSym eth = ms;
01691     TMatrixDSym p(msize);
01692     for (i = p.GetRowLwb(); i <= p.GetRowUpb(); i++)
01693       p(p.GetRowUpb()+p.GetRowLwb()-i,i) = 1;
01694     TMatrixD m2 = ms * p;
01695     m2 *= p;
01696     ok &= VerifyMatrixIdentity(m2,eth,gVerbose,epsilon);
01697   }
01698 
01699   if (ok)
01700   {
01701     if (gVerbose)
01702       cout << "Test general matrix multiplication through inline mult" << endl;
01703     TMatrixDSym ms = THilbertMatrixDSym(msize);
01704     ms(2,3) = TMath::Pi();
01705     ms(3,2) = TMath::Pi();
01706     TMatrixDSym mt(TMatrixDSym::kTransposed,ms);
01707     TMatrixDSym p = THilbertMatrixDSym(msize);
01708     TMatrixDDiag(p) += 1;
01709     TMatrixD mp(ms,TMatrixD::kMult,p);
01710     TMatrixDSym m1 = ms;
01711     TMatrixD m3(ms,TMatrixD::kMult,p);
01712     memcpy(ms.GetMatrixArray(),m3.GetMatrixArray(),msize*msize*sizeof(Double_t));
01713     ok &= VerifyMatrixIdentity(ms,mp,gVerbose,epsilon);
01714     TMatrixD mp1(mt,TMatrixD::kTransposeMult,p);
01715     ok &= VerifyMatrixIdentity(ms,mp1,gVerbose,epsilon);
01716     ok &= ( !(m1 == ms) ) ? kTRUE : kFALSE;
01717     TMatrixDSym mp2(TMatrixDSym::kZero,ms);
01718     ok &= ( mp2 == 0 ) ? kTRUE : kFALSE;
01719 
01720     if (gVerbose)
01721       cout << "Test XP=X*P  vs XP=X;XP*=P" << endl;
01722     TMatrixD mp3 = m1*p;
01723     ok &= VerifyMatrixIdentity(ms,mp3,gVerbose,epsilon);
01724   }
01725 
01726   if (ok)
01727   {
01728     if (gVerbose)
01729       cout << "Check to see UU' = U'U = E when U is the Haar matrix" << endl;
01730     {
01731       const Int_t order = 5;
01732       const Int_t no_sub_cols = (1<<order)-5;
01733       TMatrixD haarb = THaarMatrixD(5,no_sub_cols);
01734       TMatrixD haarb_t(TMatrixD::kTransposed,haarb);
01735       TMatrixD hth(haarb_t,TMatrixD::kMult,haarb);
01736       TMatrixDSym  hth1(TMatrixDSym::kAtA,haarb);
01737       ok &= VerifyMatrixIdentity(hth,hth1,gVerbose,epsilon);
01738     }
01739 
01740     {
01741       TMatrixD haar = THaarMatrixD(5);
01742       TMatrixD unit(TMatrixD::kUnit,haar);
01743       TMatrixD haar_t(TMatrixD::kTransposed,haar);
01744       TMatrixDSym hths(TMatrixDSym::kAtA,haar);
01745       TMatrixD hht(haar,TMatrixD::kMult,haar_t);
01746       TMatrixD hht1 = haar; hht1 *= haar_t;
01747       ok &= VerifyMatrixIdentity(unit,hths,gVerbose,epsilon);
01748       ok &= VerifyMatrixIdentity(unit,hht,gVerbose,epsilon);
01749       ok &= VerifyMatrixIdentity(unit,hht1,gVerbose,epsilon);
01750     }
01751   }
01752 
01753   if (ok)
01754   {
01755     if (gVerbose)
01756       cout << "Check to see A.Similarity(Haar) = Haar * A * Haar^T" <<
01757               " and A.SimilarityT(Haar) = Haar^T * A * Haar" << endl;
01758     {
01759       TMatrixD    h  = THaarMatrixD(5);
01760       TMatrixDSym ms = THilbertMatrixDSym(1<<5);
01761       TMatrixD    hmht = h*TMatrixD(ms,TMatrixD::kMultTranspose,h);
01762       ok &= VerifyMatrixIdentity(ms.Similarity(h),hmht,gVerbose,epsilon);
01763       TMatrixD    htmh = TMatrixD(h,TMatrixD::kTransposeMult,ms)*h;
01764       ok &= VerifyMatrixIdentity(ms.SimilarityT(h),htmh,gVerbose,epsilon);
01765     }
01766     if (gVerbose)
01767       cout << "Check to see A.Similarity(B_sym) = A.Similarity(B)" << endl;
01768     {
01769       TMatrixDSym nsym = THilbertMatrixDSym(5);
01770       TMatrixD    n    = THilbertMatrixD(5,5);
01771       TMatrixDSym ms   = THilbertMatrixDSym(5);
01772       ok &= VerifyMatrixIdentity(ms.Similarity(nsym),ms.Similarity(n),gVerbose,epsilon);
01773     }
01774   }
01775 
01776   if (gVerbose)
01777     cout << "\nDone\n" << endl;
01778 
01779   StatusPrint(11,"Symmetric Matrix Multiplications",ok);
01780 }
01781 
01782 //
01783 //------------------------------------------------------------------------
01784 //               Verify vector-matrix multiplications
01785 //
01786 void mstress_vm_multiplications()
01787 {
01788   Bool_t ok = kTRUE;
01789 
01790   Int_t iloop = gNrLoop;
01791   Int_t nr    = 0;
01792   while (iloop >= 0) {
01793     const Int_t msize = gSizeA[iloop];
01794 
01795     const Double_t epsilon = EPSILON*msize;
01796 
01797     const Int_t verbose = (gVerbose && nr==0 && iloop==gNrLoop);
01798 
01799     if (verbose)
01800       cout << "\n---> Verify vector-matrix multiplications "
01801              "for matrices of the characteristic size " << msize << endl;
01802 
01803     {
01804       if (verbose)
01805         cout << "\nCheck shrinking a vector by multiplying by a non-sq unit matrix" << endl;
01806       TVectorD vb(-2,msize);
01807       for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
01808         vb(i) = TMath::Pi()-i;
01809       ok &= ( vb != 0 ) ? kTRUE : kFALSE;
01810       TMatrixD mc(1,msize-2,-2,msize);       // contracting matrix
01811       mc.UnitMatrix();
01812       TVectorD v1 = vb;
01813       TVectorD v2 = vb;
01814       v1 *= mc;
01815       v2.ResizeTo(1,msize-2);
01816       ok &= VerifyVectorIdentity(v1,v2,verbose,epsilon);
01817     }
01818 
01819     if (ok)
01820     {
01821       if (verbose)
01822         cout << "Check expanding a vector by multiplying by a non-sq unit matrix" << endl;
01823       TVectorD vb(msize);
01824       for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
01825         vb(i) = TMath::Pi()+i;
01826       ok &= ( vb != 0 ) ? kTRUE : kFALSE;
01827       TMatrixD me(2,msize+5,0,msize-1);    // expanding matrix
01828       me.UnitMatrix();
01829       TVectorD v1 = vb;
01830       TVectorD v2 = vb;
01831       v1 *= me;
01832       v2.ResizeTo(v1);
01833       ok &= VerifyVectorIdentity(v1,v2,verbose,epsilon);
01834     }
01835 
01836     if (ok)
01837     {
01838       if (verbose)
01839         cout << "Check general matrix-vector multiplication" << endl;
01840       TVectorD vb(msize);
01841       for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
01842         vb(i) = TMath::Pi()+i;
01843       TMatrixD vm(msize,1);
01844       TMatrixDColumn(vm,0) = vb;
01845       TMatrixD m = THilbertMatrixD(0,msize,0,msize-1);
01846       vb *= m;
01847       ok &= ( vb.GetLwb() == 0 ) ? kTRUE : kFALSE;
01848       TMatrixD mvm(m,TMatrixD::kMult,vm);
01849       TMatrixD mvb(msize+1,1);
01850       TMatrixDColumn(mvb,0) = vb;
01851       ok &= VerifyMatrixIdentity(mvb,mvm,verbose,epsilon);
01852     }
01853 
01854     if (ok)
01855     {
01856       if (verbose)
01857         cout << "Check symmetric matrix-vector multiplication" << endl;
01858       TVectorD vb(msize);
01859       for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
01860         vb(i) = TMath::Pi()+i;
01861       TMatrixD vm(msize,1);
01862       TMatrixDColumn(vm,0) = vb;
01863       TMatrixDSym ms = THilbertMatrixDSym(0,msize-1);
01864       vb *= ms;
01865       ok &= ( vb.GetLwb() == 0 ) ? kTRUE : kFALSE;
01866       TMatrixD mvm(ms,TMatrixD::kMult,vm);
01867       TMatrixD mvb(msize,1);
01868       TMatrixDColumn(mvb,0) = vb;
01869       ok &= VerifyMatrixIdentity(mvb,mvm,verbose,epsilon);
01870     }
01871 
01872 #ifndef __CINT__
01873     if (nr >= Int_t(1.0e+5/msize/msize)) {
01874 #else
01875     if (nr >= Int_t(1.0e+3/msize/msize)) {
01876 #endif
01877       nr = 0;
01878       iloop--;
01879     } else
01880       nr++;
01881 
01882     if (!ok) {
01883       if (gVerbose)
01884         cout << "Vector Matrix Multiplications failed for size " << msize << endl;
01885       break;
01886     }
01887   }
01888 
01889   if (gVerbose)
01890     cout << "\nDone\n" << endl;
01891 
01892   StatusPrint(12,"Matrix Vector Multiplications",ok);
01893 }
01894 
01895 //
01896 //------------------------------------------------------------------------
01897 //               Verify matrix inversion
01898 //
01899 void mstress_inversion()
01900 {
01901   Bool_t ok = kTRUE;
01902 
01903   Int_t iloop = gNrLoop;
01904   Int_t nr    = 0;
01905   while (iloop >= 0) {
01906     const Int_t msize = gSizeA[iloop];
01907 
01908     const Double_t epsilon = EPSILON*msize/10;
01909 
01910     const Int_t verbose = (gVerbose && nr==0 && iloop==gNrLoop);
01911 
01912     if (verbose)
01913       cout << "\n---> Verify matrix inversion for square matrices of size " << msize << endl;
01914     {
01915       if (verbose)
01916         cout << "\nTest inversion of a diagonal matrix" << endl;
01917       TMatrixD m(-1,msize,-1,msize);
01918       TMatrixD mi(TMatrixD::kZero,m);
01919       for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
01920         m(i,i)=i-m.GetRowLwb()+1;
01921         mi(i,i) = 1/m(i,i);
01922       }
01923       TMatrixD mi1(TMatrixD::kInverted,m);
01924       m.Invert();
01925       ok &= VerifyMatrixIdentity(m,mi,verbose,epsilon);
01926       ok &= VerifyMatrixIdentity(mi1,mi,verbose,epsilon);
01927     }
01928 
01929     if (ok)
01930     {
01931       if (verbose)
01932         cout << "Test inversion of an orthonormal (Haar) matrix" << endl;
01933       const Int_t order = Int_t(TMath::Log(msize)/TMath::Log(2));
01934       TMatrixD mr = THaarMatrixD(order);
01935       TMatrixD morig = mr;
01936       TMatrixD mt(TMatrixD::kTransposed,mr);
01937       Double_t det = -1;         // init to a wrong val to see if it's changed
01938       mr.Invert(&det);
01939       ok &= VerifyMatrixIdentity(mr,mt,verbose,epsilon);
01940       ok &= ( TMath::Abs(det-1) <= msize*epsilon ) ? kTRUE : kFALSE;
01941       if (verbose) {
01942         cout << "det = " << det << " deviation= " << TMath::Abs(det-1);
01943         cout << ( (TMath::Abs(det-1) < msize*epsilon) ? " OK" : " too large") <<endl;
01944       }
01945       TMatrixD mti(TMatrixD::kInverted,mt);
01946       ok &= VerifyMatrixIdentity(mti,morig,verbose,msize*epsilon);
01947     }
01948 
01949     if (ok)
01950     {
01951       if (verbose)
01952         cout << "Test inversion of a good matrix with diagonal dominance" << endl;
01953       TMatrixD mh = THilbertMatrixD(msize,msize);
01954       TMatrixDDiag(mh) += 1;
01955       TMatrixD morig = mh;
01956       Double_t det_inv = 0;
01957       const Double_t det_comp = mh.Determinant();
01958       mh.Invert(&det_inv);
01959       if (verbose) {
01960         cout << "\tcomputed determinant             " << det_comp << endl;
01961         cout << "\tdeterminant returned by Invert() " << det_inv << endl;
01962       }
01963 
01964       if (verbose)
01965         cout << "\tcheck to see M^(-1) * M is E" << endl;
01966       TMatrixD mim(mh,TMatrixD::kMult,morig);
01967       TMatrixD unit(TMatrixD::kUnit,mh);
01968       ok &= VerifyMatrixIdentity(mim,unit,verbose,epsilon);
01969 
01970       if (verbose)
01971         cout << "Test inversion through the matrix decompositions" << endl;
01972 
01973       TMatrixDSym ms = THilbertMatrixDSym(msize);
01974       TMatrixDDiag(ms) += 1;
01975       if (verbose)
01976         cout << "Test inversion through SVD" << endl;
01977       TMatrixD inv_svd (msize,msize); TDecompSVD  svd (ms); svd.Invert(inv_svd);
01978       ok &= VerifyMatrixIdentity(inv_svd,mh,verbose,epsilon);
01979       if (verbose)
01980         cout << "Test inversion through LU" << endl;
01981       TMatrixD inv_lu  (msize,msize); TDecompLU   lu  (ms); lu.Invert(inv_lu);
01982       ok &= VerifyMatrixIdentity(inv_lu,mh,verbose,epsilon);
01983       if (verbose)
01984         cout << "Test inversion through Cholesky" << endl;
01985       TMatrixDSym inv_chol(msize); TDecompChol chol(ms); chol.Invert(inv_chol);
01986       ok &= VerifyMatrixIdentity(inv_chol,mh,verbose,epsilon);
01987       if (verbose)
01988         cout << "Test inversion through QRH" << endl;
01989       TMatrixD inv_qrh (msize,msize); TDecompQRH  qrh (ms); qrh.Invert(inv_qrh);
01990       ok &= VerifyMatrixIdentity(inv_qrh,mh,verbose,epsilon);
01991       if (verbose)
01992         cout << "Test inversion through Bunch-Kaufman" << endl;
01993       TMatrixDSym inv_bk(msize); TDecompBK bk(ms); chol.Invert(inv_bk);
01994       ok &= VerifyMatrixIdentity(inv_bk,mh,verbose,epsilon);
01995 
01996       if (verbose)
01997         cout << "\tcheck to see M * M^(-1) is E" << endl;
01998       TMatrixD mmi = morig; mmi *= mh;
01999       ok &= VerifyMatrixIdentity(mmi,unit,verbose,epsilon);
02000     }
02001 
02002 #ifndef __CINT__
02003     if (nr >= Int_t(1.0e+5/msize/msize)) {
02004 #else
02005     if (nr >= Int_t(1.0e+3/msize/msize)) {
02006 #endif
02007       nr = 0;
02008       iloop--;
02009     } else
02010       nr++;
02011 
02012     if (!ok) {
02013       if (gVerbose)
02014         cout << "Matrix Inversion failed for size " << msize << endl;
02015       break;
02016     }
02017   }
02018 
02019   {
02020     if (gVerbose) {
02021       cout << "Check to see that Invert() and InvertFast() give identical results" <<endl;
02022       cout << " for size < (7x7)" <<endl;
02023     }
02024     Int_t size;
02025     for (size = 2; size < 7; size++) {
02026       TMatrixD m1 = THilbertMatrixD(size,size);
02027       m1(0,1) = TMath::Pi();
02028       TMatrixDDiag(m1) += 1;
02029       TMatrixD m2 = m1;
02030       Double_t det1 = 0.0;
02031       Double_t det2 = 0.0;
02032       m1.Invert(&det1);
02033       m2.InvertFast(&det2);
02034       ok &= VerifyMatrixIdentity(m1,m2,gVerbose,EPSILON);
02035       ok &= (TMath::Abs(det1-det2) < EPSILON);
02036       if (gVerbose) {
02037         cout << "det(Invert)= " << det1 << "  det(InvertFast)= " << det2 <<endl;
02038         cout << " deviation= " << TMath::Abs(det1-det2);
02039         cout << ( (TMath::Abs(det1-det2) <  EPSILON) ? " OK" : " too large") <<endl;
02040       }
02041     }
02042     for (size = 2; size < 7; size++) {
02043       TMatrixDSym ms1 = THilbertMatrixDSym(size);
02044       TMatrixDDiag(ms1) += 1;
02045       TMatrixDSym ms2 = ms1;
02046       Double_t det1 = 0.0;
02047       Double_t det2 = 0.0;
02048       ms1.Invert(&det1);
02049       ms2.InvertFast(&det2);
02050       ok &= VerifyMatrixIdentity(ms1,ms2,gVerbose,EPSILON);
02051       ok &= (TMath::Abs(det1-det2) < EPSILON);
02052       if (gVerbose) {
02053         cout << "det(Invert)= " << det1 << "  det(InvertFast)= " << det2 <<endl;
02054         cout << " deviation= " << TMath::Abs(det1-det2);
02055         cout << ( (TMath::Abs(det1-det2) <  EPSILON) ? " OK" : " too large") <<endl;
02056       }
02057     }
02058   }
02059 
02060   if (gVerbose)
02061     cout << "\nDone\n" << endl;
02062 
02063   StatusPrint(13,"Matrix Inversion",ok);
02064 }
02065 
02066 //
02067 //------------------------------------------------------------------------
02068 //           Test matrix I/O
02069 //
02070 void mstress_matrix_io()
02071 {
02072   if (gVerbose)
02073     cout << "\n---> Test matrix I/O" << endl;
02074 
02075   Bool_t ok = kTRUE;
02076   const Double_t pattern = TMath::Pi();
02077 
02078   TFile *f = new TFile("vmatrix.root", "RECREATE");
02079 
02080   Char_t name[80];
02081   Int_t iloop = gNrLoop;
02082   while (iloop >= 0) {
02083     const Int_t msize = gSizeA[iloop];
02084 
02085     const Int_t verbose = (gVerbose && iloop==gNrLoop);
02086 
02087     TMatrixD m(msize,msize);
02088     m = pattern;
02089 
02090     Double_t *pattern_array = new Double_t[msize*msize];
02091     for (Int_t i = 0; i < msize*msize; i++)
02092       pattern_array[i] = pattern;
02093     TMatrixD ma;
02094     ma.Use(msize,msize,pattern_array);
02095 
02096     TMatrixDSym ms(msize);
02097     ms = pattern;
02098 
02099     if (verbose)
02100       cout << "\nWrite matrix m to database" << endl;
02101     sprintf(name,"m_%d",msize);
02102     m.Write(name);
02103 
02104     if (verbose)
02105       cout << "\nWrite matrix ma which adopts to database" << endl;
02106     sprintf(name,"ma_%d",msize);
02107     ma.Write(name);
02108 
02109     if (verbose)
02110       cout << "\nWrite symmetric matrix ms to database" << endl;
02111     sprintf(name,"ms_%d",msize);
02112     ms.Write(name);
02113 
02114     delete [] pattern_array;
02115 
02116     iloop--;
02117   }
02118 
02119   if (gVerbose)
02120     cout << "\nClose database" << endl;
02121   delete f;
02122 
02123   if (gVerbose)
02124     cout << "\nOpen database in read-only mode and read matrix" << endl;
02125   TFile *f1 = new TFile("vmatrix.root");
02126 
02127   iloop = gNrLoop;
02128   while (iloop >= 0) {
02129     const Int_t msize = gSizeA[iloop];
02130 
02131     const Int_t verbose = (gVerbose && iloop==gNrLoop);
02132 
02133     TMatrixD m(msize,msize);
02134     m = pattern;
02135     sprintf(name,"m_%d",msize);
02136     TMatrixD *mr  = (TMatrixD*) f1->Get(name);
02137     sprintf(name,"ma_%d",msize);
02138     TMatrixD *mar = (TMatrixD*) f1->Get(name);
02139     sprintf(name,"ms_%d",msize);
02140     TMatrixDSym *msr = (TMatrixDSym*) f1->Get(name);
02141 
02142     if (verbose)
02143       cout << "\nRead matrix should be same as original" << endl;
02144     ok &= ((*mr)  == m) ? kTRUE : kFALSE;
02145     ok &= ((*mar) == m) ? kTRUE : kFALSE;
02146     ok &= ((*msr) == m) ? kTRUE : kFALSE;
02147 
02148     iloop--;
02149   }
02150 
02151   delete f1;
02152 
02153   if (gVerbose)
02154     cout << "\nDone\n" << endl;
02155 
02156   StatusPrint(14,"Matrix Persistence",ok);
02157 }
02158 
02159 //------------------------------------------------------------------------
02160 //          Test allocation functions and compatibility check
02161 //
02162 void spstress_allocation(Int_t msize)
02163 {
02164   if (gVerbose)
02165     cout << "\n\n---> Test allocation and compatibility check" << endl;
02166 
02167   Int_t i,j;
02168   Bool_t ok = kTRUE;
02169 
02170   TMatrixDSparse m1(0,3,0,msize-1);
02171   {
02172     Int_t nr = 4*msize;
02173     Int_t    *irow = new Int_t[nr];
02174     Int_t    *icol = new Int_t[nr];
02175     Double_t *val  = new Double_t[nr];
02176 
02177     Int_t n = 0;
02178     for (i = m1.GetRowLwb(); i <= m1.GetRowUpb(); i++) {
02179       for (j = m1.GetColLwb(); j <= m1.GetColUpb(); j++) {
02180         irow[n] = i;
02181         icol[n] = j;
02182         val[n] = TMath::Pi()*i+TMath::E()*j;
02183         n++;
02184       }
02185     }
02186     m1.SetMatrixArray(nr,irow,icol,val);
02187     delete [] irow;
02188     delete [] icol;
02189     delete [] val;
02190   }
02191 
02192   TMatrixDSparse m2(0,3,0,msize-1);
02193   TMatrixDSparse m3(1,4,0,msize-1);
02194   TMatrixDSparse m4(m1);
02195 
02196   if (gVerbose) {
02197     cout << "\nStatus information reported for matrix m3:" << endl;
02198     cout << "  Row lower bound ... " << m3.GetRowLwb() << endl;
02199     cout << "  Row upper bound ... " << m3.GetRowUpb() << endl;
02200     cout << "  Col lower bound ... " << m3.GetColLwb() << endl;
02201     cout << "  Col upper bound ... " << m3.GetColUpb() << endl;
02202     cout << "  No. rows ..........." << m3.GetNrows()  << endl;
02203     cout << "  No. cols ..........." << m3.GetNcols()  << endl;
02204     cout << "  No. of elements ...." << m3.GetNoElements() << endl;
02205   }
02206 
02207   if (gVerbose)
02208     cout << "Check matrices 1 & 4 for compatibility" << endl;
02209   ok &= AreCompatible(m1,m4,gVerbose);
02210 
02211   if (gVerbose)
02212     cout << "m2 has to be compatible with m3 after resizing to m3" << endl;
02213   m2.ResizeTo(m3);
02214   ok &= AreCompatible(m2,m3,gVerbose);
02215 
02216   TMatrixD m5_d(m1.GetNrows()+1,m1.GetNcols()+5);
02217   for (i = m1.GetRowLwb(); i <= m1.GetRowUpb(); i++)
02218     for (j = m1.GetColLwb(); j <= m1.GetColUpb(); j++)
02219       m5_d(i,j) = TMath::Pi()*i+TMath::E()*j;
02220   TMatrixDSparse m5(m5_d);
02221 
02222   if (gVerbose)
02223     cout << "m1 has to be compatible with m5 after resizing to m5" << endl;
02224   m1.ResizeTo(m5.GetNrows(),m5.GetNcols());
02225   ok &= AreCompatible(m1,m5,gVerbose);
02226 
02227   if (gVerbose)
02228     cout << "m1 has to be equal to m4 after stretching and shrinking" << endl;
02229   m1.ResizeTo(m4.GetNrows(),m4.GetNcols());
02230   ok &= VerifyMatrixIdentity(m1,m4,gVerbose,EPSILON);
02231   if (gVerbose)
02232     cout << "m5 has to be equal to m1 after shrinking" << endl;
02233   m5.ResizeTo(m1.GetNrows(),m1.GetNcols());
02234   ok &= VerifyMatrixIdentity(m1,m5,gVerbose,msize*EPSILON);
02235 
02236   if (gVerbose)
02237     cout << "\nDone\n" << endl;
02238 
02239   StatusPrint(1,"Allocation, Resizing",ok);
02240 }
02241 
02242 //
02243 //------------------------------------------------------------------------
02244 //          Test Filling of matrix
02245 //
02246 void spstress_matrix_fill(Int_t rsize,Int_t csize)
02247 {
02248   Bool_t ok = kTRUE;
02249 
02250   if (csize < 4) {
02251     Error("spstress_matrix_fill","rsize should be >= 4");
02252     ok = kFALSE;
02253     StatusPrint(2,"Filling, Inserting, Using",ok);
02254     return;
02255   }
02256 
02257   if (csize < 4) {
02258     Error("spstress_matrix_fill","csize should be >= 4");
02259     ok = kFALSE;
02260     StatusPrint(2,"Filling, Inserting, Using",ok);
02261     return;
02262   }
02263 
02264   TMatrixD m_d(-1,rsize-2,1,csize);
02265   for (Int_t i = m_d.GetRowLwb(); i <= m_d.GetRowUpb(); i++)
02266     for (Int_t j = m_d.GetColLwb(); j <= m_d.GetColUpb(); j++)
02267       // Keep column 2 on zero
02268       if (j != 2)
02269         m_d(i,j) = TMath::Pi()*i+TMath::E()*j;
02270   TMatrixDSparse m(m_d);
02271 
02272   {
02273     if (gVerbose)
02274       cout << "Check filling through operator(i,j) without setting sparse index" << endl;
02275     TMatrixDSparse m1(-1,rsize-2,1,csize);
02276 
02277     for (Int_t i = m1.GetRowLwb(); i <= m1.GetRowUpb(); i++)
02278       for (Int_t j = m1.GetColLwb(); j <= m1.GetColUpb(); j++)
02279         if (j != 2)
02280           m1(i,j) = TMath::Pi()*i+TMath::E()*j;
02281     ok &= VerifyMatrixIdentity(m1,m,gVerbose,EPSILON);
02282   }
02283 
02284   {
02285     if (gVerbose)
02286       cout << "Check filling through operator(i,j)" << endl;
02287     TMatrixDSparse m2(-1,rsize-2,1,csize);
02288     m2.SetSparseIndex(m);
02289 
02290     for (Int_t i = m2.GetRowLwb(); i <= m2.GetRowUpb(); i++)
02291       for (Int_t j = m2.GetColLwb(); j <= m2.GetColUpb(); j++)
02292         if (j != 2)
02293           m2(i,j) = TMath::Pi()*i+TMath::E()*j;
02294     ok &= VerifyMatrixIdentity(m2,m,gVerbose,EPSILON);
02295   }
02296 
02297   {
02298     if (gVerbose)
02299       cout << "Check insertion/extraction of sub-matrices" << endl;
02300     {
02301       TMatrixDSparse m_sub1 = m;
02302       m_sub1.ResizeTo(0,rsize-2,2,csize);
02303       TMatrixDSparse m_sub2 = m.GetSub(0,rsize-2,2,csize,"");
02304       ok &= VerifyMatrixIdentity(m_sub1,m_sub2,gVerbose,EPSILON);
02305     }
02306 
02307     {
02308       TMatrixDSparse m3(-1,rsize-2,1,csize);
02309       TMatrixDSparse m_part1 = m.GetSub(-1,rsize-2,1,csize,"");
02310       m3.SetSub(-1,1,m_part1);
02311       ok &= VerifyMatrixIdentity(m,m3,gVerbose,EPSILON);
02312     }
02313 
02314     {
02315       TMatrixDSparse m4(-1,rsize-2,1,csize);
02316       TMatrixDSparse m_part1 = m.GetSub(0,rsize-2,2,csize,"");
02317       TMatrixDSparse m_part2 = m.GetSub(0,rsize-2,1,1,"");
02318       TMatrixDSparse m_part3 = m.GetSub(-1,-1,2,csize,"");
02319       TMatrixDSparse m_part4 = m.GetSub(-1,-1,1,1,"");
02320       m4.SetSub(0,2,m_part1);
02321       m4.SetSub(0,1,m_part2);
02322       m4.SetSub(-1,2,m_part3);
02323       m4.SetSub(-1,1,m_part4);
02324       ok &= VerifyMatrixIdentity(m,m4,gVerbose,EPSILON);
02325     }
02326 
02327     {
02328       // change the insertion order
02329       TMatrixDSparse m5(-1,rsize-2,1,csize);
02330       TMatrixDSparse m_part1 = m.GetSub(0,rsize-2,2,csize,"");
02331       TMatrixDSparse m_part2 = m.GetSub(0,rsize-2,1,1,"");
02332       TMatrixDSparse m_part3 = m.GetSub(-1,-1,2,csize,"");
02333       TMatrixDSparse m_part4 = m.GetSub(-1,-1,1,1,"");
02334       m5.SetSub(-1,1,m_part4);
02335       m5.SetSub(-1,2,m_part3);
02336       m5.SetSub(0,1,m_part2);
02337       m5.SetSub(0,2,m_part1);
02338       ok &= VerifyMatrixIdentity(m,m5,gVerbose,EPSILON);
02339     }
02340 
02341     {
02342       TMatrixDSparse m6(-1,rsize-2,1,csize);
02343       TMatrixDSparse m_part1 = m.GetSub(0,rsize-2,2,csize,"S");
02344       TMatrixDSparse m_part2 = m.GetSub(0,rsize-2,1,1,"S");
02345       TMatrixDSparse m_part3 = m.GetSub(-1,-1,2,csize,"S");
02346       TMatrixDSparse m_part4 = m.GetSub(-1,-1,1,1,"S");
02347       m6.SetSub(0,2,m_part1);
02348       m6.SetSub(0,1,m_part2);
02349       m6.SetSub(-1,2,m_part3);
02350       m6.SetSub(-1,1,m_part4);
02351       ok &= VerifyMatrixIdentity(m,m6,gVerbose,EPSILON);
02352     }
02353   }
02354 
02355   {
02356     if (gVerbose)
02357       cout << "Check insertion/extraction of rows" << endl;
02358 
02359     TMatrixDSparse m1 = m;
02360     TVectorD v1(1,csize);
02361     TVectorD v2(1,csize);
02362     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
02363       v1 = TMatrixDSparseRow(m,i);
02364       m1.InsertRow(i,1,v1.GetMatrixArray());
02365       ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
02366       m1.InsertRow(i,3,v1.GetMatrixArray()+2,v1.GetNrows()-2);
02367       ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
02368 
02369       m1.ExtractRow(i,1,v2.GetMatrixArray());
02370       ok &= VerifyVectorIdentity(v1,v2,gVerbose,EPSILON);
02371       m1.ExtractRow(i,3,v2.GetMatrixArray()+2,v1.GetNrows()-2);
02372       ok &= VerifyVectorIdentity(v1,v2,gVerbose,EPSILON);
02373     }
02374   }
02375 
02376   {
02377     if (gVerbose)
02378       cout << "Check array Use" << endl;
02379     {
02380       TMatrixDSparse *m1a = new TMatrixDSparse(m);
02381       TMatrixDSparse *m2a = new TMatrixDSparse();
02382       m2a->Use(*m1a);
02383       m2a->Sqr();
02384       TMatrixDSparse m7 = m; m7.Sqr();
02385       ok &= VerifyMatrixIdentity(m7,*m1a,gVerbose,EPSILON);
02386       delete m1a;
02387       delete m2a;
02388     }
02389   }
02390 
02391   if (gVerbose)
02392     cout << "\nDone\n" << endl;
02393 
02394   StatusPrint(2,"Filling, Inserting, Using",ok);
02395 }
02396 
02397 //
02398 //------------------------------------------------------------------------
02399 //                Test uniform element operations
02400 //
02401 void spstress_element_op(Int_t rsize,Int_t csize)
02402 {
02403   Bool_t ok = kTRUE;
02404   const Double_t pattern = 8.625;
02405 
02406   TMatrixDSparse m(-1,rsize-2,1,csize);
02407 
02408   if (gVerbose)
02409     cout << "Creating zero m1 ..." << endl;
02410   TMatrixDSparse m1(TMatrixDSparse::kZero, m);
02411   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
02412 
02413   if (gVerbose)
02414     cout << "Comparing m1 with 0 ..." << endl;
02415   R__ASSERT(m1 == 0);
02416   R__ASSERT(!(m1 != 0));
02417 
02418   if (gVerbose)
02419     cout << "Writing a pattern " << pattern << " by assigning through SetMatrixArray..." << endl;
02420   {
02421     const Int_t nr = rsize*csize;
02422     Int_t    *irow = new Int_t[nr];
02423     Int_t    *icol = new Int_t[nr];
02424     Double_t *val  = new Double_t[nr];
02425 
02426     Int_t n = 0;
02427     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
02428       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++) {
02429         irow[n] = i;
02430         icol[n] = j;
02431         val[n] = pattern;
02432         n++;
02433       }
02434     }
02435     m.SetMatrixArray(nr,irow,icol,val);
02436     delete [] irow;
02437     delete [] icol;
02438     delete [] val;
02439     ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
02440   }
02441 
02442   if (gVerbose)
02443     cout << "Writing the pattern by assigning to m1 as a whole ..."  << endl;
02444   m1.SetSparseIndex(m);
02445   m1 = pattern;
02446   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
02447 
02448   if (gVerbose)
02449     cout << "Comparing m and m1 ..." << endl;
02450   R__ASSERT(m == m1);
02451   if (gVerbose)
02452     cout << "Comparing (m=0) and m1 ..." << endl;
02453   R__ASSERT(!((m=0) == m1));
02454 
02455   if (gVerbose)
02456     cout << "Clearing m1 ..." << endl;
02457   m1.Zero();
02458   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
02459 
02460   if (gVerbose)
02461     cout << "\nSet m = pattern" << endl;
02462   m = pattern;
02463   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
02464   if (gVerbose)
02465     cout << "   add the doubled pattern with the negative sign" << endl;
02466   m += -2*pattern;
02467   ok &= VerifyMatrixValue(m,-pattern,gVerbose,EPSILON);
02468   if (gVerbose)
02469     cout << "   subtract the trippled pattern with the negative sign" << endl;
02470   m -= -3*pattern;
02471   ok &= VerifyMatrixValue(m,2*pattern,gVerbose,EPSILON);
02472 
02473   if (gVerbose)
02474     cout << "\nVerify comparison operations when all elems are the same" << endl;
02475   m = pattern;
02476   R__ASSERT( m == pattern && !(m != pattern) );
02477   R__ASSERT( m > 0 && m >= pattern && m <= pattern );
02478   R__ASSERT( m > -pattern && m >= -pattern );
02479   R__ASSERT( m <= pattern && !(m < pattern) );
02480   m -= 2*pattern;
02481   R__ASSERT( m  < -pattern/2 && m <= -pattern/2 );
02482   R__ASSERT( m  >= -pattern && !(m > -pattern) );
02483 
02484   if (gVerbose)
02485     cout << "\nVerify comparison operations when not all elems are the same" << endl;
02486   {
02487     Int_t nr = rsize*csize;
02488     Int_t    *irow = new Int_t[nr];
02489     Int_t    *icol = new Int_t[nr];
02490     Double_t *val  = new Double_t[nr];
02491 
02492     Int_t n = 0;
02493     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
02494       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++) {
02495         irow[n] = i;
02496         icol[n] = j;
02497         val[n] = pattern;
02498         n++;
02499       }
02500     }
02501     val[n-1] = pattern-1;
02502     m.SetMatrixArray(nr,irow,icol,val);
02503     delete [] irow;
02504     delete [] icol;
02505     delete [] val;
02506   }
02507 
02508   R__ASSERT( !(m == pattern) && !(m != pattern) );
02509   R__ASSERT( m != 0 );                   // none of elements are 0
02510   R__ASSERT( !(m >= pattern) && m <= pattern && !(m<pattern) );
02511   R__ASSERT( !(m <= pattern-1) && m >= pattern-1 && !(m>pattern-1) );
02512   if (gVerbose)
02513     cout << "\nAssign 2*pattern to m by repeating additions" << endl;
02514   m = 0; m += pattern; m += pattern;
02515   if (gVerbose)
02516     cout << "Assign 2*pattern to m1 by multiplying by two " << endl;
02517   m1.SetSparseIndex(m);
02518   m1 = pattern; m1 *= 2;
02519   ok &= VerifyMatrixValue(m1,2*pattern,gVerbose,EPSILON);
02520   R__ASSERT( m == m1 );
02521   if (gVerbose)
02522     cout << "Multiply m1 by one half returning it to the 1*pattern" << endl;
02523   m1 *= 1/2.;
02524   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
02525 
02526   if (gVerbose)
02527     cout << "\nAssign -pattern to m and m1" << endl;
02528   m = 0; m -= pattern; m1 = -pattern;
02529   ok &= VerifyMatrixValue(m,-pattern,gVerbose,EPSILON);
02530   R__ASSERT( m == m1 );
02531   if (gVerbose)
02532     cout << "m = sqrt(sqr(m)); m1 = abs(m1); Now m and m1 have to be the same" << endl;
02533   m.Sqr();
02534   ok &= VerifyMatrixValue(m,pattern*pattern,gVerbose,EPSILON);
02535   m.Sqrt();
02536   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
02537   m1.Abs();
02538   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
02539   ok &= VerifyMatrixIdentity(m1,m,gVerbose,EPSILON);
02540 
02541   if (gVerbose)
02542     cout << "\nDone\n" << endl;
02543 
02544   StatusPrint(3,"Uniform matrix operations",ok);
02545 }
02546 
02547 //
02548 //------------------------------------------------------------------------
02549 //        Test binary matrix element-by-element operations
02550 //
02551 void spstress_binary_ebe_op(Int_t rsize, Int_t csize)
02552 {
02553   if (gVerbose)
02554     cout << "\n---> Test Binary Matrix element-by-element operations" << endl;
02555 
02556   Bool_t ok = kTRUE;
02557 
02558   const Double_t pattern = 4.25;
02559 
02560   TMatrixD m_d(2,rsize+1,0,csize-1); m_d = 1;
02561   TMatrixDSparse m (TMatrixDSparse::kZero,m_d); m.SetSparseIndex (m_d);
02562   TMatrixDSparse m1(TMatrixDSparse::kZero,m);   m1.SetSparseIndex(m_d);
02563 
02564   TMatrixDSparse mp(TMatrixDSparse::kZero,m1);  mp.SetSparseIndex(m_d);
02565   {
02566     for (Int_t i = mp.GetRowLwb(); i <= mp.GetRowUpb(); i++)
02567       for (Int_t j = mp.GetColLwb(); j <= mp.GetColUpb(); j++)
02568         mp(i,j) = TMath::Pi()*i+TMath::E()*(j+1);
02569   }
02570 
02571   if (gVerbose)
02572     cout << "\nVerify assignment of a matrix to the matrix" << endl;
02573   m  = pattern;
02574   m1 = m;
02575   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
02576   R__ASSERT( m1 == m );
02577 
02578   if (gVerbose)
02579     cout << "\nAdding the matrix to itself, uniform pattern " << pattern << endl;
02580   m.Zero(); m.SetSparseIndex(m_d); m = pattern;
02581 
02582   m1 = m; m1 += m1;
02583   ok &= VerifyMatrixValue(m1,2*pattern,gVerbose,EPSILON);
02584   if (gVerbose)
02585     cout << "  subtracting two matrices ..." << endl;
02586   m1 -= m;
02587   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
02588   if (gVerbose)
02589     cout << "  subtracting the matrix from itself" << endl;
02590   m1 -= m1;
02591   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
02592   m1.SetSparseIndex(m_d);
02593 
02594   if (gVerbose) {
02595     cout << "\nArithmetic operations on matrices with not the same elements" << endl;
02596     cout << "   adding mp to the zero matrix..." << endl;
02597   }
02598   m.Zero(); m.SetSparseIndex(m_d); m += mp;
02599   ok &= VerifyMatrixIdentity(m,mp,gVerbose,EPSILON);
02600   if (gVerbose)
02601     cout << "   making m = 3*mp and m1 = 3*mp, via add() and succesive mult" << endl;
02602   m1 = m;
02603   Add(m,2.,mp);
02604   m1 += m1; m1 += mp;
02605   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
02606   if (gVerbose)
02607     cout << "   clear both m and m1, by subtracting from itself and via add()" << endl;
02608   m1 -= m1;
02609   Add(m,-3.,mp);
02610   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
02611 
02612   if (gVerbose) {
02613     cout << "\nTesting element-by-element multiplications and divisions" << endl;
02614     cout << "   squaring each element with sqr() and via multiplication" << endl;
02615   }
02616   m.SetSparseIndex(m_d);  m = mp;
02617   m1.SetSparseIndex(m_d); m1 = mp;
02618   m.Sqr();
02619   ElementMult(m1,m1);
02620   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
02621   if (gVerbose)
02622     cout << "   compare (m = pattern^2)/pattern with pattern" << endl;
02623   m = pattern; m1 = pattern;
02624   m.Sqr();
02625   ElementDiv(m,m1);
02626   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
02627   if (gVerbose)
02628     Compare(m1,m);
02629 
02630   if (gVerbose)
02631     cout << "\nDone\n" << endl;
02632 
02633   StatusPrint(4,"Binary Matrix element-by-element operations",ok);
02634 }
02635 
02636 //
02637 //------------------------------------------------------------------------
02638 //              Verify matrix transposition
02639 //
02640 void spstress_transposition(Int_t msize)
02641 {
02642   if (gVerbose) {
02643     cout << "\n---> Verify matrix transpose "
02644             "for matrices of a characteristic size " << msize << endl;
02645   }
02646 
02647   Bool_t ok = kTRUE;
02648   {
02649     if (gVerbose)
02650       cout << "\nCheck to see that a square UnitMatrix stays the same";
02651     TMatrixDSparse m(msize,msize);
02652     m.UnitMatrix();
02653     TMatrixDSparse mt(TMatrixDSparse::kTransposed,m);
02654     ok &= ( m == mt ) ? kTRUE : kFALSE;
02655   }
02656 
02657   {
02658     if (gVerbose)
02659       cout << "\nTest a non-square UnitMatrix";
02660     TMatrixDSparse m(msize,msize+1);
02661     m.UnitMatrix();
02662     TMatrixDSparse mt(TMatrixDSparse::kTransposed,m);
02663     R__ASSERT(m.GetNrows() == mt.GetNcols() && m.GetNcols() == mt.GetNrows() );
02664     const Int_t rowlwb = m.GetRowLwb();
02665     const Int_t collwb = m.GetColLwb();
02666     const Int_t upb = TMath::Min(m.GetRowUpb(),m.GetColUpb());
02667     TMatrixDSparse m_part  = m.GetSub(rowlwb,upb,collwb,upb);
02668     TMatrixDSparse mt_part = mt.GetSub(rowlwb,upb,collwb,upb);
02669     ok &= ( m_part == mt_part ) ? kTRUE : kFALSE;
02670   }
02671 
02672   {
02673     if (gVerbose)
02674       cout << "\nCheck to see that a symmetric (Hilbert)Matrix stays the same";
02675     TMatrixDSparse m = TMatrixD(THilbertMatrixD(msize,msize));
02676     TMatrixDSparse mt(TMatrixDSparse::kTransposed,m);
02677     ok &= ( m == mt ) ? kTRUE : kFALSE;
02678   }
02679 
02680   {
02681     if (gVerbose)
02682       cout << "\nCheck transposing a non-symmetric matrix";
02683     TMatrixDSparse m = TMatrixD(THilbertMatrixD(msize+1,msize));
02684     m(1,2) = TMath::Pi();
02685     TMatrixDSparse mt(TMatrixDSparse::kTransposed,m);
02686     R__ASSERT(m.GetNrows() == mt.GetNcols() && m.GetNcols() == mt.GetNrows());
02687     R__ASSERT(mt(2,1)  == (Double_t)TMath::Pi() && mt(1,2)  != (Double_t)TMath::Pi());
02688     R__ASSERT(mt[2][1] == (Double_t)TMath::Pi() && mt[1][2] != (Double_t)TMath::Pi());
02689 
02690     if (gVerbose)
02691       cout << "\nCheck double transposing a non-symmetric matrix" << endl;
02692     TMatrixDSparse mtt(TMatrixDSparse::kTransposed,mt);
02693     ok &= ( m == mtt ) ? kTRUE : kFALSE;
02694   }
02695 
02696   if (gVerbose)
02697     cout << "\nDone\n" << endl;
02698 
02699   StatusPrint(5,"Matrix transposition",ok);
02700 }
02701 
02702 //
02703 //------------------------------------------------------------------------
02704 //             Verify the norm calculation
02705 //
02706 void spstress_norms(Int_t rsize_req,Int_t csize_req)
02707 {
02708   if (gVerbose)
02709     cout << "\n---> Verify norm calculations" << endl;
02710 
02711   Bool_t ok = kTRUE;
02712   const Double_t pattern = 10.25;
02713 
02714   Int_t rsize = rsize_req;
02715   if (rsize%2 != 0)  rsize--;
02716   Int_t csize = csize_req;
02717   if (csize%2 != 0)  csize--;
02718   if (rsize%2 == 1 || csize%2 == 1) {
02719     cout << "rsize: " << rsize <<endl;
02720     cout << "csize: " << csize <<endl;
02721     Fatal("spstress_norms","Sorry, size of the matrix to test must be even for this test\n");
02722   }
02723 
02724   TMatrixD m_d(rsize,csize); m_d = 1;
02725   TMatrixDSparse m(rsize,csize); m.SetSparseIndex(m_d);
02726 
02727   if (gVerbose)
02728     cout << "\nAssign " << pattern << " to all the elements and check norms" << endl;
02729   m = pattern;
02730   if (gVerbose)
02731     cout << "  1. (col) norm should be pattern*nrows" << endl;
02732   ok &= ( m.Norm1() == pattern*m.GetNrows() ) ? kTRUE : kFALSE;
02733   ok &= ( m.Norm1() == m.ColNorm() ) ? kTRUE : kFALSE;
02734   if (gVerbose)
02735     cout << "  Inf (row) norm should be pattern*ncols" << endl;
02736   ok &= ( m.NormInf() == pattern*m.GetNcols() ) ? kTRUE : kFALSE;
02737   ok &= ( m.NormInf() == m.RowNorm() ) ? kTRUE : kFALSE;
02738   if (gVerbose)
02739     cout << "  Square of the Eucl norm has got to be pattern^2 * no_elems" << endl;
02740   ok &= ( m.E2Norm() == (pattern*pattern)*m.GetNoElements() ) ? kTRUE : kFALSE;
02741   TMatrixDSparse m1(m); m1 = 1;
02742   ok &= ( m.E2Norm() == E2Norm(m+1.,m1) ) ? kTRUE : kFALSE;
02743 
02744   if (gVerbose)
02745     cout << "\nDone\n" << endl;
02746 
02747   StatusPrint(6,"Matrix Norms",ok);
02748 }
02749 
02750 //
02751 //------------------------------------------------------------------------
02752 //               Verify matrix multiplications
02753 //
02754 void spstress_mm_multiplications()
02755 {
02756   Bool_t ok = kTRUE;
02757   Int_t i;
02758 
02759   Int_t iloop = 0;
02760   Int_t nr    = 0;
02761   while (iloop <= gNrLoop) {
02762     const Int_t msize = gSizeA[iloop];
02763     const Double_t epsilon = EPSILON*msize/100;
02764 
02765     const Int_t verbose = (gVerbose && nr==0 && iloop==gNrLoop);
02766 
02767     if (msize <= 5) {
02768        iloop++;
02769        continue;  // some references to m(3,..)
02770     }
02771 
02772     if (verbose)
02773       cout << "\n---> Verify matrix multiplications "
02774               "for matrices of the characteristic size " << msize << endl;
02775 
02776     {
02777       if (verbose)
02778         cout << "\nTest inline multiplications of the UnitMatrix" << endl;
02779       if (ok)
02780       {
02781         TMatrixDSparse m = TMatrixD(THilbertMatrixD(-1,msize,-1,msize));
02782         TMatrixDSparse ur(TMatrixDSparse::kUnit,m);
02783         TMatrixDSparse ul(TMatrixDSparse::kUnit,m);
02784         m(3,1) = TMath::Pi();
02785         ul *= m;
02786         m  *= ur;
02787         ok &= VerifyMatrixIdentity(ul,m,verbose,epsilon);
02788       }
02789 
02790       if (ok)
02791       {
02792         TMatrixD m_d = THilbertMatrixD(-1,msize,-1,msize);
02793         TMatrixDSparse ur(TMatrixDSparse::kUnit,m_d);
02794         TMatrixDSparse ul(TMatrixDSparse::kUnit,m_d);
02795         m_d(3,1) = TMath::Pi();
02796         ul *= m_d;
02797         m_d  *= TMatrixD(ur);
02798         ok &= VerifyMatrixIdentity(ul,m_d,verbose,epsilon);
02799       }
02800     }
02801 
02802     if (ok)
02803     {
02804       if (verbose)
02805         cout << "Test XPP = X where P is a permutation matrix" << endl;
02806       TMatrixDSparse m = TMatrixD(THilbertMatrixD(msize-1,msize));
02807       m(2,3) = TMath::Pi();
02808       TMatrixDSparse eth = m;
02809       TMatrixDSparse p(msize,msize);
02810       {
02811         Int_t    *irow = new Int_t[msize];
02812         Int_t    *icol = new Int_t[msize];
02813         Double_t *val  = new Double_t[msize];
02814 
02815         Int_t n = 0;
02816         for (i = p.GetRowLwb(); i <= p.GetRowUpb(); i++) {
02817           irow[n] = p.GetRowUpb()+p.GetRowLwb()-i;
02818           icol[n] = i;
02819           val[n] = 1;
02820           n++;
02821         }
02822         p.SetMatrixArray(msize,irow,icol,val);
02823         delete [] irow;
02824         delete [] icol;
02825         delete [] val;
02826       }
02827       m *= p;
02828       m *= p;
02829       ok &= VerifyMatrixIdentity(m,eth,verbose,epsilon);
02830     }
02831 
02832     if (ok)
02833     {
02834       if (verbose)
02835         cout << "Test general matrix multiplication through inline mult" << endl;
02836       TMatrixDSparse m = TMatrixD(THilbertMatrixD(msize-2,msize));
02837       m(3,3) = TMath::Pi();
02838       TMatrixD p_d = THilbertMatrixD(msize,msize);
02839       TMatrixDDiag(p_d) += 1;
02840       TMatrixDSparse mp(m,TMatrixDSparse::kMult,p_d);
02841       TMatrixDSparse m1 = m;
02842       m *= p_d;
02843       ok &= VerifyMatrixIdentity(m,mp,verbose,epsilon);
02844       TMatrixDSparse pt_d(TMatrixDSparse::kTransposed,p_d);
02845       TMatrixDSparse mp1(m1,TMatrixDSparse::kMultTranspose,pt_d);
02846       VerifyMatrixIdentity(m,mp1,verbose,epsilon);
02847 
02848       ok &= ( !(m1 == m) );
02849       TMatrixDSparse mp2(TMatrixDSparse::kZero,m1);
02850       ok &= ( mp2 == 0 );
02851       mp2.SetSparseIndex(m1);
02852       mp2.Mult(m1,p_d);
02853       ok &= VerifyMatrixIdentity(m,mp2,verbose,epsilon);
02854 
02855       if (verbose)
02856         cout << "Test XP=X*P  vs XP=X;XP*=P" << endl;
02857       TMatrixDSparse mp3 = m1*p_d;
02858       ok &= VerifyMatrixIdentity(m,mp3,verbose,epsilon);
02859     }
02860 
02861 #ifndef __CINT__
02862     if (nr >= Int_t(1.0e+5/msize/msize)) {
02863 #else
02864     if (nr >= Int_t(1.0e+3/msize/msize)) {
02865 #endif
02866       nr = 0;
02867       iloop++;
02868     } else
02869       nr++;
02870 
02871     if (!ok) {
02872       if (gVerbose)
02873         cout << "General Matrix Multiplications failed for size " << msize << endl;
02874       break;
02875     }
02876   }
02877 
02878   if (ok)
02879   {
02880     if (gVerbose)
02881       cout << "Check to see UU' = U'U = E when U is the Haar matrix" << endl;
02882     const Int_t order = 5;
02883     const Int_t no_sub_cols = (1<<order)-order;
02884     TMatrixDSparse haar_sub = TMatrixD(THaarMatrixD(order,no_sub_cols));
02885     TMatrixDSparse haar_sub_t(TMatrixDSparse::kTransposed,haar_sub);
02886     TMatrixDSparse hsths(haar_sub_t,TMatrixDSparse::kMult,haar_sub);
02887 
02888     TMatrixDSparse square(no_sub_cols,no_sub_cols);
02889     TMatrixDSparse units(TMatrixDSparse::kUnit,square);
02890     ok &= ( hsths.GetNrows() == no_sub_cols && hsths.GetNcols() == no_sub_cols );
02891     ok &= VerifyMatrixIdentity(hsths,units,gVerbose,EPSILON);
02892 
02893     TMatrixDSparse haar = TMatrixD(THaarMatrixD(order));
02894     TMatrixDSparse haar_t(TMatrixDSparse::kTransposed,haar);
02895     TMatrixDSparse unit(TMatrixDSparse::kUnit,haar);
02896 
02897     TMatrixDSparse hth(haar_t,TMatrixDSparse::kMult,haar);
02898     ok &= VerifyMatrixIdentity(hth,unit,gVerbose,EPSILON);
02899 
02900     TMatrixDSparse hht(haar,TMatrixDSparse::kMultTranspose,haar);
02901     ok &= VerifyMatrixIdentity(hht,unit,gVerbose,EPSILON);
02902 
02903     TMatrixDSparse hht1 = haar; hht1 *= haar_t;
02904     ok &= VerifyMatrixIdentity(hht1,unit,gVerbose,EPSILON);
02905 
02906     TMatrixDSparse hht2(TMatrixDSparse::kZero,haar);
02907     hht2.SetSparseIndex(hht1);
02908     hht2.Mult(haar,haar_t);
02909     ok &= VerifyMatrixIdentity(hht2,unit,gVerbose,EPSILON);
02910   }
02911 
02912   if (gVerbose)
02913     cout << "\nDone\n" << endl;
02914 
02915   StatusPrint(7,"General Matrix Multiplications",ok);
02916 }
02917 
02918 //
02919 //------------------------------------------------------------------------
02920 //               Verify vector-matrix multiplications
02921 //
02922 void spstress_vm_multiplications()
02923 {
02924   Bool_t ok = kTRUE;
02925 
02926   Int_t iloop = gNrLoop;
02927   Int_t nr    = 0;
02928   while (iloop >= 0) {
02929     const Int_t msize = gSizeA[iloop];
02930 
02931     const Double_t epsilon = EPSILON*msize;
02932 
02933     const Int_t verbose = (gVerbose && nr==0 && iloop==gNrLoop);
02934 
02935     if (verbose)
02936       cout << "\n---> Verify vector-matrix multiplications "
02937              "for matrices of the characteristic size " << msize << endl;
02938 
02939     {
02940       if (verbose)
02941         cout << "\nCheck shrinking a vector by multiplying by a non-sq unit matrix" << endl;
02942       TVectorD vb(-2,msize);
02943       for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
02944         vb(i) = TMath::Pi()-i;
02945       ok &= ( vb != 0 ) ? kTRUE : kFALSE;
02946       TMatrixDSparse mc(1,msize-2,-2,msize);       // contracting matrix
02947       mc.UnitMatrix();
02948       TVectorD v1 = vb;
02949       TVectorD v2 = vb;
02950       v1 *= mc;
02951       v2.ResizeTo(1,msize-2);
02952       ok &= VerifyVectorIdentity(v1,v2,verbose,epsilon);
02953     }
02954 
02955     if (ok)
02956     {
02957       if (verbose)
02958         cout << "Check expanding a vector by multiplying by a non-sq unit matrix" << endl;
02959       TVectorD vb(msize);
02960       for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
02961         vb(i) = TMath::Pi()+i;
02962       ok &= ( vb != 0 ) ? kTRUE : kFALSE;
02963       TMatrixDSparse me(2,msize+5,0,msize-1);    // expanding matrix
02964       me.UnitMatrix();
02965       TVectorD v1 = vb;
02966       TVectorD v2 = vb;
02967       v1 *= me;
02968       v2.ResizeTo(v1);
02969       ok &= VerifyVectorIdentity(v1,v2,verbose,epsilon);
02970     }
02971 
02972     if (ok)
02973     {
02974       if (verbose)
02975         cout << "Check general matrix-vector multiplication" << endl;
02976       TVectorD vb(msize);
02977       for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
02978         vb(i) = TMath::Pi()+i;
02979       TMatrixD vm(msize,1);
02980       TMatrixDColumn(vm,0) = vb;
02981       TMatrixD hilbert_with_zeros = THilbertMatrixD(0,msize,0,msize-1);
02982       TMatrixDRow   (hilbert_with_zeros,3) = 0.0;
02983       TMatrixDColumn(hilbert_with_zeros,3) = 0.0;
02984       const TMatrixDSparse m = hilbert_with_zeros;
02985       vb *= m;
02986       ok &= ( vb.GetLwb() == 0 ) ? kTRUE : kFALSE;
02987       TMatrixDSparse mvm(m,TMatrixDSparse::kMult,vm);
02988       TMatrixD mvb(msize+1,1);
02989       TMatrixDColumn(mvb,0) = vb;
02990       ok &= VerifyMatrixIdentity(mvb,mvm,verbose,epsilon);
02991     }
02992 
02993 #ifndef __CINT__
02994     if (nr >= Int_t(1.0e+5/msize/msize)) {
02995 #else
02996     if (nr >= Int_t(1.0e+3/msize/msize)) {
02997 #endif
02998       nr = 0;
02999       iloop--;
03000     } else
03001       nr++;
03002 
03003     if (!ok) {
03004       if (gVerbose)
03005         cout << "Vector Matrix Multiplications failed for size " << msize << endl;
03006       break;
03007     }
03008   }
03009 
03010   if (gVerbose)
03011     cout << "\nDone\n" << endl;
03012 
03013   StatusPrint(8,"Matrix Vector Multiplications",ok);
03014 }
03015 
03016 //
03017 //------------------------------------------------------------------------
03018 //           Test operations with vectors and sparse matrix slices
03019 //
03020 void spstress_matrix_slices(Int_t vsize)
03021 {
03022   if (gVerbose)
03023     cout << "\n---> Test operations with vectors and sparse matrix slices" << endl;
03024 
03025   Bool_t ok = kTRUE;
03026   const Double_t pattern = 8.625;
03027 
03028   TVectorD vc(0,vsize);
03029   TVectorD vr(0,vsize+1);
03030   TMatrixD       m_d(0,vsize,0,vsize+1); m_d = pattern;
03031   TMatrixDSparse m(m_d);
03032 
03033   Int_t i,j;
03034   if (gVerbose)
03035     cout << "\nCheck modifying the matrix row-by-row" << endl;
03036   m = pattern;
03037   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03038   for (i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
03039     TMatrixDSparseRow(m,i) = pattern+2;
03040     ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03041     vr = TMatrixDSparseRow(m,i);
03042     ok &= VerifyVectorValue(vr,pattern+2,gVerbose,EPSILON);
03043     vr = TMatrixDSparseRow(m,i+1 > m.GetRowUpb() ? m.GetRowLwb() : i+1);
03044     ok &= VerifyVectorValue(vr,pattern,gVerbose,EPSILON);
03045     TMatrixDSparseRow(m,i) += -2;
03046     ok &= ( m == pattern ) ? kTRUE : kFALSE;
03047   }
03048 
03049   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03050   for (i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
03051     vr = pattern-2;
03052     TMatrixDSparseRow(m,i) = vr;
03053     ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03054     {
03055       TMatrixDSparseRow mr(m,i);
03056       for (j = m.GetColLwb(); j <= m.GetColUpb(); j++)
03057         mr(j) *= 8;
03058     }
03059     vr = TMatrixDSparseRow(m,i);
03060     ok &= VerifyVectorValue(vr,8*(pattern-2),gVerbose,EPSILON);
03061     TMatrixDSparseRow(m,i) *= 1./8;
03062     TMatrixDSparseRow(m,i) += 2;
03063     vr = TMatrixDSparseRow(m,i);
03064     ok &= VerifyVectorValue(vr,pattern,gVerbose,EPSILON);
03065     ok &= ( m == pattern ) ? kTRUE : kFALSE;
03066   }
03067 
03068   if (gVerbose)
03069     cout << "\nCheck modifying the matrix diagonal" << endl;
03070   m = pattern;
03071   TMatrixDSparseDiag td = m;
03072   td = pattern-3;
03073   ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03074   vc = TMatrixDSparseDiag(m);
03075   ok &= VerifyVectorValue(vc,pattern-3,gVerbose,EPSILON);
03076   td += 3;
03077   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03078   vc = pattern+3;
03079   td = vc;
03080   ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03081   {
03082     TMatrixDSparseDiag md(m);
03083     for (j = 0; j < md.GetNdiags(); j++)
03084       md(j) /= 1.5;
03085   }
03086   vc = TMatrixDSparseDiag(m);
03087   ok &= VerifyVectorValue(vc,(pattern+3)/1.5,gVerbose,EPSILON);
03088   TMatrixDSparseDiag(m) *= 1.5;
03089   TMatrixDSparseDiag(m) += -3;
03090   vc = TMatrixDSparseDiag(m);
03091   ok &= VerifyVectorValue(vc,pattern,gVerbose,EPSILON);
03092   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03093 
03094   if (gVerbose)
03095     cout << "\nDone\n" << endl;
03096   StatusPrint(9,"Matrix Slices to Vectors",ok);
03097 }
03098 
03099 //
03100 //------------------------------------------------------------------------
03101 //           Test matrix I/O
03102 //
03103 void spstress_matrix_io()
03104 {
03105   if (gVerbose)
03106     cout << "\n---> Test matrix I/O" << endl;
03107 
03108   Bool_t ok = kTRUE;
03109   const Double_t pattern = TMath::Pi();
03110 
03111   TFile *f = new TFile("vmatrix.root", "RECREATE");
03112 
03113   Char_t name[80];
03114   Int_t iloop = gNrLoop;
03115   while (iloop >= 0) {
03116     const Int_t msize = gSizeA[iloop];
03117 
03118     const Int_t verbose = (gVerbose && iloop==gNrLoop);
03119 
03120     TMatrixD m_d(msize,msize); m_d = pattern;
03121     TMatrixDSparse m(m_d);
03122     TMatrixDSparse ma;
03123     ma.Use(m);
03124 
03125     if (verbose)
03126       cout << "\nWrite matrix m to database" << endl;
03127     sprintf(name,"m_%d",msize);
03128     m.Write(name);
03129 
03130     if (verbose)
03131       cout << "\nWrite matrix ma which adopts to database" << endl;
03132     sprintf(name,"ma_%d",msize);
03133     ma.Write(name);
03134 
03135     iloop--;
03136   }
03137 
03138   if (gVerbose)
03139     cout << "\nClose database" << endl;
03140   delete f;
03141 
03142   if (gVerbose)
03143     cout << "\nOpen database in read-only mode and read matrix" << endl;
03144   TFile *f1 = new TFile("vmatrix.root");
03145 
03146   iloop = gNrLoop;
03147   while (iloop >= 0) {
03148     const Int_t msize = gSizeA[iloop];
03149 
03150     const Int_t verbose = (gVerbose && iloop==gNrLoop);
03151 
03152     TMatrixD m_d(msize,msize); m_d = pattern;
03153     TMatrixDSparse m(m_d);
03154     sprintf(name,"m_%d",msize);
03155     TMatrixDSparse *mr  = (TMatrixDSparse*) f1->Get(name);
03156     sprintf(name,"ma_%d",msize);
03157     TMatrixDSparse *mar = (TMatrixDSparse*) f1->Get(name);
03158     sprintf(name,"ms_%d",msize);
03159 
03160     if (verbose)
03161       cout << "\nRead matrix should be same as original" << endl;
03162     ok &= ((*mr)  == m) ? kTRUE : kFALSE;
03163     ok &= ((*mar) == m) ? kTRUE : kFALSE;
03164 
03165     iloop--;
03166   }
03167 
03168   delete f1;
03169 
03170   if (gVerbose)
03171     cout << "\nDone\n" << endl;
03172 
03173   StatusPrint(10,"Matrix Persistence",ok);
03174 }
03175 
03176 //------------------------------------------------------------------------
03177 //          Test allocation functions and compatibility check
03178 //
03179 void vstress_allocation(Int_t msize)
03180 {
03181   if (gVerbose)
03182     cout << "\n\n---> Test allocation and compatibility check" << endl;
03183 
03184   Int_t i;
03185   Bool_t ok = kTRUE;
03186   TVectorD v1(msize);
03187   TVectorD v2(0,msize-1);
03188   TVectorD v3(1,msize);
03189   TVectorD v4(v1);
03190 
03191   if (gVerbose) {
03192     cout << "\nStatus information reported for vector v3:" << endl;
03193     cout << "  Lower bound ... " << v3.GetLwb() << endl;
03194     cout << "  Upper bound ... " << v3.GetUpb() << endl;
03195     cout << "  No. of elements " << v3.GetNoElements() << endl;
03196   }
03197 
03198   if (gVerbose)
03199     cout << "\nCheck vectors 1 & 2 for compatibility" << endl;
03200   ok &= AreCompatible(v1,v2,gVerbose);
03201 
03202   if (gVerbose)
03203     cout << "Check vectors 1 & 4 for compatibility" << endl;
03204   ok &= AreCompatible(v1,v4,gVerbose);
03205 
03206   if (gVerbose)
03207     cout << "v2 has to be compatible with v3 after resizing to v3" << endl;
03208   v2.ResizeTo(v3);
03209   ok &= AreCompatible(v2,v3,gVerbose);
03210 
03211   TVectorD v5(v1.GetUpb()+5);
03212   if (gVerbose)
03213     cout << "v1 has to be compatible with v5 after resizing to v5.upb" << endl;
03214   v1.ResizeTo(v5.GetNoElements());
03215   ok &= AreCompatible(v1,v5,gVerbose);
03216 
03217   {
03218     if (gVerbose)
03219       cout << "Check that shrinking does not change remaining elements" << endl;
03220     TVectorD vb(-1,msize);
03221     for (i = vb.GetLwb(); i <= vb.GetUpb(); i++)
03222       vb(i) = i+TMath::Pi();
03223     TVectorD v = vb;
03224     ok &= ( v == vb ) ? kTRUE : kFALSE;
03225     ok &= ( v != 0 ) ? kTRUE : kFALSE;
03226     v.ResizeTo(0,msize/2);
03227     for (i = v.GetLwb(); i <= v.GetUpb(); i++)
03228       ok &= ( v(i) == vb(i) ) ? kTRUE : kFALSE;
03229     if (gVerbose)
03230       cout << "Check that expansion expands by zeros" << endl;
03231     const Int_t old_nelems = v.GetNoElements();
03232     const Int_t old_lwb    = v.GetLwb();
03233     v.ResizeTo(vb);
03234     ok &= ( !(v == vb) ) ? kTRUE : kFALSE;
03235     for (i = old_lwb; i < old_lwb+old_nelems; i++)
03236       ok &= ( v(i) == vb(i) ) ? kTRUE : kFALSE;
03237     for (i = v.GetLwb(); i < old_lwb; i++)
03238       ok &= ( v(i) == 0 ) ? kTRUE : kFALSE;
03239     for (i = old_lwb+old_nelems; i <= v.GetUpb(); i++)
03240       ok &= ( v(i) == 0 ) ? kTRUE : kFALSE;
03241   }
03242 
03243   if (gVerbose)
03244     cout << "\nDone\n" << endl;
03245   StatusPrint(1,"Allocation, Filling, Resizing",ok);
03246 }
03247 
03248 //
03249 //------------------------------------------------------------------------
03250 //                Test uniform element operations
03251 //
03252 class SinAction : public TElementActionD {
03253   void Operation(Double_t &element) const { element = TMath::Sin(element); }
03254   public:
03255     SinAction() { }
03256 };
03257 
03258 class CosAction : public TElementPosActionD {
03259   Double_t factor;
03260   void Operation(Double_t &element) const { element = TMath::Cos(factor*fI); }
03261   public:
03262     CosAction(Int_t no_elems): factor(2*TMath::Pi()/no_elems) { }
03263 };
03264 
03265 void vstress_element_op(Int_t vsize)
03266 {
03267   if (gVerbose)
03268     cout << "\n---> Test operations that treat each element uniformly" << endl;
03269 
03270   Bool_t ok = kTRUE;
03271   const Double_t pattern = TMath::Pi();
03272 
03273   TVectorD v(-1,vsize-2);
03274   TVectorD v1(v);
03275 
03276   if (gVerbose)
03277     cout << "\nWriting zeros to v..." << endl;
03278   for (Int_t i = v.GetLwb(); i <= v.GetUpb(); i++)
03279     v(i) = 0;
03280   ok &= VerifyVectorValue(v,0.0,gVerbose,EPSILON);
03281 
03282   if (gVerbose)
03283     cout << "Clearing v1 ..." << endl;
03284   v1.Zero();
03285   ok &= VerifyVectorValue(v1,0.0,gVerbose,EPSILON);
03286 
03287   if (gVerbose)
03288     cout << "Comparing v1 with 0 ..." << endl;
03289   ok &= (v1 == 0) ? kTRUE : kFALSE;
03290 
03291   if (gVerbose)
03292     cout << "Writing a pattern " << pattern << " by assigning to v(i)..." << endl;
03293   {
03294     for (Int_t i = v.GetLwb(); i <= v.GetUpb(); i++)
03295       v(i) = pattern;
03296     ok &= VerifyVectorValue(v,pattern,gVerbose,EPSILON);
03297   }
03298 
03299   if (gVerbose)
03300     cout << "Writing the pattern by assigning to v1 as a whole ..." << endl;
03301   v1 = pattern;
03302   ok &= VerifyVectorValue(v1,pattern,gVerbose,EPSILON);
03303 
03304   if (gVerbose)
03305     cout << "Comparing v and v1 ..." << endl;
03306   ok &= (v == v1) ? kTRUE : kFALSE;
03307   if (gVerbose)
03308     cout << "Comparing (v=0) and v1 ..." << endl;
03309   ok &= (!(v.Zero() == v1)) ? kTRUE : kFALSE;
03310 
03311   if (gVerbose)
03312     cout << "\nClear v and add the pattern" << endl;
03313   v.Zero();
03314   v += pattern;
03315   ok &= VerifyVectorValue(v,pattern,gVerbose,EPSILON);
03316   if (gVerbose)
03317     cout << "   add the doubled pattern with the negative sign" << endl;
03318   v += -2*pattern;
03319   ok &= VerifyVectorValue(v,-pattern,gVerbose,EPSILON);
03320   if (gVerbose)
03321     cout << "   subtract the trippled pattern with the negative sign" << endl;
03322   v -= -3*pattern;
03323   ok &= VerifyVectorValue(v,2*pattern,gVerbose,EPSILON);
03324 
03325   if (gVerbose)
03326     cout << "\nVerify comparison operations" << endl;
03327   v = pattern;
03328   ok &= ( v == pattern && !(v != pattern) && v >= pattern && v <= pattern ) ? kTRUE : kFALSE;
03329   ok &= ( v > 0 && v >= 0 ) ? kTRUE : kFALSE;
03330   ok &= ( v > -pattern && v >= -pattern ) ? kTRUE : kFALSE;
03331   ok &= ( v < pattern+1 && v <= pattern+1 ) ? kTRUE : kFALSE;
03332   v(v.GetUpb()) += 1;
03333   ok &= ( !(v==pattern)      && !(v != pattern)  && v != pattern-1 ) ? kTRUE : kFALSE;
03334   ok &= ( v >= pattern       && !(v > pattern)   && !(v >= pattern+1) ) ? kTRUE : kFALSE;
03335   ok &= ( v <= pattern+1.001 && !(v < pattern+1) && !(v <= pattern) ) ? kTRUE : kFALSE;
03336 
03337   if (gVerbose)
03338     cout << "\nAssign 2*pattern to v by repeating additions" << endl;
03339   v = 0; v += pattern; v += pattern;
03340   if (gVerbose)
03341     cout << "Assign 2*pattern to v1 by multiplying by two" << endl;
03342   v1 = pattern; v1 *= 2;
03343   ok &= VerifyVectorValue(v1,2*pattern,gVerbose,EPSILON);
03344   ok &= ( v == v1 ) ? kTRUE : kFALSE;
03345   if (gVerbose)
03346     cout << "Multiply v1 by one half returning it to the 1*pattern" << endl;
03347   v1 *= 1/2.;
03348   ok &= VerifyVectorValue(v1,pattern,gVerbose,EPSILON);
03349 
03350   if (gVerbose)
03351     cout << "\nAssign -pattern to v and v1" << endl;
03352   v.Zero(); v -= pattern; v1 = -pattern;
03353   ok &= VerifyVectorValue(v,-pattern,gVerbose,EPSILON);
03354   ok &= ( v == v1 ) ? kTRUE : kFALSE;
03355   if (gVerbose)
03356     cout << "v = sqrt(sqr(v)); v1 = abs(v1); Now v and v1 have to be the same" << endl;
03357   v.Sqr();
03358   ok &= VerifyVectorValue(v,pattern*pattern,gVerbose,EPSILON);
03359   v.Sqrt();
03360   ok &= VerifyVectorValue(v,pattern,gVerbose,EPSILON);
03361   v1.Abs();
03362   ok &= VerifyVectorValue(v1,pattern,gVerbose,EPSILON);
03363   ok &= ( v == v1 ) ? kTRUE : kFALSE;
03364 
03365   {
03366     if (gVerbose)
03367       cout << "\nCheck out to see that sin^2(x) + cos^2(x) = 1" << endl;
03368     for (Int_t i = v.GetLwb(); i <= v.GetUpb(); i++)
03369       v(i) = 2*TMath::Pi()/v.GetNoElements()*i;
03370 #ifndef __CINT__
03371     SinAction s;
03372     v.Apply(s);
03373     CosAction c(v.GetNoElements());
03374     v1.Apply(c);
03375 #else
03376     for (Int_t i = v.GetLwb(); i <= v.GetUpb(); i++) {
03377       v(i)  = TMath::Sin(v(i));
03378       v1(i) = TMath::Cos(2*TMath::Pi()/v1.GetNrows()*i);
03379     }
03380 #endif
03381     TVectorD v2 = v;
03382     TVectorD v3 = v1;
03383     v.Sqr();
03384     v1.Sqr();
03385     v += v1;
03386     ok &= VerifyVectorValue(v,1.,gVerbose,EPSILON);
03387   }
03388 
03389   if (gVerbose)
03390     cout << "\nVerify constructor with initialization" << endl;
03391 #ifndef __CINT__
03392   TVectorD vi(0,4,0.0,1.0,2.0,3.0,4.0,"END");
03393 #else
03394   Double_t vval[] = {0.0,1.0,2.0,3.0,4.0};
03395   TVectorD vi(5,vval);
03396 #endif
03397   TVectorD vit(5);
03398   {
03399     for (Int_t i = vit.GetLwb(); i <= vit.GetUpb(); i++)
03400       vit(i) = Double_t(i);
03401     ok &= VerifyVectorIdentity(vi,vit,gVerbose,EPSILON);
03402   }
03403 
03404   if (gVerbose)
03405     cout << "\nDone\n" << endl;
03406   StatusPrint(2,"Uniform vector operations",ok);
03407 }
03408 
03409 //
03410 //------------------------------------------------------------------------
03411 //                 Test binary vector operations
03412 //
03413 void vstress_binary_op(Int_t vsize)
03414 {
03415   if (gVerbose)
03416     cout << "\n---> Test Binary Vector operations" << endl;
03417 
03418   Bool_t ok = kTRUE;
03419   const Double_t pattern = TMath::Pi();
03420 
03421   const Double_t epsilon = EPSILON*vsize/10;
03422 
03423   TVectorD v(2,vsize+1);
03424   TVectorD v1(v);
03425 
03426   if (gVerbose)
03427     cout << "\nVerify assignment of a vector to the vector" << endl;
03428   v = pattern;
03429   v1.Zero();
03430   v1 = v;
03431   ok &= VerifyVectorValue(v1,pattern,gVerbose,EPSILON);
03432   ok &= ( v1 == v ) ? kTRUE : kFALSE;
03433 
03434   if (gVerbose)
03435     cout << "\nAdding one vector to itself, uniform pattern " << pattern << endl;
03436   v.Zero(); v = pattern;
03437   v1 = v; v1 += v1;
03438   ok &= VerifyVectorValue(v1,2*pattern,gVerbose,EPSILON);
03439   if (gVerbose)
03440     cout << "  subtracting two vectors ..." << endl;
03441   v1 -= v;
03442   ok &= VerifyVectorValue(v1,pattern,gVerbose,EPSILON);
03443   if (gVerbose)
03444     cout << "  subtracting the vector from itself" << endl;
03445   v1 -= v1;
03446   ok &= VerifyVectorValue(v1,0.,gVerbose,EPSILON);
03447   if (gVerbose)
03448     cout << "  adding two vectors together" << endl;
03449   v1 += v;
03450   ok &= VerifyVectorValue(v1,pattern,gVerbose,EPSILON);
03451 
03452   TVectorD vp(2,vsize+1);
03453   {
03454     for (Int_t i = vp.GetLwb(); i <= vp.GetUpb(); i++)
03455       vp(i) = (i-vp.GetNoElements()/2.)*pattern;
03456   }
03457 
03458   if (gVerbose) {
03459     cout << "\nArithmetic operations on vectors with not the same elements" << endl;
03460     cout << "   adding vp to the zero vector..." << endl;
03461   }
03462   v.Zero();
03463   ok &= ( v == 0.0 ) ? kTRUE : kFALSE;
03464   v += vp;
03465   ok &= VerifyVectorIdentity(v,vp,gVerbose,epsilon);
03466   v1 = v;
03467   if (gVerbose)
03468     cout << "   making v = 3*vp and v1 = 3*vp, via add() and succesive mult" << endl;
03469   Add(v,2.,vp);
03470   v1 += v1; v1 += vp;
03471   ok &= VerifyVectorIdentity(v,v1,gVerbose,epsilon);
03472   if (gVerbose)
03473     cout << "   clear both v and v1, by subtracting from itself and via add()" << endl;
03474   v1 -= v1;
03475   Add(v,-3.,vp);
03476   ok &= VerifyVectorIdentity(v,v1,gVerbose,epsilon);
03477 
03478   if (gVerbose) {
03479     cout << "\nTesting element-by-element multiplications and divisions" << endl;
03480     cout << "   squaring each element with sqr() and via multiplication" << endl;
03481   }
03482   v = vp; v1 = vp;
03483   v.Sqr();
03484   ElementMult(v1,v1);
03485   ok &= VerifyVectorIdentity(v,v1,gVerbose,epsilon);
03486   if (gVerbose)
03487     cout << "   compare (v = pattern^2)/pattern with pattern" << endl;
03488   v = pattern; v1 = pattern;
03489   v.Sqr();
03490   ElementDiv(v,v1);
03491   ok &= VerifyVectorValue(v,pattern,gVerbose,epsilon);
03492   if (gVerbose)
03493    Compare(v1,v);
03494 
03495   if (gVerbose)
03496     cout << "\nDone\n" << endl;
03497   StatusPrint(3,"Binary vector element-by-element operations",ok);
03498 }
03499 
03500 //
03501 //------------------------------------------------------------------------
03502 //               Verify the norm calculation
03503 //
03504 void vstress_norms(Int_t vsize)
03505 {
03506   if (gVerbose)
03507     cout << "\n---> Verify norm calculations" << endl;
03508 
03509   Bool_t ok = kTRUE;
03510   const Double_t pattern = 10.25;
03511 
03512   if ( vsize % 2 == 1 )
03513     Fatal("vstress_norms", "size of the vector to test must be even for this test\n");
03514 
03515   TVectorD v(vsize);
03516   TVectorD v1(v);
03517 
03518   if (gVerbose)
03519     cout << "\nAssign " << pattern << " to all the elements and check norms" << endl;
03520   v = pattern;
03521   if (gVerbose)
03522     cout << "  1. norm should be pattern*no_elems" << endl;
03523   ok &= ( v.Norm1() == pattern*v.GetNoElements() ) ? kTRUE : kFALSE;
03524   if (gVerbose)
03525     cout << "  Square of the 2. norm has got to be pattern^2 * no_elems" << endl;
03526   ok &= ( v.Norm2Sqr() == (pattern*pattern)*v.GetNoElements() ) ? kTRUE : kFALSE;
03527   if (gVerbose)
03528     cout << "  Inf norm should be pattern itself" << endl;
03529   ok &= ( v.NormInf() == pattern ) ? kTRUE : kFALSE;
03530   if (gVerbose)
03531     cout << "  Scalar product of vector by itself is the sqr(2. vector norm)" << endl;
03532   ok &= ( v.Norm2Sqr() == v*v ) ? kTRUE : kFALSE;
03533 
03534   Double_t ap_step = 1;
03535   Double_t ap_a0   = -pattern;
03536   Int_t n = v.GetNoElements();
03537   if (gVerbose) {
03538     cout << "\nAssign the arithm progression with 1. term " << ap_a0 <<
03539             "\nand the difference " << ap_step << endl;
03540   }
03541   {
03542     for (Int_t i = v.GetLwb(); i <= v.GetUpb(); i++)
03543       v(i) = (i-v.GetLwb())*ap_step + ap_a0;
03544   }
03545   Int_t l = TMath::Min(TMath::Max((int)TMath::Ceil(-ap_a0/ap_step),0),n);
03546   Double_t norm = (2*ap_a0+(l+n-1)*ap_step)/2*(n-l) +
03547                   (-2*ap_a0-(l-1)*ap_step)/2*l;
03548   if (gVerbose)
03549     cout << "  1. norm should be " << norm << endl;
03550   ok &= ( v.Norm1() == norm ) ? kTRUE : kFALSE;
03551   norm = n*( (ap_a0*ap_a0)+ap_a0*ap_step*(n-1)+(ap_step*ap_step)*(n-1)*(2*n-1)/6);
03552   if (gVerbose) {
03553     cout << "  Square of the 2. norm has got to be "
03554             "n*[ a0^2 + a0*q*(n-1) + q^2/6*(n-1)*(2n-1) ], or " << norm << endl;
03555   }
03556   ok &= ( TMath::Abs( (v.Norm2Sqr()-norm)/norm ) < EPSILON ) ? kTRUE : kFALSE;
03557 
03558   norm = TMath::Max(TMath::Abs(v(v.GetLwb())),TMath::Abs(v(v.GetUpb())));
03559   if (gVerbose)
03560     cout << "  Inf norm should be max(abs(a0),abs(a0+(n-1)*q)), ie " << norm << endl;
03561   ok &= ( v.NormInf() == norm ) ? kTRUE : kFALSE;
03562   if (gVerbose)
03563     cout << "  Scalar product of vector by itself is the sqr(2. vector norm)" << endl;
03564   ok &= ( v.Norm2Sqr() == v*v ) ? kTRUE : kFALSE;
03565 
03566 #if 0
03567   v1.Zero();
03568   Compare(v,v1);  // they are not equal (of course)
03569 #endif
03570 
03571   if (gVerbose)
03572     cout << "\nConstruct v1 to be orthogonal to v as v(n), -v(n-1), v(n-2)..." << endl;
03573   {
03574     for (Int_t i = 0; i < v1.GetNoElements(); i++)
03575       v1(i+v1.GetLwb()) = v(v.GetUpb()-i) * ( i % 2 == 1 ? -1 : 1 );
03576   }
03577   if (gVerbose)
03578     cout << "||v1|| has got to be equal ||v|| regardless of the norm def" << endl;
03579   ok &= ( v1.Norm1()    == v.Norm1() ) ? kTRUE : kFALSE;
03580   ok &= ( v1.Norm2Sqr() == v.Norm2Sqr() ) ? kTRUE : kFALSE;
03581   ok &= ( v1.NormInf()  == v.NormInf() ) ? kTRUE : kFALSE;
03582   if (gVerbose)
03583     cout << "But the scalar product has to be zero" << endl;
03584   ok &= ( v1 * v == 0 ) ? kTRUE : kFALSE;
03585 
03586   if (gVerbose)
03587     cout << "\nDone\n" << endl;
03588   StatusPrint(4,"Vector Norms",ok);
03589 }
03590 
03591 //
03592 //------------------------------------------------------------------------
03593 //           Test operations with vectors and matrix slices
03594 //
03595 void vstress_matrix_slices(Int_t vsize)
03596 {
03597   if (gVerbose)
03598     cout << "\n---> Test operations with vectors and matrix slices" << endl;
03599 
03600   Bool_t ok = kTRUE;
03601   const Double_t pattern = 8.625;
03602 
03603   TVectorD vc(0,vsize);
03604   TVectorD vr(0,vsize+1);
03605   TMatrixD m(0,vsize,0,vsize+1);
03606 
03607   Int_t i,j;
03608   if (gVerbose)
03609     cout << "\nCheck modifying the matrix column-by-column" << endl;
03610   m = pattern;
03611   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03612   for (i = m.GetColLwb(); i <= m.GetColUpb(); i++) {
03613     TMatrixDColumn(m,i) = pattern-1;
03614     ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03615     TMatrixDColumn(m,i) *= 2;
03616     vc = TMatrixDColumn(m,i);
03617     ok &= VerifyVectorValue(vc,2*(pattern-1),gVerbose);
03618     vc = TMatrixDColumn(m,i+1 > m.GetColUpb() ? m.GetColLwb() : i+1);
03619     ok &= VerifyVectorValue(vc,pattern,gVerbose,EPSILON);
03620     TMatrixDColumn(m,i) *= 0.5;
03621     TMatrixDColumn(m,i) += 1;
03622     ok &= ( m == pattern ) ? kTRUE : kFALSE;
03623   }
03624 
03625   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03626   for (i = m.GetColLwb(); i <= m.GetColUpb(); i++) {
03627     vc = pattern+1;
03628     TMatrixDColumn(m,i) = vc;
03629     ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03630     {
03631       TMatrixDColumn mc(m,i);
03632       for (j = m.GetRowLwb(); j <= m.GetRowUpb(); j++)
03633         mc(j) *= 4;
03634     }
03635     vc = TMatrixDColumn(m,i);
03636     ok &= VerifyVectorValue(vc,4*(pattern+1),gVerbose,EPSILON);
03637     TMatrixDColumn(m,i) *= 0.25;
03638     TMatrixDColumn(m,i) += -1;
03639     vc = TMatrixDColumn(m,i);
03640     ok &= VerifyVectorValue(vc,pattern,gVerbose,EPSILON);
03641     ok &= ( m == pattern ) ? kTRUE : kFALSE;
03642   }
03643 
03644   if (gVerbose)
03645     cout << "\nCheck modifying the matrix row-by-row" << endl;
03646   m = pattern;
03647   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03648   for (i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
03649     TMatrixDRow(m,i) = pattern+2;
03650     ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03651     vr = TMatrixDRow(m,i);
03652     ok &= VerifyVectorValue(vr,pattern+2,gVerbose,EPSILON);
03653     vr = TMatrixDRow(m,i+1 > m.GetRowUpb() ? m.GetRowLwb() : i+1);
03654     ok &= VerifyVectorValue(vr,pattern,gVerbose,EPSILON);
03655     TMatrixDRow(m,i) += -2;
03656     ok &= ( m == pattern ) ? kTRUE : kFALSE;
03657   }
03658 
03659   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03660   for (i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
03661     vr = pattern-2;
03662     TMatrixDRow(m,i) = vr;
03663     ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03664     {
03665       TMatrixDRow mr(m,i);
03666       for (j = m.GetColLwb(); j <= m.GetColUpb(); j++)
03667         mr(j) *= 8;
03668     }
03669     vr = TMatrixDRow(m,i);
03670     ok &= VerifyVectorValue(vr,8*(pattern-2),gVerbose,EPSILON);
03671     TMatrixDRow(m,i) *= 1./8;
03672     TMatrixDRow(m,i) += 2;
03673     vr = TMatrixDRow(m,i);
03674     ok &= VerifyVectorValue(vr,pattern,gVerbose,EPSILON);
03675     ok &= ( m == pattern ) ? kTRUE : kFALSE;
03676   }
03677 
03678   if (gVerbose)
03679     cout << "\nCheck modifying the matrix diagonal" << endl;
03680   m = pattern;
03681   TMatrixDDiag td = m;
03682   td = pattern-3;
03683   ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03684   vc = TMatrixDDiag(m);
03685   ok &= VerifyVectorValue(vc,pattern-3,gVerbose,EPSILON);
03686   td += 3;
03687   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03688   vc = pattern+3;
03689   td = vc;
03690   ok &= ( !( m == pattern ) && !( m != pattern ) ) ? kTRUE : kFALSE;
03691   {
03692     TMatrixDDiag md(m);
03693     for (j = 0; j < md.GetNdiags(); j++)
03694       md(j) /= 1.5;
03695   }
03696   vc = TMatrixDDiag(m);
03697   ok &= VerifyVectorValue(vc,(pattern+3)/1.5,gVerbose,EPSILON);
03698   TMatrixDDiag(m) *= 1.5;
03699   TMatrixDDiag(m) += -3;
03700   vc = TMatrixDDiag(m);
03701   ok &= VerifyVectorValue(vc,pattern,gVerbose,EPSILON);
03702   ok &= ( m == pattern ) ? kTRUE : kFALSE;
03703 
03704   if (gVerbose) {
03705     cout << "\nCheck out to see that multiplying by diagonal is column-wise"
03706             "\nmatrix multiplication" << endl;
03707   }
03708   TMatrixD mm(m);
03709   TMatrixD m1(m.GetRowLwb(),TMath::Max(m.GetRowUpb(),m.GetColUpb()),
03710               m.GetColLwb(),TMath::Max(m.GetRowUpb(),m.GetColUpb()));
03711   TVectorD vc1(vc),vc2(vc);
03712   for (i = m.GetRowLwb(); i < m.GetRowUpb(); i++)
03713     TMatrixDRow(m,i) = pattern+i;      // Make a multiplicand
03714   mm = m;                          // Save it
03715 
03716   m1 = pattern+10;
03717   for (i = vr.GetLwb(); i <= vr.GetUpb(); i++)
03718     vr(i) = i+2;
03719   TMatrixDDiag td2 = m1;
03720   td2 = vr;
03721   ok &= ( !(m1 == pattern+10) ) ? kTRUE : kFALSE;
03722 
03723   m *= TMatrixDDiag(m1);
03724   for (i = m.GetColLwb(); i <= m.GetColUpb(); i++) {
03725     vc1 = TMatrixDColumn(mm,i);
03726     vc1 *= vr(i);                    // Do a column-wise multiplication
03727     vc2 = TMatrixDColumn(m,i);
03728     ok &= VerifyVectorIdentity(vc1,vc2,gVerbose,EPSILON);
03729   }
03730 
03731   if (gVerbose)
03732     cout << "\nDone\n" << endl;
03733   StatusPrint(5,"Matrix Slices to Vectors",ok);
03734 }
03735 
03736 //
03737 //------------------------------------------------------------------------
03738 //           Test vector I/O
03739 //
03740 void vstress_vector_io()
03741 {
03742   if (gVerbose)
03743     cout << "\n---> Test vector I/O" << endl;
03744 
03745   Bool_t ok = kTRUE;
03746   const Double_t pattern = TMath::Pi();
03747 
03748   TFile *f = new TFile("vvector.root","RECREATE");
03749 
03750   Char_t name[80];
03751   Int_t iloop = gNrLoop;
03752   while (iloop >= 0) {
03753     const Int_t msize = gSizeA[iloop];
03754 
03755     const Int_t verbose = (gVerbose && iloop==gNrLoop);
03756 
03757     TVectorD v(msize);
03758     v = pattern;
03759 
03760     Double_t *pattern_array = new Double_t[msize];
03761     for (Int_t i = 0; i < msize; i++)
03762       pattern_array[i] = pattern;
03763     TVectorD va;
03764     va.Use(msize,pattern_array);
03765 
03766     if (verbose)
03767       cout << "\nWrite vector v to database" << endl;
03768 
03769     sprintf(name,"v_%d",msize);
03770     v.Write(name);
03771     sprintf(name,"va_%d",msize);
03772     va.Write(name);
03773 
03774     delete [] pattern_array;
03775 
03776     iloop--;
03777   }
03778 
03779   if (gVerbose)
03780     cout << "\nClose database" << endl;
03781   delete f;
03782 
03783   if (gVerbose)
03784     cout << "\nOpen database in read-only mode and read vector" << endl;
03785   TFile *f1 = new TFile("vvector.root");
03786 
03787   iloop = gNrLoop;
03788   while (iloop >= 0) {
03789     const Int_t msize = gSizeA[iloop];
03790 
03791     const Int_t verbose = (gVerbose && iloop==gNrLoop);
03792 
03793     TVectorD v(msize);
03794     v = pattern;
03795 
03796     sprintf(name,"v_%d",msize);
03797     TVectorD *vr  = (TVectorD*) f1->Get(name);
03798     sprintf(name,"va_%d",msize);
03799     TVectorD *var = (TVectorD*) f1->Get(name);
03800 
03801     if (verbose)
03802       cout << "\nRead vector should be same as original still in memory" << endl;
03803     ok &= ((*vr) == v)  ? kTRUE : kFALSE;
03804     ok &= ((*var) == v) ? kTRUE : kFALSE;
03805 
03806     iloop--;
03807   }
03808 
03809   delete f1;
03810 
03811   if (gVerbose)
03812     cout << "\nDone\n" << endl;
03813   StatusPrint(6,"Vector Persistence",ok);
03814 }
03815 
03816 Bool_t test_svd_expansion(const TMatrixD &A)
03817 {
03818   if (gVerbose)
03819     cout << "\n\nSVD-decompose matrix A and check if we can compose it back\n" <<endl;
03820 
03821   Bool_t ok = kTRUE;
03822 
03823   TDecompSVD svd(A);
03824   if (gVerbose) {
03825     cout << "left factor U" <<endl;
03826     svd.GetU().Print();
03827     cout << "Vector of Singular values" <<endl;
03828     svd.GetSig().Print();
03829     cout << "right factor V" <<endl;
03830     svd.GetV().Print();
03831   }
03832 
03833   {
03834     if (gVerbose)
03835       cout << "\tchecking that U is orthogonal indeed, i.e., U'U=E and UU'=E" <<endl;
03836     const Int_t nRows = svd.GetU().GetNrows();
03837     const Int_t nCols = svd.GetU().GetNcols();
03838     TMatrixD E1(nRows,nRows); E1.UnitMatrix();
03839     TMatrixD E2(nCols,nCols); E2.UnitMatrix();
03840     TMatrixD ut(TMatrixD::kTransposed,svd.GetU());
03841     ok &= VerifyMatrixIdentity(ut * svd.GetU(),E2,gVerbose,100*EPSILON);
03842     ok &= VerifyMatrixIdentity(svd.GetU() * ut,E1,gVerbose,100*EPSILON);
03843   }
03844 
03845   {
03846     if (gVerbose)
03847       cout << "\tchecking that V is orthogonal indeed, i.e., V'V=E and VV'=E" <<endl;
03848     const Int_t nRows = svd.GetV().GetNrows();
03849     const Int_t nCols = svd.GetV().GetNcols();
03850     TMatrixD E1(nRows,nRows); E1.UnitMatrix();
03851     TMatrixD E2(nCols,nCols); E2.UnitMatrix();
03852     TMatrixD vt(TMatrixD::kTransposed,svd.GetV());
03853     ok &= VerifyMatrixIdentity(vt * svd.GetV(),E2,gVerbose,100*EPSILON);
03854     ok &= VerifyMatrixIdentity(svd.GetV() * vt,E1,gVerbose,100*EPSILON);
03855   }
03856 
03857   {
03858     if (gVerbose)
03859       cout << "\tchecking that U*Sig*V' is indeed A" <<endl;
03860     const Int_t nRows = svd.GetU().GetNrows();
03861     const Int_t nCols = svd.GetV().GetNcols();
03862     TMatrixD s(nRows,nCols);
03863     TMatrixDDiag diag(s); diag = svd.GetSig();
03864     TMatrixD vt(TMatrixD::kTransposed,svd.GetV());
03865     TMatrixD tmp = s * vt;
03866     ok &= VerifyMatrixIdentity(A,svd.GetU() * tmp,gVerbose,100*EPSILON);
03867     if (gVerbose) {
03868       cout << "U*Sig*V'" <<endl;
03869       (svd.GetU()*tmp).Print();
03870     }
03871   }
03872 
03873   return ok;
03874 }
03875 
03876 #ifndef __CINT__
03877 // Make a matrix from an array (read it row-by-row)
03878 class MakeMatrix : public TMatrixDLazy {
03879   const Double_t *array;
03880         Int_t     no_elems;
03881   void FillIn(TMatrixD& m) const {
03882     R__ASSERT( m.GetNrows() * m.GetNcols() == no_elems );
03883     const Double_t *ap = array;
03884           Double_t *mp = m.GetMatrixArray();
03885     for (Int_t i = 0; i < no_elems; i++)
03886       *mp++ = *ap++;
03887   }
03888 
03889 public:
03890   MakeMatrix(Int_t nrows,Int_t ncols,
03891              const Double_t *_array,Int_t _no_elems)
03892     :TMatrixDLazy(nrows,ncols), array(_array), no_elems(_no_elems) {}
03893   MakeMatrix(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,
03894              const Double_t *_array,Int_t _no_elems)
03895     : TMatrixDLazy(row_lwb,row_upb,col_lwb,col_upb),
03896       array(_array), no_elems(_no_elems) {}
03897 };
03898 #else
03899 TMatrixD MakeMatrix(Int_t nrows,Int_t ncols,
03900                     const Double_t *_array,Int_t _no_elems)
03901 {
03902   TMatrixD m(nrows,ncols,_array);
03903   return m;
03904 }
03905 #endif
03906 
03907 void astress_decomp()
03908 {
03909   Bool_t ok = kTRUE;
03910 
03911   {
03912     if (gVerbose)
03913       cout << "\nBrandt example page 503\n" <<endl;
03914 
03915     Double_t array0[] = { -2,1,0,0, 2,1,0,0, 0,0,0,0, 0,0,0,0 };
03916     ok &= test_svd_expansion(MakeMatrix(4,4,array0,sizeof(array0)/sizeof(array0[0])));
03917   }
03918 
03919   {
03920     if (gVerbose)
03921       cout << "\nRotated by PI/2 Matrix Diag(1,4,9)\n" <<endl;
03922 
03923     Double_t array1[] = {0,-4,0,  1,0,0,  0,0,9 };
03924     ok &= test_svd_expansion(MakeMatrix(3,3,array1,sizeof(array1)/sizeof(array1[0])));
03925   }
03926 
03927   {
03928     if (gVerbose)
03929       cout << "\nExample from the Forsythe, Malcolm, Moler's book\n" <<endl;
03930 
03931     Double_t array2[] =
03932          { 1,6,11, 2,7,12, 3,8,13, 4,9,14, 5,10,15};
03933     ok &= test_svd_expansion(MakeMatrix(5,3,array2,sizeof(array2)/sizeof(array2[0])));
03934   }
03935 
03936   {
03937     if (gVerbose)
03938       cout << "\nExample from the Wilkinson, Reinsch's book\n" <<
03939               "Singular numbers are 0, 19.5959, 20, 0, 35.3270\n" <<endl;
03940 
03941     Double_t array3[] =
03942         { 22, 10,  2,   3,  7,    14,  7, 10,  0,  8,
03943           -1, 13, -1, -11,  3,    -3, -2, 13, -2,  4,
03944            9,  8,  1,  -2,  4,     9,  1, -7,  5, -1,
03945            2, -6,  6,   5,  1,     4,  5,  0, -2,  2 };
03946     ok &= test_svd_expansion(MakeMatrix(8,5,array3,sizeof(array3)/sizeof(array3[0])));
03947   }
03948 
03949   {
03950     if (gVerbose)
03951       cout << "\nExample from the Wilkinson, Reinsch's book\n" <<
03952               "Ordered singular numbers are Sig[21-k] = sqrt(k*(k-1))\n" <<endl;
03953     TMatrixD A(21,20);
03954     for (Int_t irow = A.GetRowLwb(); irow <= A.GetRowUpb(); irow++)
03955       for (Int_t icol = A.GetColLwb(); icol <= A.GetColUpb(); icol++)
03956         A(irow,icol) = (irow>icol ? 0 : ((irow==icol) ? 20-icol : -1));
03957 
03958     ok &= test_svd_expansion(A);
03959   }
03960 
03961   if (0)
03962   {
03963     if (gVerbose) {
03964       cout << "\nTest by W. Meier <wmeier@manu.com> to catch an obscure "
03965            << "bug in QR\n" <<endl;
03966       cout << "expect singular values to be\n"
03967            << "1.4666e-024   1.828427   3.828427   4.366725  7.932951\n" <<endl;
03968     }
03969 
03970     Double_t array4[] =
03971         {  1,  2,  0,  0,  0,
03972            0,  2,  3,  0,  0,
03973            0,  0,  0,  4,  0,
03974            0,  0,  0,  4,  5,
03975            0,  0,  0,  0,  5 };
03976     ok &= test_svd_expansion(MakeMatrix(5,5,array4,sizeof(array4)/sizeof(array4[0])));
03977   }
03978 
03979   {
03980     const TMatrixD m1 = THilbertMatrixD(5,5);
03981     TDecompLU lu(m1);
03982     ok &= VerifyMatrixIdentity(lu.GetMatrix(),m1,gVerbose,100*EPSILON);
03983   }
03984 
03985   {
03986     const TMatrixD m2 = THilbertMatrixD(5,5);
03987     const TMatrixDSym mtm(TMatrixDSym::kAtA,m2);
03988     TDecompChol chol(mtm);
03989     ok &= VerifyMatrixIdentity(chol.GetMatrix(),mtm,gVerbose,100*EPSILON);
03990   }
03991 
03992   if (gVerbose)
03993     cout << "\nDone" <<endl;
03994 
03995   StatusPrint(1,"Decomposition / Reconstruction",ok);
03996 }
03997 
03998 void astress_lineqn()
03999 {
04000   if (gVerbose)
04001     cout << "\nSolve Ax=b where A is a Hilbert matrix and b(i) = sum_j Aij\n" <<endl;
04002 
04003   Bool_t ok = kTRUE;
04004 
04005   Int_t iloop = gNrLoop;
04006   Int_t nr    = 0;
04007 
04008   while (iloop >= 0) {
04009     const Int_t msize = gSizeA[iloop];
04010 
04011     const Int_t verbose = (gVerbose && nr==0 && iloop==gNrLoop);
04012 
04013     if (verbose)
04014       cout << "\nSolve Ax=b for size = " << msize <<endl;
04015 
04016     // Since The Hilbert matrix is accuracy "challenged", I will use a diagonaly
04017     // dominant one fore sizes > 100, otherwise the verification might fail
04018 
04019     TMatrixDSym m1 = THilbertMatrixDSym(-1,msize-2);
04020     TMatrixDDiag diag1(m1);
04021     diag1 += 1.;
04022 
04023     TVectorD rowsum1(-1,msize-2); rowsum1.Zero();
04024     TVectorD colsum1(-1,msize-2); colsum1.Zero();
04025     for (Int_t irow = m1.GetRowLwb(); irow <= m1.GetColUpb(); irow++) {
04026       for (Int_t icol = m1.GetColLwb(); icol <= m1.GetColUpb(); icol++) {
04027         rowsum1(irow) += m1(irow,icol);
04028         colsum1(icol) += m1(irow,icol);
04029       }
04030     }
04031 
04032     TMatrixDSym m2 = THilbertMatrixDSym(msize);
04033     TMatrixDDiag diag2(m2);
04034     diag2 += 1.;
04035 
04036     TVectorD rowsum2(msize); rowsum2.Zero();
04037     TVectorD colsum2(msize); colsum2.Zero();
04038     for (Int_t irow = m2.GetRowLwb(); irow <= m2.GetColUpb(); irow++) {
04039       for (Int_t icol = m2.GetColLwb(); icol <= m2.GetColUpb(); icol++) {
04040         rowsum2(irow) += m2(irow,icol);
04041         colsum2(icol) += m2(irow,icol);
04042       }
04043     }
04044 
04045     TVectorD b1(-1,msize-2);
04046     TVectorD b2(msize);
04047     {
04048       TDecompLU lu(m1,1.0e-20);
04049       b1 = rowsum1;
04050       lu.Solve(b1);
04051       if (msize < 10)
04052         ok &= VerifyVectorValue(b1,1.0,verbose,msize*EPSILON);
04053       b1 = colsum1;
04054       lu.TransSolve(b1);
04055       if (msize < 10)
04056         ok &= VerifyVectorValue(b1,1.0,verbose,msize*EPSILON);
04057     }
04058 
04059     {
04060       TDecompChol chol(m1,1.0e-20);
04061       b1 = rowsum1;
04062       chol.Solve(b1);
04063       if (msize < 10)
04064         ok &= VerifyVectorValue(b1,1.0,verbose,msize*EPSILON);
04065       b1 = colsum1;
04066       chol.TransSolve(b1);
04067       if (msize < 10)
04068         ok &= VerifyVectorValue(b1,1.0,verbose,msize*EPSILON);
04069     }
04070 
04071     {
04072       TDecompQRH qrh1(m1,1.0e-20);
04073       b1 = rowsum1;
04074       qrh1.Solve(b1);
04075       if (msize < 10)
04076         ok &= VerifyVectorValue(b1,1.0,verbose,msize*EPSILON);
04077 
04078       TDecompQRH qrh2(m2,1.0e-20);
04079       b2 = colsum2;
04080       qrh2.TransSolve(b2);
04081       if (msize < 10)
04082         ok &= VerifyVectorValue(b2,1.0,verbose,msize*EPSILON);
04083     }
04084 
04085     {
04086       TDecompSVD svd1(m1);
04087       b1 = rowsum1;
04088       svd1.Solve(b1);
04089       if (msize < 10)
04090         ok &= VerifyVectorValue(b1,1.0,verbose,msize*EPSILON);
04091 
04092       TDecompSVD svd2(m2);
04093       b2 = colsum2;
04094       svd2.TransSolve(b2);
04095       if (msize < 10)
04096         ok &= VerifyVectorValue(b2,1.0,verbose,msize*EPSILON);
04097     }
04098 
04099     {
04100       TDecompBK bk(m1,1.0e-20);
04101       b1 = rowsum1;
04102       bk.Solve(b1);
04103       if (msize < 10)
04104         ok &= VerifyVectorValue(b1,1.0,verbose,msize*EPSILON);
04105       b1 = colsum1;
04106       bk.TransSolve(b1);
04107       if (msize < 10)
04108         ok &= VerifyVectorValue(b1,1.0,verbose,msize*EPSILON);
04109     }
04110 
04111 #ifndef __CINT__
04112     if (nr >= Int_t(1.0e+5/msize/msize)) {
04113 #else
04114     if (nr >= Int_t(1.0e+3/msize/msize)) {
04115 #endif
04116       nr = 0;
04117       iloop--;
04118     } else
04119       nr++;
04120 
04121     if (!ok) {
04122       if (gVerbose)
04123         cout << "Linear Equations failed for size " << msize << endl;
04124       break;
04125     }
04126   }
04127 
04128   if (gVerbose)
04129     cout << "\nDone" <<endl;
04130 
04131   StatusPrint(2,"Linear Equations",ok);
04132 }
04133 
04134 void astress_pseudo()
04135 {
04136 // The pseudo-inverse of A is found by "inverting" the SVD of A.
04137 // To be more precise, we use SVD to solve the equation
04138 // AX=B where B is a unit matrix.
04139 //
04140 // After we compute the pseudo-inverse, we verify the Moore-Penrose
04141 // conditions: Matrix X is a pseudo-inverse of A iff
04142 //      AXA = A
04143 //      XAX = X
04144 //      XA = (XA)' (i.e., XA is symmetric)
04145 //      AX = (AX)' (i.e., AX is symmetric)
04146 
04147   Bool_t ok = kTRUE;
04148 
04149   // Allocate and fill matrix A
04150   enum {nrows = 4, ncols = 3};
04151 #ifndef __CINT__
04152   const Double_t A_data [nrows*ncols] =
04153 #else
04154   const Double_t A_data [12] =
04155 #endif
04156    {0, 0, 0,
04157     0, 0, 0,
04158     1, 1, 0,
04159     4, 3, 0};
04160   TMatrixD A(nrows,ncols,A_data);
04161 
04162   // Perform the SVD decomposition of the transposed matrix.
04163 
04164   TDecompSVD svd(A);
04165   if (gVerbose)
04166     cout << "\ncondition number " << svd.Condition() << endl;
04167 
04168   // Compute the inverse as a solution of A*Ainv = E
04169   TMatrixD Ainv(nrows,nrows); Ainv.UnitMatrix();
04170   svd.MultiSolve(Ainv);
04171   Ainv.ResizeTo(ncols,nrows);
04172   TMatrixD Ainv2(nrows,nrows);
04173   svd.Invert(Ainv2);
04174   Ainv2.ResizeTo(ncols,nrows);
04175   ok &= VerifyMatrixIdentity(Ainv,Ainv2,gVerbose,EPSILON);
04176 
04177   if (gVerbose) {
04178     cout << "\nChecking the Moore-Penrose conditions for the Ainv" << endl;
04179     cout << "\nVerify that Ainv * A * Ainv is Ainv" << endl;
04180   }
04181   ok &= VerifyMatrixIdentity(Ainv * A * Ainv, Ainv,gVerbose,EPSILON);
04182 
04183   if (gVerbose)
04184     cout << "\nVerify that A * Ainv * A is A" << endl;
04185   ok &= VerifyMatrixIdentity(A * Ainv * A, A,gVerbose,EPSILON);
04186 
04187   if (gVerbose)
04188     cout << "\nVerify that Ainv * A is symmetric" << endl;
04189   ok &= VerifyMatrixIdentity(Ainv * A, (Ainv*A).T(),gVerbose,EPSILON);
04190 
04191   if (gVerbose)
04192     cout << "\nVerify that A * Ainv is symmetric" << endl;
04193   ok &= VerifyMatrixIdentity(A * Ainv, (A*Ainv).T(),gVerbose,EPSILON);
04194 
04195   StatusPrint(3,"Pseudo-Inverse, Moore-Penrose",ok);
04196 }
04197 
04198 void astress_eigen(Int_t msize)
04199 {
04200   Bool_t ok = kTRUE;
04201 
04202   // Check :
04203   // 1.  the eigen values of M' * M are the same as the singular values
04204   //     squared of the SVD of M .
04205   // 2.  M' * M  x_i =  lambda_i x_i where x_i and lambda_i are the ith
04206   //     eigen - vector/value .
04207 
04208   const TMatrixD m = THilbertMatrixD(msize,msize);
04209 
04210   TDecompSVD svd(m);
04211   TVectorD sig = svd.GetSig(); sig.Sqr();
04212 
04213   // Symmetric matrix EigenVector algorithm
04214   TMatrixDSym mtm1(TMatrixDSym::kAtA,m);
04215   const TMatrixDSymEigen eigen1(mtm1);
04216   const TVectorD eigenVal1 = eigen1.GetEigenValues();
04217 
04218   ok &= VerifyVectorIdentity(sig,eigenVal1,gVerbose,EPSILON);
04219 
04220   // Check that the eigen vectors by comparing M'M x to lambda x
04221   const TMatrixD mtm1x = mtm1 * eigen1.GetEigenVectors();
04222   TMatrixD lam_x1 = eigen1.GetEigenVectors();
04223   lam_x1.NormByRow(eigen1.GetEigenValues(),"");
04224 
04225   ok &= VerifyMatrixIdentity(mtm1x,lam_x1,gVerbose,EPSILON);
04226 
04227   // General matrix EigenVector algorithm tested on symmetric matrix
04228   TMatrixD mtm2(m,TMatrixD::kTransposeMult,m);
04229   const TMatrixDEigen eigen2(mtm2);
04230   const TVectorD eigenVal2 = eigen2.GetEigenValuesRe();
04231 
04232   ok &= VerifyVectorIdentity(sig,eigenVal2,gVerbose,EPSILON);
04233 
04234   // Check that the eigen vectors by comparing M'M x to lambda x
04235   const TMatrixD mtm2x = mtm2 * eigen2.GetEigenVectors();
04236   TMatrixD lam_x2 = eigen2.GetEigenVectors();
04237   lam_x2.NormByRow(eigen2.GetEigenValuesRe(),"");
04238 
04239   ok &= VerifyMatrixIdentity(mtm2x,lam_x2,gVerbose,EPSILON);
04240 
04241   // The Imaginary part of the eigenvalues should be zero
04242   const TVectorD eigenValIm = eigen2.GetEigenValuesIm();
04243   TVectorD epsVec(msize); epsVec = EPSILON;
04244   ok &= VerifyVectorIdentity(epsVec,eigenValIm,gVerbose,EPSILON);
04245 
04246   StatusPrint(4,"Eigen - Values/Vectors",ok);
04247 }
04248 
04249 void astress_decomp_io(Int_t msize)
04250 {
04251 //
04252 //------------------------------------------------------------------------
04253 //           Test decomposition I/O
04254 //
04255   if (gVerbose)
04256     cout << "\n---> Test decomp I/O" << endl;
04257 
04258   Bool_t ok = kTRUE;
04259 
04260   const TMatrixDSym m = THilbertMatrixDSym(msize);
04261   TVectorD rowsum(msize); rowsum.Zero();
04262   TVectorD colsum(msize); colsum.Zero();
04263 
04264   for (Int_t irow = 0; irow < m.GetNrows(); irow++) {
04265     for (Int_t icol = 0; icol < m.GetNcols(); icol++) {
04266       rowsum(irow) += m(irow,icol);
04267       colsum(icol) += m(irow,icol);
04268     }
04269   }
04270 
04271   if (gVerbose)
04272     cout << "\nWrite decomp m to database" << endl;
04273 
04274   TFile *f = new TFile("vdecomp.root", "RECREATE");
04275 
04276   TDecompLU   lu(m,1.0e-20);
04277   TDecompQRH  qrh(m,1.0e-20);
04278   TDecompChol chol(m,1.0e-20);
04279   TDecompSVD  svd(m);
04280   TDecompBK   bk(m,1.0e-20);
04281 
04282   lu.Write("lu");
04283   qrh.Write("qrh");
04284   chol.Write("chol");
04285   svd.Write("svd");
04286   bk.Write("bk");
04287 
04288   if (gVerbose)
04289     cout << "\nClose database" << endl;
04290   delete f;
04291 
04292   if (gVerbose)
04293     cout << "\nOpen database in read-only mode and read matrix" << endl;
04294   TFile *f1 = new TFile("vdecomp.root");
04295 
04296   if (gVerbose)
04297     cout << "\nRead decompositions should create same solutions" << endl;
04298   {
04299     TDecompLU *rlu = (TDecompLU*)  f1->Get("lu");
04300     TVectorD b1(rowsum);
04301     lu.Solve(b1);
04302     TVectorD b2(rowsum);
04303     rlu->Solve(b2);
04304     ok &= (b1 == b2);
04305     b1 = colsum;
04306     lu.TransSolve(b1);
04307     b2 = colsum;
04308     rlu->TransSolve(b2);
04309     ok &= (b1 == b2);
04310   }
04311 
04312   {
04313     TDecompChol *rchol = (TDecompChol*) f1->Get("chol");
04314     TVectorD b1(rowsum);
04315     chol.Solve(b1);
04316     TVectorD b2(rowsum);
04317     rchol->Solve(b2);
04318     ok &= (b1 == b2);
04319     b1 = colsum;
04320     chol.TransSolve(b1);
04321     b2 = colsum;
04322     rchol->TransSolve(b2);
04323     ok &= (b1 == b2);
04324   }
04325 
04326   {
04327     TDecompQRH *rqrh = (TDecompQRH*) f1->Get("qrh");
04328     TVectorD b1(rowsum);
04329     qrh.Solve(b1);
04330     TVectorD b2(rowsum);
04331     rqrh->Solve(b2);
04332     ok &= (b1 == b2);
04333     b1 = colsum;
04334     qrh.TransSolve(b1);
04335     b2 = colsum;
04336     rqrh->TransSolve(b2);
04337     ok &= (b1 == b2);
04338   }
04339 
04340   {
04341     TDecompSVD *rsvd = (TDecompSVD*) f1->Get("svd");
04342     TVectorD b1(rowsum);
04343     svd.Solve(b1);
04344     TVectorD b2(rowsum);
04345     rsvd->Solve(b2);
04346     ok &= (b1 == b2);
04347     b1 = colsum;
04348     svd.TransSolve(b1);
04349     b2 = colsum;
04350     rsvd->TransSolve(b2);
04351     ok &= (b1 == b2);
04352   }
04353 
04354   {
04355     TDecompBK *rbk = (TDecompBK*) f1->Get("bk");
04356     TVectorD b1(rowsum);
04357     bk.Solve(b1);
04358     TVectorD b2(rowsum);
04359     rbk->Solve(b2);
04360     ok &= (b1 == b2);
04361     b1 = colsum;
04362     bk.TransSolve(b1);
04363     b2 = colsum;
04364     rbk->TransSolve(b2);
04365     ok &= (b1 == b2);
04366   }
04367 
04368   delete f1;
04369 
04370   if (gVerbose)
04371     cout << "\nDone\n" << endl;
04372 
04373   StatusPrint(5,"Decomposition Persistence",ok);
04374 }
04375 
04376 void stress_backward_io()
04377 {
04378   TFile::SetCacheFileDir(".");
04379   TFile *f = TFile::Open("http://root.cern.ch/files/linearIO.root","CACHEREAD");
04380 
04381   TMatrixF mf1 = THilbertMatrixF(-5,5,-5,5);
04382   mf1[1][2] = TMath::Pi();
04383   TMatrixFSym mf2 = THilbertMatrixFSym(-5,5);
04384   TVectorF vf_row(mf1.GetRowLwb(),mf1.GetRowUpb()); vf_row = TMatrixFRow(mf1,3);
04385 
04386   TMatrixF    *mf1_r    = (TMatrixF*)    f->Get("mf1");
04387   TMatrixFSym *mf2_r    = (TMatrixFSym*) f->Get("mf2");
04388   TVectorF    *vf_row_r = (TVectorF*)    f->Get("vf_row");
04389 
04390   Bool_t ok = kTRUE;
04391 
04392   ok &= ((*mf1_r) == mf1) ? kTRUE : kFALSE;
04393   ok &= ((*mf2_r) == mf2) ? kTRUE : kFALSE;
04394   ok &= ((*vf_row_r) == vf_row) ? kTRUE : kFALSE;
04395 
04396   TMatrixD md1 = THilbertMatrixD(-5,5,-5,5);
04397   md1[1][2] = TMath::Pi();
04398   TMatrixDSym md2 = THilbertMatrixDSym(-5,5);
04399   TMatrixDSparse md3 = md1;
04400   TVectorD vd_row(md1.GetRowLwb(),md1.GetRowUpb()); vd_row = TMatrixDRow(md1,3);
04401 
04402   TMatrixD       *md1_r    = (TMatrixD*)       f->Get("md1");
04403   TMatrixDSym    *md2_r    = (TMatrixDSym*)    f->Get("md2");
04404   TMatrixDSparse *md3_r    = (TMatrixDSparse*) f->Get("md3");
04405   TVectorD       *vd_row_r = (TVectorD*)       f->Get("vd_row");
04406 
04407   ok &= ((*md1_r) == md1) ? kTRUE : kFALSE;
04408   ok &= ((*md2_r) == md2) ? kTRUE : kFALSE;
04409   ok &= ((*md3_r) == md3) ? kTRUE : kFALSE;
04410   ok &= ((*vd_row_r) == vd_row) ? kTRUE : kFALSE;
04411 
04412   StatusPrint(1,"Streamers",ok);
04413 }
04414 
04415 void cleanup()
04416 {
04417   gSystem->Unlink("vmatrix.root");
04418   gSystem->Unlink("vvector.root");
04419   gSystem->Unlink("vdecomp.root");
04420 }

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