vmatrix.cxx

Go to the documentation of this file.
00001 // @(#)root/test:$Id: vmatrix.cxx 36320 2010-10-12 19:00:12Z brun $
00002 // Author: Fons Rademakers and Eddy Offermann  Nov 2003
00003 
00004 //////////////////////////////////////////////////////////////////////////
00005 //                                                                      //
00006 // Linear Algebra Package -- Matrix Verifications.                      //
00007 //                                                                      //
00008 // This file implements a large set of TMat operation tests.            //
00009 // *******************************************************************  //
00010 // *  Starting  Matrix - S T R E S S suite                              //
00011 // *******************************************************************  //
00012 // Test  1 : Allocation, Resizing.................................. OK  //
00013 // Test  2 : Filling, Inserting, Using............................. OK  //
00014 // Test  3 : Uniform matrix operations............................. OK  //
00015 // Test  4 : Binary Matrix element-by-element operations............OK  //
00016 // Test  5 : Matrix transposition...................................OK  //
00017 // Test  6 : Haar/Hilbert Matrix....................................OK  //
00018 // Test  7 : Matrix promises........................................OK  //
00019 // Test  8 : Matrix Norms...........................................OK  //
00020 // Test  9 : Matrix Determinant.....................................OK  //
00021 // Test 10 : General Matrix Multiplications.........................OK  //
00022 // Test 11 : Symmetric Matrix Multiplications.......................OK  //
00023 // Test 12 : Matrix Vector Multiplications..........................OK  //
00024 // Test 13 : Matrix Inversion.......................................OK  //
00025 // Test 14 : Matrix Persistence.....................................OK  //
00026 // *******************************************************************  //
00027 //                                                                      //
00028 //////////////////////////////////////////////////////////////////////////
00029 
00030 //_____________________________batch only_____________________
00031 #ifndef __CINT__
00032 
00033 #include "Riostream.h"
00034 #include "TFile.h"
00035 #include "TMatrixD.h"
00036 #include "TMatrixDSym.h"
00037 #include "TMatrixDLazy.h"
00038 #include "TVectorD.h"
00039 #include "TArrayD.h"
00040 #include "TMath.h"
00041 
00042 #include "TDecompLU.h"
00043 #include "TDecompQRH.h"
00044 #include "TDecompSVD.h"
00045 
00046 void stress_matrix                (Int_t verbose);
00047 void StatusPrint                  (Int_t id,const TString &title,Int_t status);
00048 
00049 void stress_allocation            ();
00050 void stress_matrix_fill           (Int_t rsize,Int_t csize);
00051 void stress_element_op            (Int_t rsize,Int_t csize);
00052 void stress_binary_ebe_op         (Int_t rsize, Int_t csize);
00053 void stress_transposition         (Int_t msize);
00054 void stress_special_creation      (Int_t dim);
00055 void stress_matrix_fill           (Int_t rsize,Int_t csize);
00056 void stress_matrix_promises       (Int_t dim);
00057 void stress_norms                 (Int_t rsize,Int_t csize);
00058 void stress_determinant           (Int_t msize);
00059 void stress_mm_multiplications    (Int_t msize);
00060 void stress_sym_mm_multiplications(Int_t msize);
00061 void stress_vm_multiplications    (Int_t msize);
00062 void stress_inversion             (Int_t msize);
00063 void stress_matrix_io             ();
00064 
00065 int main(int argc,char **argv)
00066 {
00067   Int_t verbose = 0;
00068   Char_t c;
00069   while (argc > 1 && argv[1][0] == '-' && argv[1][1] != 0) {
00070     for (Int_t i = 1; (c = argv[1][i]) != 0; i++) {
00071       switch (c) {
00072         case 'v':
00073           verbose = 1;
00074           break;
00075         default:
00076           Error("vmatrix", "unknown flag -%c",c);
00077           break;
00078       }
00079     }
00080     argc--;
00081     argv++;
00082   }
00083   stress_matrix(verbose);
00084   return 0;
00085 }
00086 #endif
00087 
00088 #define EPSILON 1.0e-14
00089 
00090 Int_t gVerbose = 0;
00091 
00092 //________________________________common part_________________________
00093 
00094 void stress_matrix(Int_t verbose=0)
00095 {
00096   cout << "******************************************************************" <<endl;
00097   cout << "*  Starting  Matrix - S T R E S S suite                          *" <<endl;
00098   cout << "******************************************************************" <<endl;
00099 
00100   gVerbose = verbose;
00101   stress_allocation();
00102   stress_matrix_fill(20,10);
00103   stress_element_op(20,10);
00104   stress_binary_ebe_op(10,20);
00105   stress_transposition(20);
00106   stress_special_creation(20);
00107 #ifndef __CINT__
00108   stress_matrix_promises(20);
00109 #endif
00110   stress_norms(40,20);
00111   stress_determinant(20);
00112   stress_mm_multiplications(20);
00113   stress_sym_mm_multiplications(20);
00114   stress_vm_multiplications(20);
00115   stress_inversion(20);
00116 
00117   stress_matrix_io();
00118   cout << "******************************************************************" <<endl;
00119 }
00120 
00121 //------------------------------------------------------------------------
00122 void StatusPrint(Int_t id,const Char_t *title,Bool_t status)
00123 {
00124   // Print test program number and its title
00125 //   const Int_t kMAX = 65;
00126 //   TString header = TString("Test ")+Form("%2d",id)+" : "+title;
00127 //   const Int_t nch = header.Length();
00128 //   for (Int_t i = nch; i < kMAX; i++) header += '.';
00129 //   cout << header << (status ? "OK" : "FAILED") << endl;
00130   // Print test program number and its title
00131    const Int_t kMAX = 65;
00132    char header[80];
00133    sprintf(header,"Test %2d : %s",id,title);
00134    Int_t nch = strlen(header);
00135    for (Int_t i=nch;i<kMAX;i++) header[i] = '.';
00136    header[kMAX] = 0;
00137    header[kMAX-1] = ' ';
00138    cout << header << (status ? "OK" : "FAILED") << endl;
00139 }
00140 
00141 //------------------------------------------------------------------------
00142 //          Test allocation functions and compatibility check
00143 //
00144 void stress_allocation()
00145 {
00146   if (gVerbose)
00147     cout << "\n\n---> Test allocation and compatibility check" << endl;
00148 
00149   Bool_t ok = kTRUE;
00150 
00151   Int_t i,j;
00152   TMatrixD m1(4,20);
00153   for (i = m1.GetRowLwb(); i <= m1.GetRowUpb(); i++)
00154     for (j = m1.GetColLwb(); j <= m1.GetColUpb(); j++)
00155       m1(i,j) = TMath::Pi()*i+TMath::E()*j;
00156 
00157   TMatrixD m2(0,3,0,19);
00158   TMatrixD m3(1,4,0,19);
00159   TMatrixD m4(m1);
00160 
00161   if (gVerbose) {
00162     cout << "\nStatus information reported for matrix m3:" << endl;
00163     cout << "  Row lower bound ... " << m3.GetRowLwb() << endl;
00164     cout << "  Row upper bound ... " << m3.GetRowUpb() << endl;
00165     cout << "  Col lower bound ... " << m3.GetColLwb() << endl;
00166     cout << "  Col upper bound ... " << m3.GetColUpb() << endl;
00167     cout << "  No. rows ..........." << m3.GetNrows()  << endl;
00168     cout << "  No. cols ..........." << m3.GetNcols()  << endl;
00169     cout << "  No. of elements ...." << m3.GetNoElements() << endl;
00170   }
00171 
00172   if (gVerbose)
00173     cout << "\nCheck matrices 1 & 2 for compatibility" << endl;
00174   ok &= AreCompatible(m1,m2,gVerbose);
00175 
00176   if (gVerbose)
00177     cout << "Check matrices 1 & 4 for compatibility" << endl;
00178   ok &= AreCompatible(m1,m4,gVerbose);
00179 
00180   if (gVerbose)
00181     cout << "m2 has to be compatible with m3 after resizing to m3" << endl;
00182   m2.ResizeTo(m3);
00183   ok &= AreCompatible(m2,m3,gVerbose);
00184 
00185   TMatrixD m5(m1.GetNrows()+1,m1.GetNcols()+5);
00186   for (i = m5.GetRowLwb(); i <= m5.GetRowUpb(); i++)
00187     for (j = m5.GetColLwb(); j <= m5.GetColUpb(); j++)
00188       m5(i,j) = TMath::Pi()*i+TMath::E()*j;
00189 
00190   if (gVerbose)
00191     cout << "m1 has to be compatible with m5 after resizing to m5" << endl;
00192   m1.ResizeTo(m5.GetNrows(),m5.GetNcols());
00193   ok &= AreCompatible(m1,m5,gVerbose);
00194 
00195   if (gVerbose)
00196     cout << "m1 has to be equal to m4 after stretching and shrinking" << endl;
00197   m1.ResizeTo(m4.GetNrows(),m4.GetNcols());
00198   ok &= VerifyMatrixIdentity(m1,m4,gVerbose,EPSILON);
00199   if (gVerbose)
00200     cout << "m5 has to be equal to m1 after shrinking" << endl;
00201   m5.ResizeTo(m1.GetNrows(),m1.GetNcols());
00202   ok &= VerifyMatrixIdentity(m1,m5,gVerbose,EPSILON);
00203 
00204   if (gVerbose)
00205     cout << "stretching and shrinking for small matrices (stack)" << endl;
00206   if (gVerbose)
00207     cout << "m8 has to be equal to m7 after stretching and shrinking" << endl;
00208   TMatrixD m6(4,4);
00209   for (i = m6.GetRowLwb(); i <= m6.GetRowUpb(); i++)
00210     for (j = m6.GetColLwb(); j <= m6.GetColUpb(); j++)
00211       m6(i,j) = TMath::Pi()*i+TMath::E()*j;
00212   TMatrixD m8(3,3);
00213   for (i = m8.GetRowLwb(); i <= m8.GetRowUpb(); i++)
00214     for (j = m8.GetColLwb(); j <= m8.GetColUpb(); j++)
00215       m8(i,j) = TMath::Pi()*i+TMath::E()*j;
00216   TMatrixD m7(m8);
00217 
00218   m8.ResizeTo(4,4);
00219   m8.ResizeTo(3,3);
00220   ok &= VerifyMatrixIdentity(m7,m8,gVerbose,EPSILON);
00221 
00222   if (gVerbose)
00223     cout << "m6 has to be equal to m8 after shrinking" << endl;
00224   m6.ResizeTo(3,3);
00225   ok &= VerifyMatrixIdentity(m6,m8,gVerbose,EPSILON);
00226 
00227   if (gVerbose)
00228     cout << "\nDone\n" << endl;
00229 
00230   StatusPrint(1,"Allocation, Resizing",ok);
00231 }
00232 
00233 class FillMatrix : public TElementPosActionD {
00234    Int_t no_elems,no_cols;
00235    void Operation(Double_t &element) const
00236       { element = 4*TMath::Pi()/no_elems * (fI*no_cols+fJ); }
00237 public:
00238    FillMatrix() {}
00239    FillMatrix(const TMatrixD &m) :
00240          no_elems(m.GetNoElements()),no_cols(m.GetNcols()) { }
00241 };
00242 
00243 //
00244 //------------------------------------------------------------------------
00245 //          Test Filling of matrix
00246 //
00247 void stress_matrix_fill(Int_t rsize,Int_t csize)
00248 {
00249   if (gVerbose)
00250     cout << "\n\n---> Test different matrix filling methods\n" << endl;
00251 
00252   Bool_t ok = kTRUE;
00253   if (gVerbose)
00254     cout << "Creating m  with Apply function..." << endl;
00255   TMatrixD m(-1,rsize-2,1,csize);
00256 #ifndef __CINT__
00257   FillMatrix f(m);
00258   m.Apply(f);
00259 #else
00260   for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00261     for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00262       m(i,j) = 4*TMath::Pi()/m.GetNoElements() * (i*m.GetNcols()+j);
00263 #endif
00264 
00265   {
00266     if (gVerbose)
00267       cout << "Check identity between m and matrix filled through (i,j)" << endl;
00268 
00269     TMatrixD m_overload1(-1,rsize-2,1,csize);
00270     TMatrixD m_overload2(-1,rsize-2,1,csize);
00271 
00272     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00273     {
00274       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00275       {
00276         const Double_t val = 4*TMath::Pi()/rsize/csize*(i*csize+j);
00277         m_overload1(i,j)  = val;
00278         m_overload2[i][j] = val;
00279       }
00280     }
00281 
00282     ok &= VerifyMatrixIdentity(m,m_overload1,gVerbose,EPSILON);
00283     if (gVerbose)
00284       cout << "Check identity between m and matrix filled through [i][j]" << endl;
00285     ok &= VerifyMatrixIdentity(m,m_overload2,gVerbose,EPSILON);
00286     if (gVerbose)
00287       cout << "Check identity between matrix filled through [i][j] and (i,j)" << endl;
00288     ok &= VerifyMatrixIdentity(m_overload1,m_overload2,gVerbose,EPSILON);
00289   }
00290 
00291   {
00292     TArrayD a_fortran(rsize*csize);
00293     TArrayD a_c      (rsize*csize);
00294     for (Int_t i = 0; i < rsize; i++)
00295     {
00296       for (Int_t j = 0; j < csize; j++)
00297       {
00298         a_c[i*csize+j]       = 4*TMath::Pi()/rsize/csize*((i-1)*csize+j+1);
00299         a_fortran[i+rsize*j] = a_c[i*csize+j];
00300       }
00301     }
00302 
00303     if (gVerbose)
00304       cout << "Creating m_fortran by filling with fortran stored matrix" << endl;
00305     TMatrixD m_fortran(-1,rsize-2,1,csize,a_fortran.GetArray(),"F");
00306     if (gVerbose)
00307       cout << "Check identity between m and m_fortran" << endl;
00308     ok &= VerifyMatrixIdentity(m,m_fortran,gVerbose,EPSILON);
00309 
00310     if (gVerbose)
00311       cout << "Creating m_c by filling with c stored matrix" << endl;
00312     TMatrixD m_c(-1,rsize-2,1,csize,a_c.GetArray());
00313     if (gVerbose)
00314       cout << "Check identity between m and m_c" << endl;
00315     ok &= VerifyMatrixIdentity(m,m_c,gVerbose,EPSILON);
00316   }
00317 
00318   {
00319     if (gVerbose)
00320       cout << "Check insertion/extraction of sub-matrices" << endl;
00321     {
00322       TMatrixD m_sub1 = m;
00323       m_sub1.ResizeTo(0,rsize-2,2,csize);
00324       TMatrixD m_sub2 = m.GetSub(0,rsize-2,2,csize,"");
00325       ok &= VerifyMatrixIdentity(m_sub1,m_sub2,gVerbose,EPSILON);
00326     }
00327 
00328     {
00329       TMatrixD m2(-1,rsize-2,1,csize);
00330       TMatrixD m_part1 = m.GetSub(0,rsize-2,2,csize,"");
00331       TMatrixD m_part2 = m.GetSub(0,rsize-2,1,1,"");
00332       TMatrixD m_part3 = m.GetSub(-1,-1,2,csize,"");
00333       TMatrixD m_part4 = m.GetSub(-1,-1,1,1,"");
00334       m2.SetSub(0,2,m_part1);
00335       m2.SetSub(0,1,m_part2);
00336       m2.SetSub(-1,2,m_part3);
00337       m2.SetSub(-1,1,m_part4);
00338       ok &= VerifyMatrixIdentity(m,m2,gVerbose,EPSILON);
00339     }
00340 
00341     {
00342       TMatrixD m2(-1,rsize-2,1,csize);
00343       TMatrixD m_part1 = m.GetSub(0,rsize-2,2,csize,"S");
00344       TMatrixD m_part2 = m.GetSub(0,rsize-2,1,1,"S");
00345       TMatrixD m_part3 = m.GetSub(-1,-1,2,csize,"S");
00346       TMatrixD m_part4 = m.GetSub(-1,-1,1,1,"S");
00347       m2.SetSub(0,2,m_part1);
00348       m2.SetSub(0,1,m_part2);
00349       m2.SetSub(-1,2,m_part3);
00350       m2.SetSub(-1,1,m_part4);
00351       ok &= VerifyMatrixIdentity(m,m2,gVerbose,EPSILON);
00352     }
00353   }
00354 
00355   {
00356     if (gVerbose)
00357       cout << "Check array Use" << endl;
00358     {
00359       TMatrixD *m1 = new TMatrixD(m);
00360       TMatrixD *m2 = new TMatrixD();
00361       m2->Use(m1->GetRowLwb(),m1->GetRowUpb(),m1->GetColLwb(),m1->GetColUpb(),m1->GetMatrixArray());
00362       ok &= VerifyMatrixIdentity(m,*m2,gVerbose,EPSILON);
00363       m2->Sqr();
00364       TMatrixD m3 = m; m3.Sqr();
00365       ok &= VerifyMatrixIdentity(m3,*m1,gVerbose,EPSILON);
00366       delete m1;
00367       delete m2;
00368     }
00369   }
00370 
00371   if (gVerbose)
00372     cout << "\nDone\n" << endl;
00373 
00374   StatusPrint(2,"Filling, Inserting, Using",ok);
00375 }
00376 
00377 //
00378 //------------------------------------------------------------------------
00379 //                Test uniform element operations
00380 //
00381 typedef  double (*dfunc)(double);
00382 class ApplyFunction : public TElementActionD {
00383    dfunc fFunc;
00384    void Operation(Double_t &element) const { element = fFunc(double(element)); }
00385 public:
00386    ApplyFunction(dfunc func) : fFunc(func) { }
00387 };
00388 
00389 void stress_element_op(Int_t rsize,Int_t csize)
00390 {
00391   Bool_t ok = kTRUE;
00392   const Double_t pattern = 8.625;
00393 
00394   TMatrixD m(-1,rsize-2,1,csize);
00395 
00396   if (gVerbose)
00397     cout << "\nWriting zeros to m..." << endl;
00398   {
00399     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00400       for(Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00401         m(i,j) = 0;
00402     ok &= VerifyMatrixValue(m,0.,gVerbose,EPSILON);
00403   }
00404 
00405   if (gVerbose)
00406     cout << "Creating zero m1 ..." << endl;
00407   TMatrixD m1(TMatrixD::kZero, m);
00408   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
00409 
00410   if (gVerbose)
00411     cout << "Comparing m1 with 0 ..." << endl;
00412   R__ASSERT(m1 == 0);
00413   R__ASSERT(!(m1 != 0));
00414 
00415   if (gVerbose)
00416     cout << "Writing a pattern " << pattern << " by assigning to m(i,j)..." << endl;
00417   {
00418     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00419       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00420         m(i,j) = pattern;
00421     ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
00422   }
00423 
00424   if (gVerbose)
00425     cout << "Writing the pattern by assigning to m1 as a whole ..."  << endl;
00426   m1 = pattern;
00427   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00428 
00429   if (gVerbose)
00430     cout << "Comparing m and m1 ..." << endl;
00431   R__ASSERT(m == m1);
00432   if (gVerbose)
00433     cout << "Comparing (m=0) and m1 ..." << endl;
00434   R__ASSERT(!(m.Zero() == m1));
00435 
00436   if (gVerbose)
00437     cout << "Clearing m1 ..." << endl;
00438   m1.Zero();
00439   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
00440 
00441   if (gVerbose)
00442     cout << "\nClear m and add the pattern" << endl;
00443   m.Zero();
00444   m += pattern;
00445   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
00446   if (gVerbose)
00447     cout << "   add the doubled pattern with the negative sign" << endl;
00448   m += -2*pattern;
00449   ok &= VerifyMatrixValue(m,-pattern,gVerbose,EPSILON);
00450   if (gVerbose)
00451     cout << "   subtract the trippled pattern with the negative sign" << endl;
00452   m -= -3*pattern;
00453   ok &= VerifyMatrixValue(m,2*pattern,gVerbose,EPSILON);
00454 
00455   if (gVerbose)
00456     cout << "\nVerify comparison operations when all elems are the same" << endl;
00457   m = pattern;
00458   R__ASSERT( m == pattern && !(m != pattern) );
00459   R__ASSERT( m > 0 && m >= pattern && m <= pattern );
00460   R__ASSERT( m > -pattern && m >= -pattern );
00461   R__ASSERT( m <= pattern && !(m < pattern) );
00462   m -= 2*pattern;
00463   R__ASSERT( m  < -pattern/2 && m <= -pattern/2 );
00464   R__ASSERT( m  >= -pattern && !(m > -pattern) );
00465 
00466   if (gVerbose)
00467     cout << "\nVerify comparison operations when not all elems are the same" << endl;
00468   m = pattern; m(m.GetRowUpb(),m.GetColUpb()) = pattern-1;
00469   R__ASSERT( !(m == pattern) && !(m != pattern) );
00470   R__ASSERT( m != 0 );                   // none of elements are 0
00471   R__ASSERT( !(m >= pattern) && m <= pattern && !(m<pattern) );
00472   R__ASSERT( !(m <= pattern-1) && m >= pattern-1 && !(m>pattern-1) );
00473 
00474   if (gVerbose)
00475     cout << "\nAssign 2*pattern to m by repeating additions" << endl;
00476   m = 0; m += pattern; m += pattern;
00477   if (gVerbose)
00478     cout << "Assign 2*pattern to m1 by multiplying by two " << endl;
00479   m1 = pattern; m1 *= 2;
00480   ok &= VerifyMatrixValue(m1,2*pattern,gVerbose,EPSILON);
00481   R__ASSERT( m == m1 );
00482   if (gVerbose)
00483     cout << "Multiply m1 by one half returning it to the 1*pattern" << endl;
00484   m1 *= 1/2.;
00485   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00486 
00487   if (gVerbose)
00488     cout << "\nAssign -pattern to m and m1" << endl;
00489   m.Zero(); m -= pattern; m1 = -pattern;
00490   ok &= VerifyMatrixValue(m,-pattern,gVerbose,EPSILON);
00491   R__ASSERT( m == m1 );
00492   if (gVerbose)
00493     cout << "m = sqrt(sqr(m)); m1 = abs(m1); Now m and m1 have to be the same" << endl;
00494   m.Sqr();
00495   ok &= VerifyMatrixValue(m,pattern*pattern,gVerbose,EPSILON);
00496   m.Sqrt();
00497   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
00498   m1.Abs();
00499   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00500   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00501 
00502   if (gVerbose)
00503     cout << "\nCheck out to see that sin^2(x) + cos^2(x) = 1" << endl;
00504   {
00505 #ifndef __CINT__
00506     FillMatrix f(m);
00507     m.Apply(f);
00508 #else
00509     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00510       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00511         m(i,j) = 4*TMath::Pi()/m.GetNoElements() * (i*m.GetNcols()+j);
00512 #endif
00513   }
00514   m1 = m;
00515   {
00516 #ifndef __CINT__
00517     ApplyFunction s(&TMath::Sin);
00518     ApplyFunction c(&TMath::Cos);
00519     m.Apply(s);
00520     m1.Apply(c);
00521 #else
00522     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++) {
00523       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++) {
00524         m(i,j)  = TMath::Sin(m(i,j));
00525         m1(i,j) = TMath::Cos(m1(i,j));
00526       }
00527     }
00528 #endif
00529   }
00530   m.Sqr();
00531   m1.Sqr();
00532   m += m1;
00533   ok &= VerifyMatrixValue(m,1.,gVerbose,EPSILON);
00534 
00535   if (gVerbose)
00536     cout << "\nDone\n" << endl;
00537 
00538   StatusPrint(3,"Uniform matrix operations",ok);
00539 }
00540 
00541 //
00542 //------------------------------------------------------------------------
00543 //        Test binary matrix element-by-element operations
00544 //
00545 void stress_binary_ebe_op(Int_t rsize, Int_t csize)
00546 {
00547   if (gVerbose)
00548     cout << "\n---> Test Binary Matrix element-by-element operations" << endl;
00549 
00550   Bool_t ok = kTRUE;
00551   const double pattern = 4.25;
00552 
00553   TMatrixD m(2,rsize+1,0,csize-1);
00554   TMatrixD m1(TMatrixD::kZero,m);
00555   TMatrixD mp(TMatrixD::kZero,m);
00556 
00557   {
00558     for (Int_t i = mp.GetRowLwb(); i <= mp.GetRowUpb(); i++)
00559       for (Int_t j = mp.GetColLwb(); j <= mp.GetColUpb(); j++)
00560         mp(i,j) = (i-m.GetNrows()/2.)*j*pattern;
00561   }
00562 
00563   if (gVerbose)
00564     cout << "\nVerify assignment of a matrix to the matrix" << endl;
00565   m = pattern;
00566   m1.Zero();
00567   m1 = m;
00568   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00569   R__ASSERT( m1 == m );
00570 
00571   if (gVerbose)
00572     cout << "\nAdding the matrix to itself, uniform pattern " << pattern << endl;
00573   m.Zero(); m = pattern;
00574   m1 = m; m1 += m1;
00575   ok &= VerifyMatrixValue(m1,2*pattern,gVerbose,EPSILON);
00576   if (gVerbose)
00577     cout << "  subtracting two matrices ..." << endl;
00578   m1 -= m;
00579   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00580   if (gVerbose)
00581     cout << "  subtracting the matrix from itself" << endl;
00582   m1 -= m1;
00583   ok &= VerifyMatrixValue(m1,0.,gVerbose,EPSILON);
00584   if (gVerbose)
00585     cout << "  adding two matrices together" << endl;
00586   m1 += m;
00587   ok &= VerifyMatrixValue(m1,pattern,gVerbose,EPSILON);
00588 
00589   if (gVerbose) {
00590     cout << "\nArithmetic operations on matrices with not the same elements" << endl;
00591     cout << "   adding mp to the zero matrix..." << endl;
00592   }
00593   m.Zero(); m += mp;
00594   ok &= VerifyMatrixIdentity(m,mp,gVerbose,EPSILON);
00595   m1 = m;
00596   if (gVerbose)
00597     cout << "   making m = 3*mp and m1 = 3*mp, via add() and succesive mult" << endl;
00598   Add(m,2.,mp);
00599   m1 += m1; m1 += mp;
00600   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00601   if (gVerbose)
00602     cout << "   clear both m and m1, by subtracting from itself and via add()" << endl;
00603   m1 -= m1;
00604   Add(m,-3.,mp);
00605   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00606 
00607   if (gVerbose) {
00608     cout << "\nTesting element-by-element multiplications and divisions" << endl;
00609     cout << "   squaring each element with sqr() and via multiplication" << endl;
00610   }
00611   m = mp; m1 = mp;
00612   m.Sqr();
00613   ElementMult(m1,m1);
00614   ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00615   if (gVerbose)
00616     cout << "   compare (m = pattern^2)/pattern with pattern" << endl;
00617   m = pattern; m1 = pattern;
00618   m.Sqr();
00619   ElementDiv(m,m1);
00620   ok &= VerifyMatrixValue(m,pattern,gVerbose,EPSILON);
00621   if (gVerbose)
00622     Compare(m1,m);
00623 
00624   if (gVerbose)
00625     cout << "\nDone\n" << endl;
00626 
00627   StatusPrint(4,"Binary Matrix element-by-element operations",ok);
00628 }
00629 
00630 //
00631 //------------------------------------------------------------------------
00632 //              Verify matrix transposition
00633 //
00634 void stress_transposition(Int_t msize)
00635 {
00636   if (gVerbose) {
00637     cout << "\n---> Verify matrix transpose "
00638             "for matrices of a characteristic size " << msize << endl;
00639   }
00640 
00641   Bool_t ok = kTRUE;
00642   {
00643     if (gVerbose)
00644       cout << "\nCheck to see that a square UnitMatrix stays the same";
00645     TMatrixD m(msize,msize);
00646     m.UnitMatrix();
00647     TMatrixD mt(TMatrixD::kTransposed,m);
00648     ok &= ( m == mt ) ? kTRUE : kFALSE;
00649   }
00650 
00651   {
00652     if (gVerbose)
00653       cout << "\nTest a non-square UnitMatrix";
00654     TMatrixD m(msize,msize+1);
00655     m.UnitMatrix();
00656     TMatrixD mt(TMatrixD::kTransposed,m);
00657     R__ASSERT(m.GetNrows() == mt.GetNcols() && m.GetNcols() == mt.GetNrows() );
00658     for (Int_t i = m.GetRowLwb(); i <= TMath::Min(m.GetRowUpb(),m.GetColUpb()); i++)
00659       for (Int_t j = m.GetColLwb(); j <= TMath::Min(m.GetRowUpb(),m.GetColUpb()); j++)
00660         ok &= ( m(i,j) == mt(i,j) ) ? kTRUE : kFALSE;
00661   }
00662 
00663   {
00664     if (gVerbose)
00665       cout << "\nCheck to see that a symmetric (Hilbert)Matrix stays the same";
00666     TMatrixD m = THilbertMatrixD(msize,msize);
00667     TMatrixD mt(TMatrixD::kTransposed,m);
00668     ok &= ( m == mt ) ? kTRUE : kFALSE;
00669   }
00670 
00671   {
00672     if (gVerbose)
00673       cout << "\nCheck transposing a non-symmetric matrix";
00674     TMatrixD m = THilbertMatrixD(msize+1,msize);
00675     m(1,2) = TMath::Pi();
00676     TMatrixD mt(TMatrixD::kTransposed,m);
00677     R__ASSERT(m.GetNrows() == mt.GetNcols() && m.GetNcols() == mt.GetNrows());
00678     R__ASSERT(mt(2,1)  == (Double_t)TMath::Pi() && mt(1,2)  != (Double_t)TMath::Pi());
00679     R__ASSERT(mt[2][1] == (Double_t)TMath::Pi() && mt[1][2] != (Double_t)TMath::Pi());
00680 
00681     if (gVerbose)
00682       cout << "\nCheck double transposing a non-symmetric matrix" << endl;
00683     TMatrixD mtt(TMatrixD::kTransposed,mt);
00684     ok &= ( m == mtt ) ? kTRUE : kFALSE;
00685   }
00686 
00687   if (gVerbose)
00688     cout << "\nDone\n" << endl;
00689 
00690   StatusPrint(5,"Matrix transposition",ok);
00691 }
00692 
00693 //
00694 //------------------------------------------------------------------------
00695 //           Test special matrix creation
00696 //
00697 class MakeHilbert : public TElementPosActionD {
00698   void Operation(Double_t &element) const { element = 1./(fI+fJ+1); }
00699 public:
00700   MakeHilbert() { }
00701 };
00702 
00703 #ifndef __CINT__
00704 class TestUnit : public TElementPosActionD {
00705   mutable Int_t fIsUnit;
00706   void Operation(Double_t &element) const
00707       { if (fIsUnit)
00708           fIsUnit = ((fI==fJ) ? (element == 1.0) : (element == 0)); }
00709 public:
00710   TestUnit() : fIsUnit(0==0) { }
00711   Int_t is_indeed_unit() const { return fIsUnit; }
00712 };
00713 #else
00714   Bool_t is_indeed_unit(TMatrixD &m) {
00715     Bool_t isUnit = kTRUE;
00716     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00717       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++) {
00718         if (isUnit)
00719           isUnit = ((i==j) ? (m(i,j) == 1.0) : (m(i,j) == 0));
00720       }
00721     return isUnit;
00722   }
00723 #endif
00724 
00725 void stress_special_creation(Int_t dim)
00726 {
00727   if (gVerbose)
00728     cout << "\n---> Check creating some special matrices of dimension " << dim << endl;
00729 
00730   Int_t j;
00731   Bool_t ok = kTRUE;
00732   {
00733     if (gVerbose)
00734       cout << "\ntest creating Hilbert matrices" << endl;
00735     TMatrixD m = THilbertMatrixD(dim+1,dim);
00736     TMatrixD m1(TMatrixD::kZero,m);
00737     ok &= ( !(m == m1) ) ? kTRUE : kFALSE;
00738     ok &= ( m != 0 ) ? kTRUE : kFALSE;
00739 #ifndef __CINT__
00740     MakeHilbert mh;
00741     m1.Apply(mh);
00742 #else
00743     for (Int_t i = m1.GetRowLwb(); i <= m1.GetRowUpb(); i++)
00744       for (j = m1.GetColLwb(); j <= m1.GetColUpb(); j++)
00745         m1(i,j) = 1./(i+j+1);
00746 #endif
00747     ok &= ( m1 != 0 ) ? kTRUE : kFALSE;
00748     ok &= ( m == m1 ) ? kTRUE : kFALSE;
00749   }
00750 
00751   {
00752     if (gVerbose)
00753       cout << "test creating zero matrix and copy constructor" << endl;
00754     TMatrixD m = THilbertMatrixD(dim,dim+1);
00755     ok &= ( m != 0 ) ? kTRUE : kFALSE;
00756     TMatrixD m1(m);               // Applying the copy constructor
00757     ok &= ( m1 == m ) ? kTRUE : kFALSE;
00758     TMatrixD m2(TMatrixD::kZero,m);
00759     ok &= ( m2 == 0 ) ? kTRUE : kFALSE;
00760     ok &= ( m != 0 ) ? kTRUE : kFALSE;
00761   }
00762 
00763   {
00764     if (gVerbose)
00765       cout << "test creating unit matrices" << endl;
00766     TMatrixD m(dim,dim);
00767 #ifndef __CINT__
00768     {
00769       TestUnit test_unit;
00770       m.Apply(test_unit);
00771       ok &= ( !test_unit.is_indeed_unit() ) ? kTRUE : kFALSE;
00772     }
00773 #else
00774     ok &= ( !is_indeed_unit(m) ) ? kTRUE : kFALSE;
00775 #endif
00776     m.UnitMatrix();
00777 #ifndef __CINT__
00778     {
00779       TestUnit test_unit;
00780        m.Apply(test_unit);
00781        ok &= ( test_unit.is_indeed_unit() ) ? kTRUE : kFALSE;
00782     }
00783 #else
00784     ok &= ( is_indeed_unit(m) ) ? kTRUE : kFALSE;
00785 #endif
00786     m.ResizeTo(dim-1,dim);
00787     TMatrixD m2(TMatrixD::kUnit,m);
00788 #ifndef __CINT__
00789     {
00790       TestUnit test_unit;
00791       m2.Apply(test_unit);
00792       ok &= ( test_unit.is_indeed_unit() ) ? kTRUE : kFALSE;
00793     }
00794 #else
00795     ok &= ( is_indeed_unit(m2) ) ? kTRUE : kFALSE;
00796 #endif
00797     m.ResizeTo(dim,dim-2);
00798     m.UnitMatrix();
00799 #ifndef __CINT__
00800     {
00801       TestUnit test_unit;
00802       m.Apply(test_unit);
00803       ok &= ( test_unit.is_indeed_unit() ) ? kTRUE : kFALSE;
00804     }
00805 #else
00806     ok &= ( is_indeed_unit(m) ) ? kTRUE : kFALSE;
00807 #endif
00808   }
00809 
00810   {
00811     if (gVerbose)
00812       cout << "check to see that Haar matrix has *exactly* orthogonal columns" << endl;
00813     const Int_t order = 5;
00814     const TMatrixD haar = THaarMatrixD(order);
00815     ok &= ( haar.GetNrows() == (1<<order) &&
00816                haar.GetNrows() == haar.GetNcols() ) ? kTRUE : kFALSE;
00817     TVectorD colj(1<<order);
00818     TVectorD coll(1<<order);
00819     for (j = haar.GetColLwb(); j <= haar.GetColUpb(); j++) {
00820       colj = TMatrixDColumn_const(haar,j);
00821       ok &= (TMath::Abs(colj*colj-1.0) <= 1.0e-15 ) ? kTRUE : kFALSE;
00822       for (Int_t l = j+1; l <= haar.GetColUpb(); l++) {
00823         coll = TMatrixDColumn_const(haar,l);
00824         const Double_t val = colj*coll;
00825         ok &= ( TMath::Abs(val) <= 1.0e-15 ) ? kTRUE : kFALSE;
00826       }
00827     }
00828 
00829     if (gVerbose)
00830       cout << "make Haar (sub)matrix and test it *is* a submatrix" << endl;
00831     const Int_t no_sub_cols = (1<<order) - 3;
00832     const TMatrixD haar_sub = THaarMatrixD(order,no_sub_cols);
00833     ok &= ( haar_sub.GetNrows() == (1<<order) &&
00834                haar_sub.GetNcols() == no_sub_cols ) ? kTRUE : kFALSE;
00835     for (j = haar_sub.GetColLwb(); j <= haar_sub.GetColUpb(); j++) {
00836       colj = TMatrixDColumn_const(haar,j);
00837       coll = TMatrixDColumn_const(haar_sub,j);
00838       ok &= VerifyVectorIdentity(colj,coll,gVerbose);
00839     }
00840   }
00841 
00842   if (gVerbose)
00843     cout << "\nDone\n" << endl;
00844 
00845   StatusPrint(6,"Haar/Hilbert Matrix",ok);
00846 }
00847 
00848 //
00849 //------------------------------------------------------------------------
00850 //           Test matrix promises
00851 //
00852 class hilbert_matrix_promise : public TMatrixDLazy {
00853   void FillIn(TMatrixD &m) const { m = THilbertMatrixD(m.GetRowLwb(),m.GetRowUpb(),
00854                                                    m.GetColLwb(),m.GetColUpb()); }
00855 
00856 public:
00857   hilbert_matrix_promise(Int_t nrows,Int_t ncols)
00858      : TMatrixDLazy(nrows,ncols) {}
00859   hilbert_matrix_promise(Int_t row_lwb,Int_t row_upb,
00860                          Int_t col_lwb,Int_t col_upb)
00861      : TMatrixDLazy(row_lwb,row_upb,col_lwb,col_upb) { }
00862 };
00863 
00864 void stress_matrix_promises(Int_t dim)
00865 {
00866   if (gVerbose)
00867     cout << "\n---> Check making/forcing promises, (lazy)matrices of dimension " << dim << endl;
00868 
00869   Bool_t ok = kTRUE;
00870   {
00871     if (gVerbose)
00872       cout << "\nmake a promise and force it by a constructor" << endl;
00873     TMatrixD m  = hilbert_matrix_promise(dim,dim+1);
00874     TMatrixD m1 = THilbertMatrixD(dim,dim+1);
00875     ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00876   }
00877 
00878   {
00879     if (gVerbose)
00880       cout << "make a promise and force it by an assignment" << endl;
00881     TMatrixD m(-1,dim,0,dim);
00882     m = hilbert_matrix_promise(-1,dim,0,dim);
00883     TMatrixD m1 = THilbertMatrixD(-1,dim,0,dim);
00884     ok &= VerifyMatrixIdentity(m,m1,gVerbose,EPSILON);
00885   }
00886 
00887   if (gVerbose)
00888     cout << "\nDone\n" << endl;
00889 
00890   StatusPrint(7,"Matrix promises",ok);
00891 }
00892 
00893 //
00894 //------------------------------------------------------------------------
00895 //             Verify the norm calculation
00896 //
00897 void stress_norms(Int_t rsize,Int_t csize)
00898 {
00899   if (gVerbose)
00900     cout << "\n---> Verify norm calculations" << endl;
00901 
00902   Bool_t ok = kTRUE;
00903   const double pattern = 10.25;
00904 
00905   if (rsize % 2 == 1 || csize %2 == 1)
00906     Fatal("stress_norms","Sorry, size of the matrix to test must be even for this test\n");
00907 
00908   TMatrixD m(rsize,csize);
00909 
00910   if (gVerbose)
00911     cout << "\nAssign " << pattern << " to all the elements and check norms" << endl;
00912   m = pattern;
00913   if (gVerbose)
00914     cout << "  1. (col) norm should be pattern*nrows" << endl;
00915   ok &= ( m.Norm1() == pattern*m.GetNrows() ) ? kTRUE : kFALSE;
00916   ok &= ( m.Norm1() == m.ColNorm() ) ? kTRUE : kFALSE;
00917   if (gVerbose)
00918     cout << "  Inf (row) norm should be pattern*ncols" << endl;
00919   ok &= ( m.NormInf() == pattern*m.GetNcols() ) ? kTRUE : kFALSE;
00920   ok &= ( m.NormInf() == m.RowNorm() ) ? kTRUE : kFALSE;
00921   if (gVerbose)
00922     cout << "  Square of the Eucl norm has got to be pattern^2 * no_elems" << endl;
00923   ok &= ( m.E2Norm() == (pattern*pattern)*m.GetNoElements() ) ? kTRUE : kFALSE;
00924   TMatrixD m1(TMatrixD::kZero,m);
00925   ok &= ( m.E2Norm() == E2Norm(m,m1) ) ? kTRUE : kFALSE;
00926 
00927   if (gVerbose)
00928     cout << "\nDone\n" << endl;
00929 
00930   StatusPrint(8,"Matrix Norms",ok);
00931 }
00932 
00933 //
00934 //------------------------------------------------------------------------
00935 //              Verify the determinant evaluation
00936 //
00937 void stress_determinant(Int_t msize)
00938 {
00939   if (gVerbose)
00940     cout << "\n---> Verify determinant evaluation for a square matrix of size " << msize << endl;
00941 
00942   Bool_t ok = kTRUE;
00943   TMatrixD m(msize,msize);
00944   const double pattern = 2.5;
00945 
00946   if (gVerbose)
00947     cout << "\nCheck to see that the determinant of the unit matrix is one";
00948   m.UnitMatrix();
00949   if (gVerbose)
00950     cout << "\n determinant is " << m.Determinant();
00951   ok &= ( m.Determinant() == 1 ) ? kTRUE : kFALSE;
00952 
00953   if (gVerbose)
00954     cout << "\nCheck the determinant for the matrix with " << pattern << " at the diagonal";
00955   {
00956     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
00957       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
00958         m(i,j) = ( i==j ? pattern : 0 );
00959   }
00960   if (gVerbose)
00961     cout << "\n determinant is " << m.Determinant() << " should be " << TMath::Power(pattern,(double)m.GetNrows()) <<endl;
00962   ok &= ( TMath::Abs(m.Determinant()-TMath::Power(pattern,(double)m.GetNrows())) < DBL_EPSILON  ) ? kTRUE : kFALSE;
00963 
00964   if (gVerbose)
00965     cout << "\nCheck the determinant of the transposed matrix";
00966   m.UnitMatrix();
00967   m(1,2) = pattern;
00968   TMatrixD m_tran(TMatrixD::kTransposed,m);
00969   ok &= ( !(m == m_tran) ) ? kTRUE : kFALSE;
00970   ok &= ( m.Determinant() == m_tran.Determinant() ) ? kTRUE : kFALSE;
00971 
00972   {
00973     if (gVerbose)
00974       cout << "\nswap two rows/cols of a matrix through method 1 and watch det's sign";
00975     m.UnitMatrix();
00976     TMatrixDRow(m,3) = pattern;
00977     const double det1 = m.Determinant();
00978     TMatrixDRow row1(m,1);
00979     TVectorD vrow1(m.GetRowLwb(),m.GetRowUpb()); vrow1 = row1;
00980     TVectorD vrow3(m.GetRowLwb(),m.GetRowUpb()); vrow3 = TMatrixDRow(m,3);
00981     row1 = vrow3; TMatrixDRow(m,3) = vrow1;
00982     ok &= ( m.Determinant() == -det1 ) ? kTRUE : kFALSE;
00983     TMatrixDColumn col2(m,2);
00984     TVectorD vcol2(m.GetRowLwb(),m.GetRowUpb()); vcol2 = col2;
00985     TVectorD vcol4(m.GetRowLwb(),m.GetRowUpb()); vcol4 = TMatrixDColumn(m,4);
00986     col2 = vcol4; TMatrixDColumn(m,4) = vcol2;
00987     ok &= ( m.Determinant() == det1 ) ? kTRUE : kFALSE;
00988   }
00989 
00990   {
00991     if (gVerbose)
00992       cout << "\nswap two rows/cols of a matrix through method 2 and watch det's sign";
00993     m.UnitMatrix();
00994     TMatrixDRow(m,3) = pattern;
00995     const double det1 = m.Determinant();
00996 
00997     TMatrixD m_save( m);
00998     TMatrixDRow(m,1) = TMatrixDRow(m_save,3);
00999     TMatrixDRow(m,3) = TMatrixDRow(m_save,1);
01000     ok &= ( m.Determinant() == -det1 ) ? kTRUE : kFALSE;
01001 
01002     m_save = m;
01003     TMatrixDColumn(m,2) = TMatrixDColumn(m_save,4);
01004     TMatrixDColumn(m,4) = TMatrixDColumn(m_save,2);
01005     ok &= ( m.Determinant() == det1 ) ? kTRUE : kFALSE;
01006   }
01007 
01008   if (gVerbose)
01009     cout << "\nCheck the determinant for the matrix with " << pattern << " at the anti-diagonal";
01010   {
01011     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
01012       for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
01013         m(i,j) = ( i==(m.GetColUpb()+m.GetColLwb()-j) ? pattern : 0 );
01014     ok &= ( m.Determinant() == TMath::Power(pattern,(double)m.GetNrows()) *
01015                ( m.GetNrows()*(m.GetNrows()-1)/2 & 1 ? -1 : 1 ) ) ? kTRUE : kFALSE;
01016   }
01017 
01018   if (0)
01019   {
01020     if (gVerbose)
01021       cout << "\nCheck the determinant for the singular matrix"
01022               "\n       defined as above with zero first row";
01023     m.Zero();
01024     {
01025       for (Int_t i = m.GetRowLwb()+1; i <= m.GetRowUpb(); i++)
01026         for (Int_t j = m.GetColLwb(); j <= m.GetColUpb(); j++)
01027           m(i,j) = ( i==(m.GetColUpb()+m.GetColLwb()-j) ? pattern : 0 );
01028     }
01029     if (gVerbose)
01030       cout << "\n       determinant is " << m.Determinant();
01031     ok &= ( m.Determinant() == 0 ) ? kTRUE : kFALSE;
01032   }
01033 
01034   if (gVerbose)
01035     cout << "\nCheck out the determinant of the Hilbert matrix";
01036   TMatrixD H = THilbertMatrixD(3,3);
01037   if (gVerbose) {
01038     cout << "\n    3x3 Hilbert matrix: exact determinant 1/2160 ";
01039     cout << "\n                              computed    1/"<< 1/H.Determinant();
01040   }
01041 
01042   H.ResizeTo(4,4);
01043   H = THilbertMatrixD(4,4);
01044   if (gVerbose) {
01045     cout << "\n    4x4 Hilbert matrix: exact determinant 1/6048000 ";
01046     cout << "\n                              computed    1/"<< 1/H.Determinant();
01047   }
01048 
01049   H.ResizeTo(5,5);
01050   H = THilbertMatrixD(5,5);
01051   if (gVerbose) {
01052     cout << "\n    5x5 Hilbert matrix: exact determinant 3.749295e-12";
01053     cout << "\n                              computed    "<< H.Determinant();
01054   }
01055 
01056   if (gVerbose) {
01057     TDecompQRH qrh(H);
01058     Double_t d1,d2;
01059     qrh.Det(d1,d2);
01060     cout  << "\n qrh det = " << d1*TMath::Power(2.0,d2) <<endl;
01061   }
01062 
01063   if (gVerbose) {
01064     TDecompSVD svd(H);
01065     Double_t d1,d2;
01066     svd.Det(d1,d2);
01067     cout  << "\n svd det = " << d1*TMath::Power(2.0,d2) <<endl;
01068   }
01069 
01070   H.ResizeTo(7,7);
01071   H = THilbertMatrixD(7,7);
01072   if (gVerbose) {
01073     cout << "\n    7x7 Hilbert matrix: exact determinant 4.8358e-25";
01074     cout << "\n                              computed    "<< H.Determinant();
01075   }
01076 
01077   H.ResizeTo(9,9);
01078   H = THilbertMatrixD(9,9);
01079   if (gVerbose) {
01080     cout << "\n    9x9 Hilbert matrix: exact determinant 9.72023e-43";
01081     cout << "\n                              computed    "<< H.Determinant();
01082   }
01083 
01084   H.ResizeTo(10,10);
01085   H = THilbertMatrixD(10,10);
01086   if (gVerbose) {
01087     cout << "\n    10x10 Hilbert matrix: exact determinant 2.16418e-53";
01088     cout << "\n                              computed    "<< H.Determinant();
01089   }
01090 
01091   if (gVerbose)
01092   cout << "\nDone\n" << endl;
01093 
01094   StatusPrint(9,"Matrix Determinant",ok);
01095 }
01096 
01097 //
01098 //------------------------------------------------------------------------
01099 //               Verify matrix multiplications
01100 //
01101 void stress_mm_multiplications(Int_t msize)
01102 {
01103   if (gVerbose)
01104     cout << "\n---> Verify matrix multiplications "
01105             "for matrices of the characteristic size " << msize << endl;
01106 
01107   const Double_t epsilon = EPSILON*msize/100;
01108 
01109   Int_t i,j;
01110   Bool_t ok = kTRUE;
01111   {
01112     if (gVerbose)
01113       cout << "\nTest inline multiplications of the UnitMatrix" << endl;
01114     TMatrixD m = THilbertMatrixD(-1,msize,-1,msize);
01115     TMatrixD u(TMatrixD::kUnit,m);
01116     m(3,1) = TMath::Pi();
01117     u *= m;
01118     ok &= VerifyMatrixIdentity(u,m,gVerbose,epsilon);
01119   }
01120 
01121   {
01122     if (gVerbose)
01123       cout << "Test inline multiplications by a DiagMat" << endl;
01124     TMatrixD m = THilbertMatrixD(msize+3,msize);
01125     m(1,3) = TMath::Pi();
01126     TVectorD v(msize);
01127     for (i = v.GetLwb(); i <= v.GetUpb(); i++)
01128       v(i) = 1+i;
01129     TMatrixD diag(msize,msize);
01130     TMatrixDDiag d = TMatrixDDiag(diag);
01131     d = v;
01132     TMatrixD eth = m;
01133     for (i = eth.GetRowLwb(); i <= eth.GetRowUpb(); i++)
01134       for (j = eth.GetColLwb(); j <= eth.GetColUpb(); j++)
01135         eth(i,j) *= v(j);
01136     m *= diag;
01137     ok &= VerifyMatrixIdentity(m,eth,gVerbose,epsilon);
01138   }
01139 
01140   {
01141     if (gVerbose)
01142       cout << "Test XPP = X where P is a permutation matrix" << endl;
01143     TMatrixD m = THilbertMatrixD(msize-1,msize);
01144     m(2,3) = TMath::Pi();
01145     TMatrixD eth = m;
01146     TMatrixD p(msize,msize);
01147     for (i = p.GetRowLwb(); i <= p.GetRowUpb(); i++)
01148       p(p.GetRowUpb()+p.GetRowLwb()-i,i) = 1;
01149     m *= p;
01150     m *= p;
01151     ok &= VerifyMatrixIdentity(m,eth,gVerbose,epsilon);
01152   }
01153 
01154   {
01155     if (gVerbose)
01156       cout << "Test general matrix multiplication through inline mult" << endl;
01157     TMatrixD m = THilbertMatrixD(msize-2,msize);
01158     m(3,3) = TMath::Pi();
01159     TMatrixD mt(TMatrixD::kTransposed,m);
01160     TMatrixD p = THilbertMatrixD(msize,msize);
01161     TMatrixDDiag(p) += 1;
01162     TMatrixD mp(m,TMatrixD::kMult,p);
01163     TMatrixD m1 = m;
01164     m *= p;
01165     ok &= VerifyMatrixIdentity(m,mp,gVerbose,epsilon);
01166     TMatrixD mp1(mt,TMatrixD::kTransposeMult,p);
01167     VerifyMatrixIdentity(m,mp1,gVerbose,epsilon);
01168     ok &= ( !(m1 == m) );
01169     TMatrixD mp2(TMatrixD::kZero,m1);
01170     ok &= ( mp2 == 0 );
01171     mp2.Mult(m1,p);
01172     ok &= VerifyMatrixIdentity(m,mp2,gVerbose,epsilon);
01173 
01174     if (gVerbose)
01175       cout << "Test XP=X*P  vs XP=X;XP*=P" << endl;
01176     TMatrixD mp3 = m1*p;
01177     ok &= VerifyMatrixIdentity(m,mp3,gVerbose,epsilon);
01178   }
01179 
01180   {
01181     if (gVerbose)
01182       cout << "Check to see UU' = U'U = E when U is the Haar matrix" << endl;
01183     const Int_t order = 5;
01184     const Int_t no_sub_cols = (1<<order)-5;
01185     TMatrixD haar_sub = THaarMatrixD(5,no_sub_cols);
01186     TMatrixD haar_sub_t(TMatrixD::kTransposed,haar_sub);
01187     TMatrixD hsths(haar_sub_t,TMatrixD::kMult,haar_sub);
01188     TMatrixD hsths1(TMatrixD::kZero,hsths); hsths1.Mult(haar_sub_t,haar_sub);
01189     TMatrixD hsths_eth(TMatrixD::kUnit,hsths);
01190     ok &= ( hsths.GetNrows() == no_sub_cols && hsths.GetNcols() == no_sub_cols );
01191     ok &= VerifyMatrixIdentity(hsths,hsths_eth,gVerbose,EPSILON);
01192     ok &= VerifyMatrixIdentity(hsths1,hsths_eth,gVerbose,EPSILON);
01193     TMatrixD haar = THaarMatrixD(5);
01194     TMatrixD unit(TMatrixD::kUnit,haar);
01195     TMatrixD haar_t(TMatrixD::kTransposed,haar);
01196     TMatrixD hth(haar,TMatrixD::kTransposeMult,haar);
01197     TMatrixD hht(haar,TMatrixD::kMult,haar_t);
01198     TMatrixD hht1 = haar; hht1 *= haar_t;
01199     TMatrixD hht2(TMatrixD::kZero,haar); hht2.Mult(haar,haar_t);
01200     ok &= VerifyMatrixIdentity(unit,hth,gVerbose,EPSILON);
01201     ok &= VerifyMatrixIdentity(unit,hht,gVerbose,EPSILON);
01202     ok &= VerifyMatrixIdentity(unit,hht1,gVerbose,EPSILON);
01203     ok &= VerifyMatrixIdentity(unit,hht2,gVerbose,EPSILON);
01204   }
01205   if (gVerbose)
01206     cout << "\nDone\n" << endl;
01207 
01208   StatusPrint(10,"General Matrix Multiplications",ok);
01209 }
01210 
01211 //
01212 //------------------------------------------------------------------------
01213 //               Verify symmetric matrix multiplications
01214 //
01215 void stress_sym_mm_multiplications(Int_t msize)
01216 {
01217   if (gVerbose)
01218     cout << "\n---> Verify symmetric matrix multiplications "
01219             "for matrices of the characteristic size " << msize << endl;
01220 
01221   Bool_t ok = kTRUE;
01222 
01223   Int_t i,j;
01224   const Double_t epsilon = EPSILON*msize/100;
01225 
01226   {
01227     if (gVerbose)
01228       cout << "\nTest inline multiplications of the UnitMatrix" << endl;
01229     TMatrixD m = THilbertMatrixD(-1,msize,-1,msize);
01230     TMatrixDSym m_sym(-1,msize,m.GetMatrixArray());
01231     TMatrixDSym u(TMatrixDSym::kUnit,m_sym);
01232     TMatrixD u2 = u * m_sym;
01233     ok &= VerifyMatrixIdentity(u2,m_sym,gVerbose,epsilon);
01234   }
01235 
01236   if (ok)
01237   {
01238     if (gVerbose)
01239       cout << "\nTest symmetric multiplications" << endl;
01240     {
01241       if (gVerbose)
01242         cout << "\n  Test m * m_sym == m_sym * m == m_sym * m_sym  multiplications" << endl;
01243       TMatrixD m = THilbertMatrixD(-1,msize,-1,msize);
01244       TMatrixDSym m_sym(-1,msize,m.GetMatrixArray());
01245       TMatrixD mm      = m * m;
01246       TMatrixD mm_sym1 = m_sym * m_sym;
01247       TMatrixD mm_sym2 = m     * m_sym;
01248       TMatrixD mm_sym3 = m_sym * m;
01249       ok &= VerifyMatrixIdentity(mm,mm_sym1,gVerbose,epsilon);
01250       ok &= VerifyMatrixIdentity(mm,mm_sym2,gVerbose,epsilon);
01251       ok &= VerifyMatrixIdentity(mm,mm_sym3,gVerbose,epsilon);
01252     }
01253 
01254     {
01255       if (gVerbose)
01256         cout << "\n  Test n * m_sym == n * m multiplications" << endl;
01257       TMatrixD n = THilbertMatrixD(-1,msize,-1,msize);
01258       TMatrixD m = n;
01259       n(1,3) = TMath::Pi();
01260       n(3,1) = TMath::Pi();
01261       TMatrixDSym m_sym(-1,msize,m.GetMatrixArray());
01262       TMatrixD nm1 = n * m_sym;
01263       TMatrixD nm2 = n * m;
01264       ok &= VerifyMatrixIdentity(nm1,nm2,gVerbose,epsilon);
01265     }
01266   }
01267 
01268   if (ok)
01269   {
01270     if (gVerbose)
01271       cout << "Test inline multiplications by a DiagMatrix" << endl;
01272     TMatrixDSym m = THilbertMatrixDSym(msize);
01273     m(1,3) = TMath::Pi();
01274     m(3,1) = TMath::Pi();
01275     TVectorD v(msize);
01276     for (i = v.GetLwb(); i <= v.GetUpb(); i++)
01277       v(i) = 1+i;
01278     TMatrixDSym diag(msize);
01279     TMatrixDDiag d(diag); d = v;
01280     TMatrixDSym eth = m;
01281     for (i = eth.GetRowLwb(); i <= eth.GetRowUpb(); i++)
01282       for (j = eth.GetColLwb(); j <= eth.GetColUpb(); j++)
01283         eth(i,j) *= v(j);
01284     TMatrixD m2 = m * diag;
01285     ok &= VerifyMatrixIdentity(m2,eth,gVerbose,epsilon);
01286   }
01287 
01288   if (ok)
01289   {
01290     if (gVerbose)
01291       cout << "Test XPP = X where P is a permutation matrix" << endl;
01292     TMatrixDSym m = THilbertMatrixDSym(msize);
01293     m(2,3) = TMath::Pi();
01294     m(3,2) = TMath::Pi();
01295     TMatrixDSym eth = m;
01296     TMatrixDSym p(msize);
01297     for (i = p.GetRowLwb(); i <= p.GetRowUpb(); i++)
01298       p(p.GetRowUpb()+p.GetRowLwb()-i,i) = 1;
01299     TMatrixD m2 = m * p;
01300     m2 *= p;
01301     ok &= VerifyMatrixIdentity(m2,eth,gVerbose,epsilon);
01302   }
01303 
01304   if (ok)
01305   {
01306     if (gVerbose)
01307       cout << "Test general matrix multiplication through inline mult" << endl;
01308     TMatrixDSym m = THilbertMatrixDSym(msize);
01309     m(2,3) = TMath::Pi();
01310     m(3,2) = TMath::Pi();
01311     TMatrixDSym mt(TMatrixDSym::kTransposed,m);
01312     TMatrixDSym p = THilbertMatrixDSym(msize);
01313     TMatrixDDiag(p) += 1;
01314     TMatrixD mp(m,TMatrixD::kMult,p);
01315     TMatrixDSym m1 = m;
01316     TMatrixD m3(m,TMatrixD::kMult,p);
01317     memcpy(m.GetMatrixArray(),m3.GetMatrixArray(),msize*msize*sizeof(Double_t));
01318     ok &= VerifyMatrixIdentity(m,mp,gVerbose,epsilon);
01319     TMatrixD mp1(mt,TMatrixD::kTransposeMult,p);
01320     ok &= VerifyMatrixIdentity(m,mp1,gVerbose,epsilon);
01321     ok &= ( !(m1 == m) ) ? kTRUE : kFALSE;
01322     TMatrixDSym mp2(TMatrixDSym::kZero,m);
01323     ok &= ( mp2 == 0 ) ? kTRUE : kFALSE;
01324 
01325     if (gVerbose)
01326       cout << "Test XP=X*P  vs XP=X;XP*=P" << endl;
01327     TMatrixD mp3 = m1*p;
01328     ok &= VerifyMatrixIdentity(m,mp3,gVerbose,epsilon);
01329   }
01330 
01331   if (ok)
01332   {
01333     if (gVerbose)
01334       cout << "Check to see UU' = U'U = E when U is the Haar matrix" << endl;
01335     {
01336       const Int_t order = 5;
01337       const Int_t no_sub_cols = (1<<order)-5;
01338       TMatrixD haarb = THaarMatrixD(5,no_sub_cols);
01339       TMatrixD haarb_t(TMatrixD::kTransposed,haarb);
01340       TMatrixD hth(haarb_t,TMatrixD::kMult,haarb);
01341       TMatrixDSym  hth1(TMatrixDSym::kAtA,haarb);
01342       ok &= VerifyMatrixIdentity(hth,hth1,gVerbose,epsilon);
01343     }
01344 
01345     {
01346       TMatrixD haar = THaarMatrixD(5);
01347       TMatrixD unit(TMatrixD::kUnit,haar);
01348       TMatrixD haar_t(TMatrixD::kTransposed,haar);
01349       TMatrixDSym  hth(TMatrixDSym::kAtA,haar);
01350       TMatrixD hht(haar,TMatrixD::kMult,haar_t);
01351       TMatrixD hht1 = haar; hht1 *= haar_t;
01352       ok &= VerifyMatrixIdentity(unit,hth,gVerbose,epsilon);
01353       ok &= VerifyMatrixIdentity(unit,hht,gVerbose,epsilon);
01354       ok &= VerifyMatrixIdentity(unit,hht1,gVerbose,epsilon);
01355     }
01356   }
01357 
01358   if (gVerbose)
01359     cout << "\nDone\n" << endl;
01360 
01361   StatusPrint(11,"Symmetric Matrix Multiplications",ok);
01362 }
01363 
01364 //
01365 //------------------------------------------------------------------------
01366 //               Verify vector-matrix multiplications
01367 //
01368 void stress_vm_multiplications(Int_t msize)
01369 {
01370   if (gVerbose)
01371     cout << "\n---> Verify vector-matrix multiplications "
01372            "for matrices of the characteristic size " << msize << endl;
01373 
01374   const Double_t epsilon = EPSILON*msize/100;
01375 
01376   Bool_t ok = kTRUE;
01377   {
01378     if (gVerbose)
01379       cout << "\nCheck shrinking a vector by multiplying by a non-sq unit matrix" << endl;
01380     TVectorD vb(-2,msize);
01381     for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
01382       vb(i) = TMath::Pi()-i;
01383     ok &= ( vb != 0 ) ? kTRUE : kFALSE;
01384     TMatrixD mc(1,msize-2,-2,msize);       // contracting matrix
01385     mc.UnitMatrix();
01386     TVectorD v1 = vb;
01387     TVectorD v2 = vb;
01388     v1 *= mc;
01389     v2.ResizeTo(1,msize-2);
01390     ok &= VerifyVectorIdentity(v1,v2,gVerbose,epsilon);
01391   }
01392 
01393   {
01394     if (gVerbose)
01395       cout << "Check expanding a vector by multiplying by a non-sq unit matrix" << endl;
01396     TVectorD vb(msize);
01397     for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
01398       vb(i) = TMath::Pi()+i;
01399     ok &= ( vb != 0 ) ? kTRUE : kFALSE;
01400     TMatrixD me(2,msize+5,0,msize-1);    // expanding matrix
01401     me.UnitMatrix();
01402     TVectorD v1 = vb;
01403     TVectorD v2 = vb;
01404     v1 *= me;
01405     v2.ResizeTo(v1);
01406     ok &= VerifyVectorIdentity(v1,v2,gVerbose,epsilon);
01407   }
01408 
01409   {
01410     if (gVerbose)
01411       cout << "Check general matrix-vector multiplication" << endl;
01412     TVectorD vb(msize);
01413     for (Int_t i = vb.GetLwb(); i <= vb.GetUpb(); i++)
01414       vb(i) = TMath::Pi()+i;
01415     TMatrixD vm(msize,1);
01416     TMatrixDColumn(vm,0) = vb;
01417     TMatrixD m = THilbertMatrixD(0,msize,0,msize-1);
01418     vb *= m;
01419     ok &= ( vb.GetLwb() == 0 ) ? kTRUE : kFALSE;
01420     TMatrixD mvm(m,TMatrixD::kMult,vm);
01421     TMatrixD mvb(msize+1,1);
01422     TMatrixDColumn(mvb,0) = vb;
01423     ok &= VerifyMatrixIdentity(mvb,mvm,gVerbose,epsilon);
01424   }
01425 
01426   if (gVerbose)
01427     cout << "\nDone\n" << endl;
01428 
01429   StatusPrint(12,"Matrix Vector Multiplications",ok);
01430 }
01431 
01432 //
01433 //------------------------------------------------------------------------
01434 //               Verify matrix inversion
01435 //
01436 void stress_inversion(Int_t msize)
01437 {
01438   if (gVerbose)
01439     cout << "\n---> Verify matrix inversion for square matrices of size " << msize << endl;
01440 
01441   const Double_t epsilon = EPSILON*msize/10;
01442 
01443   Bool_t ok = kTRUE;
01444   {
01445     if (gVerbose)
01446       cout << "\nTest inversion of a diagonal matrix" << endl;
01447     TMatrixD m(-1,msize,-1,msize);
01448     TMatrixD mi(TMatrixD::kZero,m);
01449     for (Int_t i = m.GetRowLwb(); i <= m.GetRowUpb(); i++)
01450       mi(i,i) = 1/(m(i,i)=i-m.GetRowLwb()+1);
01451     TMatrixD mi1(TMatrixD::kInverted,m);
01452     m.Invert();
01453     ok &= VerifyMatrixIdentity(m,mi,gVerbose,epsilon);
01454     ok &= VerifyMatrixIdentity(mi1,mi,gVerbose,epsilon);
01455   }
01456 
01457   {
01458     if (gVerbose)
01459       cout << "Test inversion of an orthonormal (Haar) matrix" << endl;
01460     TMatrixD m = THaarMatrixD(3);
01461     TMatrixD morig = m;
01462     TMatrixD mt(TMatrixD::kTransposed,m);
01463     double det = -1;         // init to a wrong val to see if it's changed
01464     m.Invert(&det);
01465     ok &= ( TMath::Abs(det-1) <= msize*epsilon ) ? kTRUE : kFALSE;
01466     ok &= VerifyMatrixIdentity(m,mt,gVerbose,epsilon);
01467     TMatrixD mti(TMatrixD::kInverted,mt);
01468     ok &= VerifyMatrixIdentity(mti,morig,gVerbose,msize*epsilon);
01469   }
01470 
01471   {
01472     if (gVerbose)
01473       cout << "Test inversion of a good matrix with diagonal dominance" << endl;
01474     TMatrixD m = THilbertMatrixD(msize,msize);
01475     TMatrixDDiag(m) += 1;
01476     TMatrixD morig = m;
01477     Double_t det_inv = 0;
01478     const Double_t det_comp = m.Determinant();
01479     m.Invert(&det_inv);
01480     if (gVerbose) {
01481       cout << "\tcomputed determinant             " << det_comp << endl;
01482       cout << "\tdeterminant returned by Invert() " << det_inv << endl;
01483     }
01484 
01485     if (gVerbose)
01486       cout << "\tcheck to see M^(-1) * M is E" << endl;
01487     TMatrixD mim(m,TMatrixD::kMult,morig);
01488     TMatrixD unit(TMatrixD::kUnit,m);
01489     ok &= VerifyMatrixIdentity(mim,unit,gVerbose,epsilon);
01490 
01491     if (gVerbose)
01492       cout << "\tcheck to see M * M^(-1) is E" << endl;
01493     TMatrixD mmi = morig; mmi *= m;
01494     ok &= VerifyMatrixIdentity(mmi,unit,gVerbose,epsilon);
01495   }
01496 
01497   if (gVerbose)
01498     cout << "\nDone\n" << endl;
01499 
01500   StatusPrint(13,"Matrix Inversion",ok);
01501 }
01502 
01503 //
01504 //------------------------------------------------------------------------
01505 //           Test matrix I/O
01506 //
01507 void stress_matrix_io()
01508 {
01509   if (gVerbose)
01510     cout << "\n---> Test matrix I/O" << endl;
01511 
01512   Bool_t ok = kTRUE;
01513   const double pattern = TMath::Pi();
01514 
01515   TMatrixD m(40,40);
01516   m = pattern;
01517 
01518   if (gVerbose)
01519     cout << "\nWrite matrix m to database" << endl;
01520 
01521   TFile *f = new TFile("vmatrix.root", "RECREATE");
01522 
01523   m.Write("m");
01524 
01525   if (gVerbose)
01526     cout << "\nClose database" << endl;
01527   delete f;
01528 
01529   if (gVerbose)
01530     cout << "\nOpen database in read-only mode and read matrix" << endl;
01531   TFile *f1 = new TFile("vmatrix.root");
01532 
01533   TMatrixD *mr = (TMatrixD*) f1->Get("m");
01534 
01535   if (gVerbose)
01536     cout << "\nRead matrix should be same as original still in memory" << endl;
01537   ok &= ((*mr) == m) ? kTRUE : kFALSE;
01538 
01539   delete f1;
01540 
01541   if (gVerbose)
01542     cout << "\nDone\n" << endl;
01543 
01544   StatusPrint(14,"Matrix Persistence",ok);
01545 }

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