00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
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
00125
00126
00127
00128
00129
00130
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
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
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
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 );
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
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
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
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);
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
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
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
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
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
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
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);
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);
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
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;
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
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 }