TMatrixT.cxx

Go to the documentation of this file.
00001 // @(#)root/matrix:$Id: TMatrixT.cxx 35998 2010-10-01 12:47:38Z brun $
00002 // Authors: Fons Rademakers, Eddy Offermann   Nov 2003
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TMatrixT                                                             //
00015 //                                                                      //
00016 // Template class of a general matrix in the linear algebra package     //
00017 //                                                                      //
00018 //////////////////////////////////////////////////////////////////////////
00019 
00020 #include <iostream>
00021 #include <typeinfo>
00022 
00023 #include "TMatrixT.h"
00024 #include "TMatrixTSym.h"
00025 #include "TMatrixTLazy.h"
00026 #include "TMatrixTCramerInv.h"
00027 #include "TDecompLU.h"
00028 #include "TMatrixDEigen.h"
00029 #include "TClass.h"
00030 #include "TMath.h"
00031 
00032 #ifndef R__ALPHA
00033 templateClassImp(TMatrixT)
00034 #endif
00035 //______________________________________________________________________________
00036 template<class Element>
00037 TMatrixT<Element>::TMatrixT(Int_t nrows,Int_t ncols)
00038 {
00039 // Constructor for (nrows x ncols) matrix
00040 
00041    Allocate(nrows,ncols,0,0,1);
00042 }
00043 
00044 //______________________________________________________________________________
00045 template<class Element>
00046 TMatrixT<Element>::TMatrixT(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb)
00047 {
00048 // Constructor for ([row_lwb..row_upb] x [col_lwb..col_upb]) matrix
00049 
00050    Allocate(row_upb-row_lwb+1,col_upb-col_lwb+1,row_lwb,col_lwb,1);
00051 }
00052 
00053 //______________________________________________________________________________
00054 template<class Element>
00055 TMatrixT<Element>::TMatrixT(Int_t no_rows,Int_t no_cols,const Element *elements,Option_t *option)
00056 {
00057 // option="F": array elements contains the matrix stored column-wise
00058 //             like in Fortran, so a[i,j] = elements[i+no_rows*j],
00059 // else        it is supposed that array elements are stored row-wise
00060 //             a[i,j] = elements[i*no_cols+j]
00061 //
00062 // array elements are copied
00063 
00064    Allocate(no_rows,no_cols);
00065    TMatrixTBase<Element>::SetMatrixArray(elements,option);
00066 }
00067 
00068 //______________________________________________________________________________
00069 template<class Element>
00070 TMatrixT<Element>::TMatrixT(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,
00071                             const Element *elements,Option_t *option)
00072 {
00073 // array elements are copied
00074 
00075    Allocate(row_upb-row_lwb+1,col_upb-col_lwb+1,row_lwb,col_lwb);
00076    TMatrixTBase<Element>::SetMatrixArray(elements,option);
00077 }
00078 
00079 //______________________________________________________________________________
00080 template<class Element>
00081 TMatrixT<Element>::TMatrixT(const TMatrixT<Element> &another) : TMatrixTBase<Element>(another)
00082 {
00083 // Copy constructor
00084 
00085    R__ASSERT(another.IsValid());
00086    Allocate(another.GetNrows(),another.GetNcols(),another.GetRowLwb(),another.GetColLwb());
00087    *this = another;
00088 }
00089 
00090 //______________________________________________________________________________
00091 template<class Element>
00092 TMatrixT<Element>::TMatrixT(const TMatrixTSym<Element> &another)
00093 {
00094 // Copy constructor of a symmetric matrix
00095 
00096    R__ASSERT(another.IsValid());
00097    Allocate(another.GetNrows(),another.GetNcols(),another.GetRowLwb(),another.GetColLwb());
00098    *this = another;
00099 }
00100 
00101 //______________________________________________________________________________
00102 template<class Element>
00103 TMatrixT<Element>::TMatrixT(const TMatrixTSparse<Element> &another)
00104 {
00105 // Copy constructor of a sparse matrix
00106 
00107    R__ASSERT(another.IsValid());
00108    Allocate(another.GetNrows(),another.GetNcols(),another.GetRowLwb(),another.GetColLwb());
00109    *this = another;
00110 }
00111 
00112 //______________________________________________________________________________
00113 template<class Element>
00114 TMatrixT<Element>::TMatrixT(EMatrixCreatorsOp1 op,const TMatrixT<Element> &prototype)
00115 {
00116 // Constructor of matrix applying a specific operation to the prototype.
00117 // Example: TMatrixT<Element> a(10,12); ...; TMatrixT<Element> b(TMatrixT::kTransposed, a);
00118 // Supported operations are: kZero, kUnit, kTransposed, kInverted and kAtA.
00119 
00120    R__ASSERT(prototype.IsValid());
00121 
00122    switch(op) {
00123       case kZero:
00124          Allocate(prototype.GetNrows(),prototype.GetNcols(),
00125                   prototype.GetRowLwb(),prototype.GetColLwb(),1);
00126          break;
00127 
00128       case kUnit:
00129          Allocate(prototype.GetNrows(),prototype.GetNcols(),
00130                   prototype.GetRowLwb(),prototype.GetColLwb(),1);
00131          this->UnitMatrix();
00132          break;
00133 
00134       case kTransposed:
00135          Allocate(prototype.GetNcols(), prototype.GetNrows(),
00136                   prototype.GetColLwb(),prototype.GetRowLwb());
00137          Transpose(prototype);
00138          break;
00139 
00140       case kInverted:
00141       {
00142          Allocate(prototype.GetNrows(),prototype.GetNcols(),
00143                   prototype.GetRowLwb(),prototype.GetColLwb(),1);
00144          *this = prototype;
00145          // Since the user can not control the tolerance of this newly created matrix
00146          // we put it to the smallest possible number
00147          const Element oldTol = this->SetTol(std::numeric_limits<Element>::min());
00148          this->Invert();
00149          this->SetTol(oldTol);
00150          break;
00151       }
00152 
00153       case kAtA:
00154          Allocate(prototype.GetNcols(),prototype.GetNcols(),prototype.GetColLwb(),prototype.GetColLwb(),1);
00155          TMult(prototype,prototype);
00156          break;
00157 
00158       default:
00159          Error("TMatrixT(EMatrixCreatorOp1)", "operation %d not yet implemented", op);
00160    }
00161 }
00162 
00163 //______________________________________________________________________________
00164 template<class Element>
00165 TMatrixT<Element>::TMatrixT(const TMatrixT<Element> &a,EMatrixCreatorsOp2 op,const TMatrixT<Element> &b)
00166 {
00167 // Constructor of matrix applying a specific operation to two prototypes.
00168 // Example: TMatrixT<Element> a(10,12), b(12,5); ...; TMatrixT<Element> c(a, TMatrixT::kMult, b);
00169 // Supported operations are: kMult (a*b), kTransposeMult (a'*b), kInvMult (a^(-1)*b)
00170 
00171    R__ASSERT(a.IsValid());
00172    R__ASSERT(b.IsValid());
00173 
00174    switch(op) {
00175       case kMult:
00176          Allocate(a.GetNrows(),b.GetNcols(),a.GetRowLwb(),b.GetColLwb(),1);
00177          Mult(a,b);
00178          break;
00179 
00180       case kTransposeMult:
00181          Allocate(a.GetNcols(),b.GetNcols(),a.GetColLwb(),b.GetColLwb(),1);
00182          TMult(a,b);
00183          break;
00184 
00185       case kMultTranspose:
00186          Allocate(a.GetNrows(),b.GetNrows(),a.GetRowLwb(),b.GetRowLwb(),1);
00187          MultT(a,b);
00188          break;
00189 
00190       case kInvMult:
00191       {
00192          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00193          *this = a;
00194          const Element oldTol = this->SetTol(std::numeric_limits<Element>::min());
00195          this->Invert();
00196          this->SetTol(oldTol);
00197          *this *= b;
00198          break;
00199       }
00200 
00201       case kPlus:
00202       {
00203          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00204          Plus(a,b);
00205          break;
00206       }
00207 
00208       case kMinus:
00209       {
00210          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00211          Minus(a,b);
00212          break;
00213       }
00214 
00215       default:
00216          Error("TMatrixT(EMatrixCreatorOp2)", "operation %d not yet implemented", op);
00217    }
00218 }
00219 
00220 //______________________________________________________________________________
00221 template<class Element>
00222 TMatrixT<Element>::TMatrixT(const TMatrixT<Element> &a,EMatrixCreatorsOp2 op,const TMatrixTSym<Element> &b)
00223 {
00224 // Constructor of matrix applying a specific operation to two prototypes.
00225 // Example: TMatrixT<Element> a(10,12), b(12,5); ...; TMatrixT<Element> c(a, TMatrixT::kMult, b);
00226 // Supported operations are: kMult (a*b), kTransposeMult (a'*b), kInvMult (a^(-1)*b)
00227 
00228    R__ASSERT(a.IsValid());
00229    R__ASSERT(b.IsValid());
00230 
00231    switch(op) {
00232       case kMult:
00233          Allocate(a.GetNrows(),b.GetNcols(),a.GetRowLwb(),b.GetColLwb(),1);
00234          Mult(a,b);
00235          break;
00236 
00237       case kTransposeMult:
00238          Allocate(a.GetNcols(),b.GetNcols(),a.GetColLwb(),b.GetColLwb(),1);
00239          TMult(a,b);
00240          break;
00241 
00242       case kMultTranspose:
00243          Allocate(a.GetNrows(),b.GetNrows(),a.GetRowLwb(),b.GetRowLwb(),1);
00244          MultT(a,b);
00245          break;
00246 
00247       case kInvMult:
00248       {
00249          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00250          *this = a;
00251          const Element oldTol = this->SetTol(std::numeric_limits<Element>::min());
00252          this->Invert();
00253          this->SetTol(oldTol);
00254          *this *= b;
00255          break;
00256       }
00257 
00258       case kPlus:
00259       {
00260          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00261          Plus(a,b);
00262          break;
00263       }
00264 
00265       case kMinus:
00266       {
00267          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00268          Minus(a,b);
00269          break;
00270       }
00271 
00272       default:
00273          Error("TMatrixT(EMatrixCreatorOp2)", "operation %d not yet implemented", op);
00274    }
00275 }
00276 
00277 //______________________________________________________________________________
00278 template<class Element>
00279 TMatrixT<Element>::TMatrixT(const TMatrixTSym<Element> &a,EMatrixCreatorsOp2 op,const TMatrixT<Element> &b)
00280 {
00281 // Constructor of matrix applying a specific operation to two prototypes.
00282 // Example: TMatrixT<Element> a(10,12), b(12,5); ...; TMatrixT<Element> c(a, TMatrixT::kMult, b);
00283 // Supported operations are: kMult (a*b), kTransposeMult (a'*b), kInvMult (a^(-1)*b)
00284 
00285    R__ASSERT(a.IsValid());
00286    R__ASSERT(b.IsValid());
00287 
00288    switch(op) {
00289       case kMult:
00290          Allocate(a.GetNrows(),b.GetNcols(),a.GetRowLwb(),b.GetColLwb(),1);
00291          Mult(a,b);
00292          break;
00293 
00294       case kTransposeMult:
00295          Allocate(a.GetNcols(),b.GetNcols(),a.GetColLwb(),b.GetColLwb(),1);
00296          TMult(a,b);
00297          break;
00298 
00299       case kMultTranspose:
00300          Allocate(a.GetNrows(),b.GetNrows(),a.GetRowLwb(),b.GetRowLwb(),1);
00301          MultT(a,b);
00302          break;
00303 
00304       case kInvMult:
00305       {
00306          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00307          *this = a;
00308          const Element oldTol = this->SetTol(std::numeric_limits<Element>::min());
00309          this->Invert();
00310          this->SetTol(oldTol);
00311          *this *= b;
00312          break;
00313       }
00314 
00315       case kPlus:
00316       {
00317          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00318          Plus(a,b);
00319          break;
00320       }
00321 
00322       case kMinus:
00323       {
00324          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00325          Minus(a,b);
00326          break;
00327       }
00328 
00329       default:
00330          Error("TMatrixT(EMatrixCreatorOp2)", "operation %d not yet implemented", op);
00331    }
00332 }
00333 
00334 //______________________________________________________________________________
00335 template<class Element>
00336 TMatrixT<Element>::TMatrixT(const TMatrixTSym<Element> &a,EMatrixCreatorsOp2 op,const TMatrixTSym<Element> &b)
00337 {
00338 // Constructor of matrix applying a specific operation to two prototypes.
00339 // Example: TMatrixT<Element> a(10,12), b(12,5); ...; TMatrixT<Element> c(a, TMatrixT::kMult, b);
00340 // Supported operations are: kMult (a*b), kTransposeMult (a'*b), kInvMult (a^(-1)*b)
00341 
00342    R__ASSERT(a.IsValid());
00343    R__ASSERT(b.IsValid());
00344 
00345    switch(op) {
00346       case kMult:
00347          Allocate(a.GetNrows(),b.GetNcols(),a.GetRowLwb(),b.GetColLwb(),1);
00348          Mult(a,b);
00349          break;
00350 
00351       case kTransposeMult:
00352          Allocate(a.GetNcols(),b.GetNcols(),a.GetColLwb(),b.GetColLwb(),1);
00353          TMult(a,b);
00354          break;
00355 
00356       case kMultTranspose:
00357          Allocate(a.GetNrows(),b.GetNrows(),a.GetRowLwb(),b.GetRowLwb(),1);
00358          MultT(a,b);
00359          break;
00360 
00361       case kInvMult:
00362       {
00363          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00364          *this = a;
00365          const Element oldTol = this->SetTol(std::numeric_limits<Element>::min());
00366          this->Invert();
00367          this->SetTol(oldTol);
00368          *this *= b;
00369          break;
00370       }
00371 
00372       case kPlus:
00373       {
00374          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00375          Plus(*dynamic_cast<const TMatrixT<Element> *>(&a),b);
00376          break;
00377       }
00378 
00379       case kMinus:
00380       {
00381          Allocate(a.GetNrows(),a.GetNcols(),a.GetRowLwb(),a.GetColLwb(),1);
00382          Minus(*dynamic_cast<const TMatrixT<Element> *>(&a),b);
00383          break;
00384       }
00385 
00386       default:
00387          Error("TMatrixT(EMatrixCreatorOp2)", "operation %d not yet implemented", op);
00388    }
00389 }
00390 
00391 //______________________________________________________________________________
00392 template<class Element>
00393 TMatrixT<Element>::TMatrixT(const TMatrixTLazy<Element> &lazy_constructor)
00394 {
00395 // Constructor using the TMatrixTLazy class
00396 
00397    Allocate(lazy_constructor.GetRowUpb()-lazy_constructor.GetRowLwb()+1,
00398             lazy_constructor.GetColUpb()-lazy_constructor.GetColLwb()+1,
00399             lazy_constructor.GetRowLwb(),lazy_constructor.GetColLwb(),1);
00400    lazy_constructor.FillIn(*this);
00401 }
00402 
00403 //______________________________________________________________________________
00404 template<class Element>
00405 void TMatrixT<Element>::Delete_m(Int_t size,Element *&m)
00406 {
00407 // Delete data pointer m, if it was assigned on the heap
00408 
00409    if (m) {
00410       if (size > this->kSizeMax)
00411          delete [] m;
00412       m = 0;
00413    }
00414 }
00415 
00416 //______________________________________________________________________________
00417 template<class Element>
00418 Element* TMatrixT<Element>::New_m(Int_t size)
00419 {
00420 // Return data pointer . if requested size <= kSizeMax, assign pointer
00421 // to the stack space
00422 
00423    if (size == 0) return 0;
00424    else {
00425       if ( size <= this->kSizeMax )
00426          return fDataStack;
00427       else {
00428          Element *heap = new Element[size];
00429          return heap;
00430       }
00431    }
00432 }
00433 
00434 //______________________________________________________________________________
00435 template<class Element>
00436 Int_t TMatrixT<Element>::Memcpy_m(Element *newp,const Element *oldp,Int_t copySize,
00437                                   Int_t newSize,Int_t oldSize)
00438 {
00439 // Copy copySize doubles from *oldp to *newp . However take care of the
00440 // situation where both pointers are assigned to the same stack space
00441 
00442    if (copySize == 0 || oldp == newp)
00443       return 0;
00444    else {
00445       if ( newSize <= this->kSizeMax && oldSize <= this->kSizeMax ) {
00446          // both pointers are inside fDataStack, be careful with copy direction !
00447          if (newp > oldp) {
00448             for (Int_t i = copySize-1; i >= 0; i--)
00449                newp[i] = oldp[i];
00450          } else {
00451             for (Int_t i = 0; i < copySize; i++)
00452                newp[i] = oldp[i];
00453          }
00454       }
00455       else
00456          memcpy(newp,oldp,copySize*sizeof(Element));
00457    }
00458    return 0;
00459 }
00460 
00461 //______________________________________________________________________________
00462 template<class Element>
00463 void TMatrixT<Element>::Allocate(Int_t no_rows,Int_t no_cols,Int_t row_lwb,Int_t col_lwb,
00464                                  Int_t init,Int_t /*nr_nonzeros*/)
00465 {
00466 // Allocate new matrix. Arguments are number of rows, columns, row
00467 // lowerbound (0 default) and column lowerbound (0 default).
00468 
00469    this->fIsOwner = kTRUE;
00470    this->fTol     = std::numeric_limits<Element>::epsilon();
00471    fElements      = 0;
00472    this->fNrows   = 0;
00473    this->fNcols   = 0;
00474    this->fRowLwb  = 0;
00475    this->fColLwb  = 0;
00476    this->fNelems  = 0;
00477 
00478    if (no_rows < 0 || no_cols < 0)
00479    {
00480       Error("Allocate","no_rows=%d no_cols=%d",no_rows,no_cols);
00481       this->Invalidate();
00482       return;
00483    }
00484 
00485    this->MakeValid();
00486    this->fNrows   = no_rows;
00487    this->fNcols   = no_cols;
00488    this->fRowLwb  = row_lwb;
00489    this->fColLwb  = col_lwb;
00490    this->fNelems  = this->fNrows*this->fNcols;
00491 
00492    if (this->fNelems > 0) {
00493       fElements = New_m(this->fNelems);
00494       if (init)
00495          memset(fElements,0,this->fNelems*sizeof(Element));
00496    } else
00497      fElements = 0;
00498 }
00499 
00500 //______________________________________________________________________________
00501 template<class Element>
00502 void TMatrixT<Element>::Plus(const TMatrixT<Element> &a,const TMatrixT<Element> &b)
00503 {
00504 // General matrix summation. Create a matrix C such that C = A + B.
00505 
00506    if (gMatrixCheck) {
00507       if (!AreCompatible(a,b)) {
00508          Error("Plus","matrices not compatible");
00509          return;
00510       }
00511 
00512       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00513          Error("Plus","this->GetMatrixArray() == a.GetMatrixArray()");
00514          return;
00515       }
00516 
00517       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00518          Error("Plus","this->GetMatrixArray() == b.GetMatrixArray()");
00519          return;
00520       }
00521    }
00522 
00523    const Element *       ap      = a.GetMatrixArray();
00524    const Element *       bp      = b.GetMatrixArray();
00525          Element *       cp      = this->GetMatrixArray();
00526    const Element * const cp_last = cp+this->fNelems;
00527 
00528    while (cp < cp_last) {
00529        *cp = *ap++ + *bp++;
00530        cp++;
00531    }
00532 }
00533 
00534 //______________________________________________________________________________
00535 template<class Element>
00536 void TMatrixT<Element>::Plus(const TMatrixT<Element> &a,const TMatrixTSym<Element> &b)
00537 {
00538 // General matrix summation. Create a matrix C such that C = A + B.
00539 
00540    if (gMatrixCheck) {
00541       if (!AreCompatible(a,b)) {
00542          Error("Plus","matrices not compatible");
00543          return;
00544       }
00545 
00546       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00547          Error("Plus","this->GetMatrixArray() == a.GetMatrixArray()");
00548          return;
00549       }
00550 
00551       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00552          Error("Plus","this->GetMatrixArray() == b.GetMatrixArray()");
00553          return;
00554       }
00555    }
00556 
00557    const Element *       ap      = a.GetMatrixArray();
00558    const Element *       bp      = b.GetMatrixArray();
00559          Element *       cp      = this->GetMatrixArray();
00560    const Element * const cp_last = cp+this->fNelems;
00561 
00562    while (cp < cp_last) {
00563        *cp = *ap++ + *bp++;
00564        cp++;
00565    }
00566 }
00567 
00568 //______________________________________________________________________________
00569 template<class Element>
00570 void TMatrixT<Element>::Minus(const TMatrixT<Element> &a,const TMatrixT<Element> &b)
00571 {
00572 // General matrix summation. Create a matrix C such that C = A - B.
00573 
00574    if (gMatrixCheck) {
00575       if (!AreCompatible(a,b)) {
00576          Error("Minus","matrices not compatible");
00577          return;
00578       }
00579 
00580       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00581          Error("Minus","this->GetMatrixArray() == a.GetMatrixArray()");
00582          return;
00583       }
00584 
00585       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00586          Error("Minus","this->GetMatrixArray() == b.GetMatrixArray()");
00587          return;
00588       }
00589    }
00590 
00591    const Element *       ap      = a.GetMatrixArray();
00592    const Element *       bp      = b.GetMatrixArray();
00593          Element *       cp      = this->GetMatrixArray();
00594    const Element * const cp_last = cp+this->fNelems;
00595 
00596    while (cp < cp_last) {
00597       *cp = *ap++ - *bp++;
00598       cp++;
00599    }
00600 }
00601 
00602 //______________________________________________________________________________
00603 template<class Element>
00604 void TMatrixT<Element>::Minus(const TMatrixT<Element> &a,const TMatrixTSym<Element> &b)
00605 {
00606 // General matrix summation. Create a matrix C such that C = A - B.
00607 
00608    if (gMatrixCheck) {
00609       if (!AreCompatible(a,b)) {
00610          Error("Minus","matrices not compatible");
00611          return;
00612       }
00613 
00614       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00615          Error("Minus","this->GetMatrixArray() == a.GetMatrixArray()");
00616          return;
00617       }
00618 
00619       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00620          Error("Minus","this->GetMatrixArray() == b.GetMatrixArray()");
00621          return;
00622       }
00623    }
00624 
00625    const Element *       ap      = a.GetMatrixArray();
00626    const Element *       bp      = b.GetMatrixArray();
00627          Element *       cp      = this->GetMatrixArray();
00628    const Element * const cp_last = cp+this->fNelems;
00629 
00630    while (cp < cp_last) {
00631        *cp = *ap++ - *bp++;
00632        cp++;
00633    }
00634 }
00635 
00636 //______________________________________________________________________________
00637 template<class Element>
00638 void TMatrixT<Element>::Mult(const TMatrixT<Element> &a,const TMatrixT<Element> &b)
00639 {
00640 // General matrix multiplication. Create a matrix C such that C = A * B.
00641 
00642    if (gMatrixCheck) {
00643       if (a.GetNcols() != b.GetNrows() || a.GetColLwb() != b.GetRowLwb()) {
00644          Error("Mult","A rows and B columns incompatible");
00645          return;
00646       }
00647 
00648       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00649          Error("Mult","this->GetMatrixArray() == a.GetMatrixArray()");
00650          return;
00651       }
00652 
00653       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00654          Error("Mult","this->GetMatrixArray() == b.GetMatrixArray()");
00655          return;
00656       }
00657    }
00658 
00659 #ifdef CBLAS
00660    const Element *ap = a.GetMatrixArray();
00661    const Element *bp = b.GetMatrixArray();
00662          Element *cp = this->GetMatrixArray();
00663    if (typeid(Element) == typeid(Double_t))
00664       cblas_dgemm (CblasRowMajor,CblasNoTrans,CblasNoTrans,fNrows,fNcols,a.GetNcols(),
00665                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,fNcols);
00666    else if (typeid(Element) != typeid(Float_t))
00667       cblas_sgemm (CblasRowMajor,CblasNoTrans,CblasNoTrans,fNrows,fNcols,a.GetNcols(),
00668                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,fNcols);
00669    else
00670       Error("Mult","type %s not implemented in BLAS library",typeid(Element));
00671 #else
00672    const Int_t na     = a.GetNoElements();
00673    const Int_t nb     = b.GetNoElements();
00674    const Int_t ncolsa = a.GetNcols();
00675    const Int_t ncolsb = b.GetNcols();
00676    const Element * const ap = a.GetMatrixArray();
00677    const Element * const bp = b.GetMatrixArray();
00678          Element *       cp = this->GetMatrixArray();
00679 
00680    AMultB(ap,na,ncolsa,bp,nb,ncolsb,cp);
00681 #endif
00682 }
00683 
00684 //______________________________________________________________________________
00685 template<class Element>
00686 void TMatrixT<Element>::Mult(const TMatrixTSym<Element> &a,const TMatrixT<Element> &b)
00687 {
00688 // Matrix multiplication, with A symmetric and B general.
00689 // Create a matrix C such that C = A * B.
00690 
00691    if (gMatrixCheck) {
00692       R__ASSERT(a.IsValid());
00693       R__ASSERT(b.IsValid());
00694       if (a.GetNcols() != b.GetNrows() || a.GetColLwb() != b.GetRowLwb()) {
00695          Error("Mult","A rows and B columns incompatible");
00696          return;
00697       }
00698 
00699       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00700          Error("Mult","this->GetMatrixArray() == a.GetMatrixArray()");
00701          return;
00702       }
00703 
00704       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00705          Error("Mult","this->GetMatrixArray() == b.GetMatrixArray()");
00706          return;
00707       }
00708    }
00709 
00710 #ifdef CBLAS
00711    const Element *ap = a.GetMatrixArray();
00712    const Element *bp = b.GetMatrixArray();
00713          Element *cp = this->GetMatrixArray();
00714    if (typeid(Element) == typeid(Double_t))
00715       cblas_dsymm (CblasRowMajor,CblasLeft,CblasUpper,fNrows,fNcols,1.0,
00716                    ap,a.GetNcols(),bp,b.GetNcols(),0.0,cp,fNcols);
00717    else if (typeid(Element) != typeid(Float_t))
00718       cblas_ssymm (CblasRowMajor,CblasLeft,CblasUpper,fNrows,fNcols,1.0,
00719                    ap,a.GetNcols(),bp,b.GetNcols(),0.0,cp,fNcols);
00720    else
00721       Error("Mult","type %s not implemented in BLAS library",typeid(Element));
00722 #else
00723    const Int_t na     = a.GetNoElements();
00724    const Int_t nb     = b.GetNoElements();
00725    const Int_t ncolsa = a.GetNcols();
00726    const Int_t ncolsb = b.GetNcols();
00727    const Element * const ap = a.GetMatrixArray();
00728    const Element * const bp = b.GetMatrixArray();
00729          Element *       cp = this->GetMatrixArray();
00730 
00731    AMultB(ap,na,ncolsa,bp,nb,ncolsb,cp);
00732 
00733 #endif
00734 }
00735 
00736 //______________________________________________________________________________
00737 template<class Element>
00738 void TMatrixT<Element>::Mult(const TMatrixT<Element> &a,const TMatrixTSym<Element> &b)
00739 {
00740 // Matrix multiplication, with A general and B symmetric.
00741 // Create a matrix C such that C = A * B.
00742 
00743    if (gMatrixCheck) {
00744       R__ASSERT(a.IsValid());
00745       R__ASSERT(b.IsValid());
00746       if (a.GetNcols() != b.GetNrows() || a.GetColLwb() != b.GetRowLwb()) {
00747          Error("Mult","A rows and B columns incompatible");
00748          return;
00749       }
00750 
00751       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00752          Error("Mult","this->GetMatrixArray() == a.GetMatrixArray()");
00753          return;
00754       }
00755 
00756       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00757          Error("Mult","this->GetMatrixArray() == b.GetMatrixArray()");
00758          return;
00759       }
00760    }
00761 
00762 #ifdef CBLAS
00763    const Element *ap = a.GetMatrixArray();
00764    const Element *bp = b.GetMatrixArray();
00765          Element *cp = this->GetMatrixArray();
00766    if (typeid(Element) == typeid(Double_t))
00767       cblas_dsymm (CblasRowMajor,CblasRight,CblasUpper,fNrows,fNcols,1.0,
00768                    bp,b.GetNcols(),ap,a.GetNcols(),0.0,cp,fNcols);
00769    else if (typeid(Element) != typeid(Float_t))
00770       cblas_ssymm (CblasRowMajor,CblasRight,CblasUpper,fNrows,fNcols,1.0,
00771                    bp,b.GetNcols(),ap,a.GetNcols(),0.0,cp,fNcols);
00772    else
00773       Error("Mult","type %s not implemented in BLAS library",typeid(Element));
00774 #else
00775    const Int_t na     = a.GetNoElements();
00776    const Int_t nb     = b.GetNoElements();
00777    const Int_t ncolsa = a.GetNcols();
00778    const Int_t ncolsb = b.GetNcols();
00779    const Element * const ap = a.GetMatrixArray();
00780    const Element * const bp = b.GetMatrixArray();
00781          Element *       cp = this->GetMatrixArray();
00782 
00783    AMultB(ap,na,ncolsa,bp,nb,ncolsb,cp);
00784 #endif
00785 }
00786 
00787 //______________________________________________________________________________
00788 template<class Element>
00789 void TMatrixT<Element>::Mult(const TMatrixTSym<Element> &a,const TMatrixTSym<Element> &b)
00790 {
00791 // Matrix multiplication, with A symmetric and B symmetric.
00792 // (Actually copied for the moment routine for B general)
00793 // Create a matrix C such that C = A * B.
00794 
00795    if (gMatrixCheck) {
00796       R__ASSERT(a.IsValid());
00797       R__ASSERT(b.IsValid());
00798       if (a.GetNcols() != b.GetNrows() || a.GetColLwb() != b.GetRowLwb()) {
00799          Error("Mult","A rows and B columns incompatible");
00800          return;
00801       }
00802 
00803       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00804          Error("Mult","this->GetMatrixArray() == a.GetMatrixArray()");
00805          return;
00806       }
00807 
00808       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00809          Error("Mult","this->GetMatrixArray() == b.GetMatrixArray()");
00810          return;
00811       }
00812    }
00813 
00814 #ifdef CBLAS
00815    const Element *ap = a.GetMatrixArray();
00816    const Element *bp = b.GetMatrixArray();
00817          Element *cp = this->GetMatrixArray();
00818    if (typeid(Element) == typeid(Double_t))
00819       cblas_dsymm (CblasRowMajor,CblasLeft,CblasUpper,fNrows,fNcols,1.0,
00820                    ap,a.GetNcols(),bp,b.GetNcols(),0.0,cp,fNcols);
00821    else if (typeid(Element) != typeid(Float_t))
00822       cblas_ssymm (CblasRowMajor,CblasLeft,CblasUpper,fNrows,fNcols,1.0,
00823                    ap,a.GetNcols(),bp,b.GetNcols(),0.0,cp,fNcols);
00824    else
00825       Error("Mult","type %s not implemented in BLAS library",typeid(Element));
00826 #else
00827    const Int_t na     = a.GetNoElements();
00828    const Int_t nb     = b.GetNoElements();
00829    const Int_t ncolsa = a.GetNcols();
00830    const Int_t ncolsb = b.GetNcols();
00831    const Element * const ap = a.GetMatrixArray();
00832    const Element * const bp = b.GetMatrixArray();
00833          Element *       cp = this->GetMatrixArray();
00834 
00835    AMultB(ap,na,ncolsa,bp,nb,ncolsb,cp);
00836 #endif
00837 }
00838 
00839 //______________________________________________________________________________
00840 template<class Element>
00841 void TMatrixT<Element>::TMult(const TMatrixT<Element> &a,const TMatrixT<Element> &b)
00842 {
00843 // Create a matrix C such that C = A' * B. In other words,
00844 // c[i,j] = SUM{ a[k,i] * b[k,j] }.
00845 
00846    if (gMatrixCheck) {
00847       R__ASSERT(a.IsValid());
00848       R__ASSERT(b.IsValid());
00849       if (a.GetNrows() != b.GetNrows() || a.GetRowLwb() != b.GetRowLwb()) {
00850          Error("TMult","A rows and B columns incompatible");
00851          return;
00852       }
00853 
00854       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00855          Error("TMult","this->GetMatrixArray() == a.GetMatrixArray()");
00856          return;
00857       }
00858 
00859       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00860          Error("TMult","this->GetMatrixArray() == b.GetMatrixArray()");
00861          return;
00862       }
00863    }
00864 
00865 #ifdef CBLAS
00866    const Element *ap = a.GetMatrixArray();
00867    const Element *bp = b.GetMatrixArray();
00868          Element *cp = this->GetMatrixArray();
00869    if (typeid(Element) == typeid(Double_t))
00870       cblas_dgemm (CblasRowMajor,CblasTrans,CblasNoTrans,this->fNrows,this->fNcols,a.GetNrows(),
00871                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,this->fNcols);
00872    else if (typeid(Element) != typeid(Float_t))
00873       cblas_sgemm (CblasRowMajor,CblasTrans,CblasNoTrans,fNrows,fNcols,a.GetNrows(),
00874                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,fNcols);
00875    else
00876       Error("TMult","type %s not implemented in BLAS library",typeid(Element));
00877 #else
00878    const Int_t nb     = b.GetNoElements();
00879    const Int_t ncolsa = a.GetNcols();
00880    const Int_t ncolsb = b.GetNcols();
00881    const Element * const ap = a.GetMatrixArray();
00882    const Element * const bp = b.GetMatrixArray();
00883          Element *       cp = this->GetMatrixArray();
00884 
00885    AtMultB(ap,ncolsa,bp,nb,ncolsb,cp);
00886 #endif
00887 }
00888 
00889 //______________________________________________________________________________
00890 template<class Element>
00891 void TMatrixT<Element>::TMult(const TMatrixT<Element> &a,const TMatrixTSym<Element> &b)
00892 {
00893 // Create a matrix C such that C = A' * B. In other words,
00894 // c[i,j] = SUM{ a[k,i] * b[k,j] }.
00895 
00896    if (gMatrixCheck) {
00897       R__ASSERT(a.IsValid());
00898       R__ASSERT(b.IsValid());
00899       if (a.GetNrows() != b.GetNrows() || a.GetRowLwb() != b.GetRowLwb()) {
00900          Error("TMult","A rows and B columns incompatible");
00901          return;
00902       }
00903 
00904       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00905          Error("TMult","this->GetMatrixArray() == a.GetMatrixArray()");
00906          return;
00907       }
00908 
00909       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00910          Error("TMult","this->GetMatrixArray() == b.GetMatrixArray()");
00911          return;
00912       }
00913    }
00914 
00915 #ifdef CBLAS
00916    const Element *ap = a.GetMatrixArray();
00917    const Element *bp = b.GetMatrixArray();
00918          Element *cp = this->GetMatrixArray();
00919    if (typeid(Element) == typeid(Double_t))
00920       cblas_dgemm (CblasRowMajor,CblasTrans,CblasNoTrans,fNrows,fNcols,a.GetNrows(),
00921                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,fNcols);
00922    else if (typeid(Element) != typeid(Float_t))
00923       cblas_sgemm (CblasRowMajor,CblasTrans,CblasNoTrans,fNrows,fNcols,a.GetNrows(),
00924                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,fNcols);
00925    else
00926       Error("TMult","type %s not implemented in BLAS library",typeid(Element));
00927 #else
00928    const Int_t nb     = b.GetNoElements();
00929    const Int_t ncolsa = a.GetNcols();
00930    const Int_t ncolsb = b.GetNcols();
00931    const Element * const ap = a.GetMatrixArray();
00932    const Element * const bp = b.GetMatrixArray();
00933          Element *       cp = this->GetMatrixArray();
00934 
00935    AtMultB(ap,ncolsa,bp,nb,ncolsb,cp);
00936 #endif
00937 }
00938 
00939 //______________________________________________________________________________
00940 template<class Element>
00941 void TMatrixT<Element>::MultT(const TMatrixT<Element> &a,const TMatrixT<Element> &b)
00942 {
00943 // General matrix multiplication. Create a matrix C such that C = A * B^T.
00944 
00945    if (gMatrixCheck) {
00946       R__ASSERT(a.IsValid());
00947       R__ASSERT(b.IsValid());
00948 
00949       if (a.GetNcols() != b.GetNcols() || a.GetColLwb() != b.GetColLwb()) {
00950          Error("MultT","A rows and B columns incompatible");
00951          return;
00952       }
00953 
00954       if (this->GetMatrixArray() == a.GetMatrixArray()) {
00955          Error("MultT","this->GetMatrixArray() == a.GetMatrixArray()");
00956          return;
00957       }
00958 
00959       if (this->GetMatrixArray() == b.GetMatrixArray()) {
00960          Error("MultT","this->GetMatrixArray() == b.GetMatrixArray()");
00961          return;
00962       }
00963    }
00964 
00965 #ifdef CBLAS
00966    const Element *ap = a.GetMatrixArray();
00967    const Element *bp = b.GetMatrixArray();
00968          Element *cp = this->GetMatrixArray();
00969    if (typeid(Element) == typeid(Double_t))
00970       cblas_dgemm (CblasRowMajor,CblasNoTrans,CblasTrans,fNrows,fNcols,a.GetNcols(),
00971                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,fNcols);
00972    else if (typeid(Element) != typeid(Float_t))
00973       cblas_sgemm (CblasRowMajor,CblasNoTrans,CblasTrans,fNrows,fNcols,a.GetNcols(),
00974                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,fNcols);
00975    else
00976       Error("MultT","type %s not implemented in BLAS library",typeid(Element));
00977 #else
00978    const Int_t na     = a.GetNoElements();
00979    const Int_t nb     = b.GetNoElements();
00980    const Int_t ncolsa = a.GetNcols();
00981    const Int_t ncolsb = b.GetNcols();
00982    const Element * const ap = a.GetMatrixArray();
00983    const Element * const bp = b.GetMatrixArray();
00984          Element *       cp = this->GetMatrixArray();
00985 
00986    AMultBt(ap,na,ncolsa,bp,nb,ncolsb,cp);
00987 #endif
00988 }
00989 
00990 //______________________________________________________________________________
00991 template<class Element>
00992 void TMatrixT<Element>::MultT(const TMatrixTSym<Element> &a,const TMatrixT<Element> &b)
00993 {
00994 // Matrix multiplication, with A symmetric and B general.
00995 // Create a matrix C such that C = A * B^T.
00996 
00997    if (gMatrixCheck) {
00998       R__ASSERT(a.IsValid());
00999       R__ASSERT(b.IsValid());
01000       if (a.GetNcols() != b.GetNcols() || a.GetColLwb() != b.GetColLwb()) {
01001          Error("MultT","A rows and B columns incompatible");
01002          return;
01003       }
01004 
01005       if (this->GetMatrixArray() == a.GetMatrixArray()) {
01006          Error("MultT","this->GetMatrixArray() == a.GetMatrixArray()");
01007          return;
01008       }
01009 
01010       if (this->GetMatrixArray() == b.GetMatrixArray()) {
01011          Error("MultT","this->GetMatrixArray() == b.GetMatrixArray()");
01012          return;
01013       }
01014    }
01015 
01016 #ifdef CBLAS
01017    const Element *ap = a.GetMatrixArray();
01018    const Element *bp = b.GetMatrixArray();
01019          Element *cp = this->GetMatrixArray();
01020    if (typeid(Element) == typeid(Double_t))
01021       cblas_dgemm (CblasRowMajor,CblasNoTrans,CblasTrans,this->fNrows,this->fNcols,a.GetNcols(),
01022                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,this->fNcols);
01023    else if (typeid(Element) != typeid(Float_t))
01024       cblas_sgemm (CblasRowMajor,CblasNoTrans,CblasTrans,fNrows,fNcols,a.GetNcols(),
01025                    1.0,ap,a.GetNcols(),bp,b.GetNcols(),1.0,cp,fNcols);
01026    else
01027       Error("MultT","type %s not implemented in BLAS library",typeid(Element));
01028 #else
01029    const Int_t na     = a.GetNoElements();
01030    const Int_t nb     = b.GetNoElements();
01031    const Int_t ncolsa = a.GetNcols();
01032    const Int_t ncolsb = b.GetNcols();
01033    const Element * const ap = a.GetMatrixArray();
01034    const Element * const bp = b.GetMatrixArray();
01035          Element *       cp = this->GetMatrixArray();
01036 
01037    AMultBt(ap,na,ncolsa,bp,nb,ncolsb,cp);
01038 #endif
01039 }
01040 
01041 //______________________________________________________________________________
01042 template<class Element>
01043 TMatrixT<Element> &TMatrixT<Element>::Use(Int_t row_lwb,Int_t row_upb,
01044                                           Int_t col_lwb,Int_t col_upb,Element *data)
01045 {
01046 // Use the array data to fill the matrix ([row_lwb..row_upb] x [col_lwb..col_upb])
01047 
01048    if (gMatrixCheck) {
01049       if (row_upb < row_lwb)
01050       {
01051          Error("Use","row_upb=%d < row_lwb=%d",row_upb,row_lwb);
01052          return *this;
01053       }
01054       if (col_upb < col_lwb)
01055       {
01056          Error("Use","col_upb=%d < col_lwb=%d",col_upb,col_lwb);
01057          return *this;
01058       }
01059    }
01060 
01061    Clear();
01062    this->fNrows    = row_upb-row_lwb+1;
01063    this->fNcols    = col_upb-col_lwb+1;
01064    this->fRowLwb   = row_lwb;
01065    this->fColLwb   = col_lwb;
01066    this->fNelems   = this->fNrows*this->fNcols;
01067          fElements = data;
01068    this->fIsOwner  = kFALSE;
01069 
01070    return *this;
01071 }
01072 
01073 //______________________________________________________________________________
01074 template<class Element>
01075 TMatrixTBase<Element> &TMatrixT<Element>::GetSub(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,
01076                                                  TMatrixTBase<Element> &target,Option_t *option) const
01077 {
01078 // Get submatrix [row_lwb..row_upb] x [col_lwb..col_upb]; The indexing range of the
01079 // returned matrix depends on the argument option:
01080 //
01081 // option == "S" : return [0..row_upb-row_lwb+1][0..col_upb-col_lwb+1] (default)
01082 // else          : return [row_lwb..row_upb][col_lwb..col_upb]
01083 
01084    if (gMatrixCheck) {
01085       R__ASSERT(this->IsValid());
01086       if (row_lwb < this->fRowLwb || row_lwb > this->fRowLwb+this->fNrows-1) {
01087          Error("GetSub","row_lwb out of bounds");
01088          return target;
01089       }
01090       if (col_lwb < this->fColLwb || col_lwb > this->fColLwb+this->fNcols-1) {
01091          Error("GetSub","col_lwb out of bounds");
01092          return target;
01093       }
01094       if (row_upb < this->fRowLwb || row_upb > this->fRowLwb+this->fNrows-1) {
01095          Error("GetSub","row_upb out of bounds");
01096          return target;
01097       }
01098       if (col_upb < this->fColLwb || col_upb > this->fColLwb+this->fNcols-1) {
01099          Error("GetSub","col_upb out of bounds");
01100          return target;
01101       }
01102       if (row_upb < row_lwb || col_upb < col_lwb) {
01103          Error("GetSub","row_upb < row_lwb || col_upb < col_lwb");
01104          return target;
01105       }
01106    }
01107 
01108    TString opt(option);
01109    opt.ToUpper();
01110    const Int_t shift = (opt.Contains("S")) ? 1 : 0;
01111 
01112    const Int_t row_lwb_sub = (shift) ? 0               : row_lwb;
01113    const Int_t row_upb_sub = (shift) ? row_upb-row_lwb : row_upb;
01114    const Int_t col_lwb_sub = (shift) ? 0               : col_lwb;
01115    const Int_t col_upb_sub = (shift) ? col_upb-col_lwb : col_upb;
01116 
01117    target.ResizeTo(row_lwb_sub,row_upb_sub,col_lwb_sub,col_upb_sub);
01118    const Int_t nrows_sub = row_upb_sub-row_lwb_sub+1;
01119    const Int_t ncols_sub = col_upb_sub-col_lwb_sub+1;
01120 
01121    if (target.GetRowIndexArray() && target.GetColIndexArray()) {
01122       for (Int_t irow = 0; irow < nrows_sub; irow++) {
01123          for (Int_t icol = 0; icol < ncols_sub; icol++) {
01124             target(irow+row_lwb_sub,icol+col_lwb_sub) = (*this)(row_lwb+irow,col_lwb+icol);
01125          }
01126       }
01127    } else {
01128       const Element *ap = this->GetMatrixArray()+(row_lwb-this->fRowLwb)*this->fNcols+(col_lwb-this->fColLwb);
01129             Element *bp = target.GetMatrixArray();
01130 
01131       for (Int_t irow = 0; irow < nrows_sub; irow++) {
01132          const Element *ap_sub = ap;
01133          for (Int_t icol = 0; icol < ncols_sub; icol++) {
01134             *bp++ = *ap_sub++;
01135          }
01136          ap += this->fNcols;
01137       }
01138    }
01139 
01140    return target;
01141 }
01142 
01143 //______________________________________________________________________________
01144 template<class Element>
01145 TMatrixTBase<Element> &TMatrixT<Element>::SetSub(Int_t row_lwb,Int_t col_lwb,const TMatrixTBase<Element> &source)
01146 {
01147 // Insert matrix source starting at [row_lwb][col_lwb], thereby overwriting the part
01148 // [row_lwb..row_lwb+nrows_source][col_lwb..col_lwb+ncols_source];
01149 
01150    if (gMatrixCheck) {
01151       R__ASSERT(this->IsValid());
01152       R__ASSERT(source.IsValid());
01153 
01154       if (row_lwb < this->fRowLwb || row_lwb > this->fRowLwb+this->fNrows-1) {
01155          Error("SetSub","row_lwb outof bounds");
01156          return *this;
01157       }
01158       if (col_lwb < this->fColLwb || col_lwb > this->fColLwb+this->fNcols-1) {
01159          Error("SetSub","col_lwb outof bounds");
01160          return *this;
01161       }
01162       if (row_lwb+source.GetNrows() > this->fRowLwb+this->fNrows ||
01163             col_lwb+source.GetNcols() > this->fColLwb+this->fNcols) {
01164          Error("SetSub","source matrix too large");
01165          return *this;
01166       }
01167    }
01168 
01169    const Int_t nRows_source = source.GetNrows();
01170    const Int_t nCols_source = source.GetNcols();
01171 
01172    if (source.GetRowIndexArray() && source.GetColIndexArray()) {
01173       const Int_t rowlwb_s = source.GetRowLwb();
01174       const Int_t collwb_s = source.GetColLwb();
01175       for (Int_t irow = 0; irow < nRows_source; irow++) {
01176          for (Int_t icol = 0; icol < nCols_source; icol++) {
01177             (*this)(row_lwb+irow,col_lwb+icol) = source(rowlwb_s+irow,collwb_s+icol);
01178          }
01179       }
01180    } else {
01181       const Element *bp = source.GetMatrixArray();
01182             Element *ap = this->GetMatrixArray()+(row_lwb-this->fRowLwb)*this->fNcols+(col_lwb-this->fColLwb);
01183 
01184       for (Int_t irow = 0; irow < nRows_source; irow++) {
01185          Element *ap_sub = ap;
01186          for (Int_t icol = 0; icol < nCols_source; icol++) {
01187             *ap_sub++ = *bp++;
01188          }
01189          ap += this->fNcols;
01190       }
01191    }
01192 
01193    return *this;
01194 }
01195 
01196 //______________________________________________________________________________
01197 template<class Element>
01198 TMatrixTBase<Element> &TMatrixT<Element>::ResizeTo(Int_t nrows,Int_t ncols,Int_t /*nr_nonzeros*/)
01199 {
01200 // Set size of the matrix to nrows x ncols
01201 // New dynamic elements are created, the overlapping part of the old ones are
01202 // copied to the new structures, then the old elements are deleted.
01203 
01204    R__ASSERT(this->IsValid());
01205    if (!this->fIsOwner) {
01206       Error("ResizeTo(Int_t,Int_t)","Not owner of data array,cannot resize");
01207       return *this;
01208    }
01209 
01210    if (this->fNelems > 0) {
01211       if (this->fNrows == nrows && this->fNcols == ncols)
01212          return *this;
01213       else if (nrows == 0 || ncols == 0) {
01214          this->fNrows = nrows; this->fNcols = ncols;
01215          Clear();
01216          return *this;
01217       }
01218 
01219       Element    *elements_old = GetMatrixArray();
01220       const Int_t nelems_old   = this->fNelems;
01221       const Int_t nrows_old    = this->fNrows;
01222       const Int_t ncols_old    = this->fNcols;
01223 
01224       Allocate(nrows,ncols);
01225       R__ASSERT(this->IsValid());
01226 
01227       Element *elements_new = GetMatrixArray();
01228       // new memory should be initialized but be careful not to wipe out the stack
01229       // storage. Initialize all when old or new storage was on the heap
01230       if (this->fNelems > this->kSizeMax || nelems_old > this->kSizeMax)
01231          memset(elements_new,0,this->fNelems*sizeof(Element));
01232       else if (this->fNelems > nelems_old)
01233          memset(elements_new+nelems_old,0,(this->fNelems-nelems_old)*sizeof(Element));
01234 
01235       // Copy overlap
01236       const Int_t ncols_copy = TMath::Min(this->fNcols,ncols_old);
01237       const Int_t nrows_copy = TMath::Min(this->fNrows,nrows_old);
01238 
01239       const Int_t nelems_new = this->fNelems;
01240       if (ncols_old < this->fNcols) {
01241          for (Int_t i = nrows_copy-1; i >= 0; i--) {
01242             Memcpy_m(elements_new+i*this->fNcols,elements_old+i*ncols_old,ncols_copy,
01243                      nelems_new,nelems_old);
01244             if (this->fNelems <= this->kSizeMax && nelems_old <= this->kSizeMax)
01245                memset(elements_new+i*this->fNcols+ncols_copy,0,(this->fNcols-ncols_copy)*sizeof(Element));
01246          }
01247       } else {
01248          for (Int_t i = 0; i < nrows_copy; i++)
01249             Memcpy_m(elements_new+i*this->fNcols,elements_old+i*ncols_old,ncols_copy,
01250                      nelems_new,nelems_old);
01251       }
01252 
01253       Delete_m(nelems_old,elements_old);
01254    } else {
01255       Allocate(nrows,ncols,0,0,1);
01256    }
01257 
01258    return *this;
01259 }
01260 
01261 //______________________________________________________________________________
01262 template<class Element>
01263 TMatrixTBase<Element> &TMatrixT<Element>::ResizeTo(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,
01264                                                    Int_t /*nr_nonzeros*/)
01265 {
01266 // Set size of the matrix to [row_lwb:row_upb] x [col_lwb:col_upb]
01267 // New dynamic elemenst are created, the overlapping part of the old ones are
01268 // copied to the new structures, then the old elements are deleted.
01269 
01270    R__ASSERT(this->IsValid());
01271    if (!this->fIsOwner) {
01272       Error("ResizeTo(Int_t,Int_t,Int_t,Int_t)","Not owner of data array,cannot resize");
01273       return *this;
01274    }
01275 
01276    const Int_t new_nrows = row_upb-row_lwb+1;
01277    const Int_t new_ncols = col_upb-col_lwb+1;
01278 
01279    if (this->fNelems > 0) {
01280 
01281       if (this->fNrows  == new_nrows  && this->fNcols  == new_ncols &&
01282            this->fRowLwb == row_lwb    && this->fColLwb == col_lwb)
01283           return *this;
01284       else if (new_nrows == 0 || new_ncols == 0) {
01285          this->fNrows = new_nrows; this->fNcols = new_ncols;
01286          this->fRowLwb = row_lwb; this->fColLwb = col_lwb;
01287          Clear();
01288          return *this;
01289       }
01290 
01291       Element    *elements_old = GetMatrixArray();
01292       const Int_t nelems_old   = this->fNelems;
01293       const Int_t nrows_old    = this->fNrows;
01294       const Int_t ncols_old    = this->fNcols;
01295       const Int_t rowLwb_old   = this->fRowLwb;
01296       const Int_t colLwb_old   = this->fColLwb;
01297 
01298       Allocate(new_nrows,new_ncols,row_lwb,col_lwb);
01299       R__ASSERT(this->IsValid());
01300 
01301       Element *elements_new = GetMatrixArray();
01302       // new memory should be initialized but be careful not to wipe out the stack
01303       // storage. Initialize all when old or new storage was on the heap
01304       if (this->fNelems > this->kSizeMax || nelems_old > this->kSizeMax)
01305          memset(elements_new,0,this->fNelems*sizeof(Element));
01306       else if (this->fNelems > nelems_old)
01307          memset(elements_new+nelems_old,0,(this->fNelems-nelems_old)*sizeof(Element));
01308 
01309       // Copy overlap
01310       const Int_t rowLwb_copy = TMath::Max(this->fRowLwb,rowLwb_old);
01311       const Int_t colLwb_copy = TMath::Max(this->fColLwb,colLwb_old);
01312       const Int_t rowUpb_copy = TMath::Min(this->fRowLwb+this->fNrows-1,rowLwb_old+nrows_old-1);
01313       const Int_t colUpb_copy = TMath::Min(this->fColLwb+this->fNcols-1,colLwb_old+ncols_old-1);
01314 
01315       const Int_t nrows_copy = rowUpb_copy-rowLwb_copy+1;
01316       const Int_t ncols_copy = colUpb_copy-colLwb_copy+1;
01317 
01318       if (nrows_copy > 0 && ncols_copy > 0) {
01319          const Int_t colOldOff = colLwb_copy-colLwb_old;
01320          const Int_t colNewOff = colLwb_copy-this->fColLwb;
01321          if (ncols_old < this->fNcols) {
01322             for (Int_t i = nrows_copy-1; i >= 0; i--) {
01323                const Int_t iRowOld = rowLwb_copy+i-rowLwb_old;
01324                const Int_t iRowNew = rowLwb_copy+i-this->fRowLwb;
01325                Memcpy_m(elements_new+iRowNew*this->fNcols+colNewOff,
01326                         elements_old+iRowOld*ncols_old+colOldOff,ncols_copy,this->fNelems,nelems_old);
01327                if (this->fNelems <= this->kSizeMax && nelems_old <= this->kSizeMax)
01328                   memset(elements_new+iRowNew*this->fNcols+colNewOff+ncols_copy,0,
01329                          (this->fNcols-ncols_copy)*sizeof(Element));
01330             }
01331          } else {
01332             for (Int_t i = 0; i < nrows_copy; i++) {
01333                const Int_t iRowOld = rowLwb_copy+i-rowLwb_old;
01334                const Int_t iRowNew = rowLwb_copy+i-this->fRowLwb;
01335                Memcpy_m(elements_new+iRowNew*this->fNcols+colNewOff,
01336                         elements_old+iRowOld*ncols_old+colOldOff,ncols_copy,this->fNelems,nelems_old);
01337             }
01338          }
01339       }
01340 
01341       Delete_m(nelems_old,elements_old);
01342    } else {
01343       Allocate(new_nrows,new_ncols,row_lwb,col_lwb,1);
01344    }
01345 
01346    return *this;
01347 }
01348 
01349 //______________________________________________________________________________
01350 template<class Element>
01351 Double_t TMatrixT<Element>::Determinant() const
01352 {
01353 // Return the matrix determinant 
01354 
01355    const TMatrixT<Element> &tmp = *this;
01356    TDecompLU lu(tmp,this->fTol);
01357    Double_t d1,d2;
01358    lu.Det(d1,d2);
01359    return d1*TMath::Power(2.0,d2);
01360 }
01361 
01362 //______________________________________________________________________________
01363 template<class Element>
01364 void TMatrixT<Element>::Determinant(Double_t &d1,Double_t &d2) const
01365 {
01366 // Return the matrix determinant as d1,d2 where det = d1*TMath::Power(2.0,d2)
01367 
01368    const TMatrixT<Element> &tmp = *this;
01369    TDecompLU lu(tmp,Double_t(this->fTol));
01370    lu.Det(d1,d2);
01371 }
01372 
01373 //______________________________________________________________________________
01374 template<class Element>
01375 TMatrixT<Element> &TMatrixT<Element>::Invert(Double_t *det)
01376 {
01377 // Invert the matrix and calculate its determinant
01378 
01379    R__ASSERT(this->IsValid());
01380    if (typeid(Element) == typeid(Double_t))
01381       TDecompLU::InvertLU(*dynamic_cast<TMatrixD *>(this),Double_t(this->fTol),det);
01382    else {
01383       TMatrixD tmp(*this);
01384       if (TDecompLU::InvertLU(tmp,Double_t(this->fTol),det)) {
01385          const Double_t *p1 = tmp.GetMatrixArray();
01386                Element  *p2 = this->GetMatrixArray();
01387          for (Int_t i = 0; i < this->GetNoElements(); i++)
01388             p2[i] = p1[i];
01389       }
01390    }
01391 
01392    return *this;
01393 }
01394 
01395 //______________________________________________________________________________
01396 template<class Element>
01397 TMatrixT<Element> &TMatrixT<Element>::InvertFast(Double_t *det)
01398 {
01399 // Invert the matrix and calculate its determinant, however upto (6x6)
01400 // a fast Cramer inversion is used .
01401 
01402    R__ASSERT(this->IsValid());
01403 
01404    const Char_t nRows = Char_t(this->GetNrows());
01405    switch (nRows) {
01406       case 1:
01407       {
01408          if (this->GetNrows() != this->GetNcols() || this->GetRowLwb() != this->GetColLwb()) {
01409              Error("Invert()","matrix should be square");
01410          } else {
01411             Element *pM = this->GetMatrixArray();
01412             if (*pM == 0.) {
01413                Error("InvertFast","matrix is singular");
01414                *det = 0;
01415             }
01416             else {
01417                *det = *pM;
01418                *pM = 1.0/(*pM);
01419             }
01420          }
01421          return *this;
01422       }
01423       case 2:
01424       {
01425          TMatrixTCramerInv::Inv2x2<Element>(*this,det);
01426          return *this;
01427       }
01428       case 3:
01429       {
01430          TMatrixTCramerInv::Inv3x3<Element>(*this,det);
01431          return *this;
01432       }
01433       case 4:
01434       {
01435          TMatrixTCramerInv::Inv4x4<Element>(*this,det);
01436          return *this;
01437       }
01438       case 5:
01439       {
01440          TMatrixTCramerInv::Inv5x5<Element>(*this,det);
01441          return *this;
01442       }
01443       case 6:
01444       {
01445          TMatrixTCramerInv::Inv6x6<Element>(*this,det);
01446          return *this;
01447       }
01448 
01449       default:
01450       {
01451          if(typeid(Element) == typeid(Double_t))
01452             TDecompLU::InvertLU(*dynamic_cast<TMatrixD *>(this),Double_t(this->fTol),det);
01453          else {
01454             TMatrixD tmp(*this);
01455             if (TDecompLU::InvertLU(tmp,Double_t(this->fTol),det)) {
01456                const Double_t *p1 = tmp.GetMatrixArray();
01457                      Element  *p2 = this->GetMatrixArray();
01458                for (Int_t i = 0; i < this->GetNoElements(); i++)
01459                   p2[i] = p1[i];
01460             }
01461          }
01462          return *this;
01463       }
01464     }
01465 }
01466 
01467 //______________________________________________________________________________
01468 template<class Element>
01469 TMatrixT<Element> &TMatrixT<Element>::Transpose(const TMatrixT<Element> &source)
01470 {
01471 // Transpose matrix source.
01472 
01473    R__ASSERT(this->IsValid());
01474    R__ASSERT(source.IsValid());
01475 
01476    if (this->GetMatrixArray() == source.GetMatrixArray()) {
01477       Element *ap = this->GetMatrixArray();
01478       if (this->fNrows == this->fNcols && this->fRowLwb == this->fColLwb) {
01479          for (Int_t i = 0; i < this->fNrows; i++) {
01480             const Int_t off_i = i*this->fNrows;
01481             for (Int_t j = i+1; j < this->fNcols; j++) {
01482                const Int_t off_j = j*this->fNcols;
01483                const Element tmp = ap[off_i+j];
01484                ap[off_i+j] = ap[off_j+i];
01485                ap[off_j+i] = tmp;
01486             }
01487          }
01488       } else {
01489          Element *oldElems = new Element[source.GetNoElements()];
01490          memcpy(oldElems,source.GetMatrixArray(),source.GetNoElements()*sizeof(Element));
01491          const Int_t nrows_old  = this->fNrows;
01492          const Int_t ncols_old  = this->fNcols;
01493          const Int_t rowlwb_old = this->fRowLwb;
01494          const Int_t collwb_old = this->fColLwb;
01495 
01496          this->fNrows  = ncols_old;  this->fNcols  = nrows_old;
01497          this->fRowLwb = collwb_old; this->fColLwb = rowlwb_old;
01498          for (Int_t irow = this->fRowLwb; irow < this->fRowLwb+this->fNrows; irow++) {
01499             for (Int_t icol = this->fColLwb; icol < this->fColLwb+this->fNcols; icol++) {
01500                const Int_t off = (icol-collwb_old)*ncols_old;
01501                (*this)(irow,icol) = oldElems[off+irow-rowlwb_old];
01502             }
01503          }
01504          delete [] oldElems;
01505       }
01506    } else {
01507       if (this->fNrows  != source.GetNcols()  || this->fNcols  != source.GetNrows() ||
01508           this->fRowLwb != source.GetColLwb() || this->fColLwb != source.GetRowLwb())
01509       {
01510          Error("Transpose","matrix has wrong shape");
01511          return *this;
01512       }
01513 
01514       const Element *sp1 = source.GetMatrixArray();
01515       const Element *scp = sp1; // Row source pointer
01516             Element *tp  = this->GetMatrixArray();
01517       const Element * const tp_last = this->GetMatrixArray()+this->fNelems;
01518 
01519       // (This: target) matrix is traversed row-wise way,
01520       // whilst the source matrix is scanned column-wise
01521       while (tp < tp_last) {
01522          const Element *sp2 = scp++;
01523 
01524          // Move tp to the next elem in the row and sp to the next elem in the curr col
01525          while (sp2 < sp1+this->fNelems) {
01526             *tp++ = *sp2;
01527             sp2 += this->fNrows;
01528          }
01529       }
01530       R__ASSERT(tp == tp_last && scp == sp1+this->fNrows);
01531    }
01532 
01533    return *this;
01534 }
01535 
01536 //______________________________________________________________________________
01537 template<class Element>
01538 TMatrixT<Element> &TMatrixT<Element>::Rank1Update(const TVectorT<Element> &v,Element alpha)
01539 {
01540 // Perform a rank 1 operation on matrix A:
01541 //     A += alpha * v * v^T
01542 
01543    if (gMatrixCheck) {
01544       R__ASSERT(this->IsValid());
01545       R__ASSERT(v.IsValid());
01546       if (v.GetNoElements() < TMath::Max(this->fNrows,this->fNcols)) {
01547          Error("Rank1Update","vector too short");
01548          return *this;
01549       }
01550    }
01551 
01552    const Element * const pv = v.GetMatrixArray();
01553          Element *mp = this->GetMatrixArray();
01554 
01555    for (Int_t i = 0; i < this->fNrows; i++) {
01556       const Element tmp = alpha*pv[i];
01557       for (Int_t j = 0; j < this->fNcols; j++)
01558          *mp++ += tmp*pv[j];
01559    }
01560 
01561    return *this;
01562 }
01563 
01564 //______________________________________________________________________________
01565 template<class Element>
01566 TMatrixT<Element> &TMatrixT<Element>::Rank1Update(const TVectorT<Element> &v1,const TVectorT<Element> &v2,Element alpha)
01567 {
01568 // Perform a rank 1 operation on matrix A:
01569 //     A += alpha * v1 * v2^T
01570 
01571    if (gMatrixCheck) {
01572       R__ASSERT(this->IsValid());
01573       R__ASSERT(v1.IsValid());
01574       R__ASSERT(v2.IsValid());
01575       if (v1.GetNoElements() < this->fNrows) {
01576          Error("Rank1Update","vector v1 too short");
01577          return *this;
01578       }
01579 
01580       if (v2.GetNoElements() < this->fNcols) {
01581          Error("Rank1Update","vector v2 too short");
01582          return *this;
01583       }
01584    }
01585 
01586    const Element * const pv1 = v1.GetMatrixArray();
01587    const Element * const pv2 = v2.GetMatrixArray();
01588          Element *mp = this->GetMatrixArray();
01589 
01590    for (Int_t i = 0; i < this->fNrows; i++) {
01591       const Element tmp = alpha*pv1[i];
01592       for (Int_t j = 0; j < this->fNcols; j++)
01593          *mp++ += tmp*pv2[j];
01594    }
01595 
01596    return *this;
01597 }
01598 
01599 //______________________________________________________________________________
01600 template<class Element>
01601 Element TMatrixT<Element>::Similarity(const TVectorT<Element> &v) const
01602 {
01603 // Calculate scalar v * (*this) * v^T
01604 
01605    if (gMatrixCheck) {
01606       R__ASSERT(this->IsValid());
01607       R__ASSERT(v.IsValid());
01608       if (this->fNcols != this->fNrows || this->fColLwb != this->fRowLwb) {
01609          Error("Similarity(const TVectorT &)","matrix is not square");
01610          return -1.;
01611       }
01612 
01613       if (this->fNcols != v.GetNrows() || this->fColLwb != v.GetLwb()) {
01614          Error("Similarity(const TVectorT &)","vector and matrix incompatible");
01615          return -1.;
01616       }
01617    }
01618 
01619    const Element *mp = this->GetMatrixArray(); // Matrix row ptr
01620    const Element *vp = v.GetMatrixArray();     // vector ptr
01621 
01622    Element sum1 = 0;
01623    const Element * const vp_first = vp;
01624    const Element * const vp_last  = vp+v.GetNrows();
01625    while (vp < vp_last) {
01626       Element sum2 = 0;
01627       for (const Element *sp = vp_first; sp < vp_last; )
01628          sum2 += *mp++ * *sp++;
01629       sum1 += sum2 * *vp++;
01630    }
01631 
01632    R__ASSERT(mp == this->GetMatrixArray()+this->GetNoElements());
01633 
01634    return sum1;
01635 }
01636 
01637 //______________________________________________________________________________
01638 template<class Element>
01639 TMatrixT<Element> &TMatrixT<Element>::NormByColumn(const TVectorT<Element> &v,Option_t *option)
01640 {
01641 // Multiply/divide matrix columns by a vector:
01642 // option:
01643 // "D"   :  b(i,j) = a(i,j)/v(i)   i = 0,fNrows-1 (default)
01644 // else  :  b(i,j) = a(i,j)*v(i)
01645 
01646    if (gMatrixCheck) {
01647       R__ASSERT(this->IsValid());
01648       R__ASSERT(v.IsValid());
01649       if (v.GetNoElements() < this->fNrows) {
01650          Error("NormByColumn","vector shorter than matrix column");
01651          return *this;
01652       }
01653    }
01654 
01655    TString opt(option);
01656    opt.ToUpper();
01657    const Int_t divide = (opt.Contains("D")) ? 1 : 0;
01658 
01659    const Element *pv = v.GetMatrixArray();
01660          Element *mp = this->GetMatrixArray();
01661    const Element * const mp_last = mp+this->fNelems;
01662 
01663    if (divide) {
01664       for ( ; mp < mp_last; pv++) {
01665          for (Int_t j = 0; j < this->fNcols; j++)
01666          {
01667             if (*pv != 0.0)
01668                *mp++ /= *pv;
01669             else {
01670                Error("NormbyColumn","vector element %ld is zero",Long_t(pv-v.GetMatrixArray()));
01671                mp++;
01672             }
01673          }
01674       }
01675    } else {
01676       for ( ; mp < mp_last; pv++)
01677          for (Int_t j = 0; j < this->fNcols; j++)
01678             *mp++ *= *pv;
01679    }
01680 
01681    return *this;
01682 }
01683 
01684 //______________________________________________________________________________
01685 template<class Element>
01686 TMatrixT<Element> &TMatrixT<Element>::NormByRow(const TVectorT<Element> &v,Option_t *option)
01687 {
01688 // Multiply/divide matrix rows with a vector:
01689 // option:
01690 // "D"   :  b(i,j) = a(i,j)/v(j)   i = 0,fNcols-1 (default)
01691 // else  :  b(i,j) = a(i,j)*v(j)
01692 
01693    if (gMatrixCheck) {
01694       R__ASSERT(this->IsValid());
01695       R__ASSERT(v.IsValid());
01696       if (v.GetNoElements() < this->fNcols) {
01697          Error("NormByRow","vector shorter than matrix column");
01698          return *this;
01699       }
01700    }
01701 
01702    TString opt(option);
01703    opt.ToUpper();
01704    const Int_t divide = (opt.Contains("D")) ? 1 : 0;
01705 
01706    const Element *pv0 = v.GetMatrixArray();
01707    const Element *pv  = pv0;
01708          Element *mp  = this->GetMatrixArray();
01709    const Element * const mp_last = mp+this->fNelems;
01710 
01711    if (divide) {
01712       for ( ; mp < mp_last; pv = pv0 )
01713          for (Int_t j = 0; j < this->fNcols; j++) {
01714             if (*pv != 0.0)
01715                *mp++ /= *pv++;
01716             else {
01717                Error("NormbyRow","vector element %ld is zero",Long_t(pv-pv0));
01718                mp++;
01719             }
01720          }
01721     } else {
01722        for ( ; mp < mp_last; pv = pv0 )
01723           for (Int_t j = 0; j < this->fNcols; j++)
01724              *mp++ *= *pv++;
01725     }
01726 
01727    return *this;
01728 }
01729 
01730 //______________________________________________________________________________
01731 template<class Element>
01732 TMatrixT<Element> &TMatrixT<Element>::operator=(const TMatrixT<Element> &source)
01733 {
01734 // Assignment operator
01735 
01736    if (gMatrixCheck && !AreCompatible(*this,source)) {
01737       Error("operator=(const TMatrixT &)","matrices not compatible");
01738       return *this;
01739    }
01740 
01741    if (this->GetMatrixArray() != source.GetMatrixArray()) {
01742       TObject::operator=(source);
01743       memcpy(fElements,source.GetMatrixArray(),this->fNelems*sizeof(Element));
01744       this->fTol = source.GetTol();
01745    }
01746    return *this;
01747 }
01748 
01749 //______________________________________________________________________________
01750 template<class Element>
01751 TMatrixT<Element> &TMatrixT<Element>::operator=(const TMatrixTSym<Element> &source)
01752 {
01753 // Assignment operator
01754 
01755    if (gMatrixCheck && !AreCompatible(*this,source)) {
01756       Error("operator=(const TMatrixTSym &)","matrices not compatible");
01757       return *this;
01758    }
01759 
01760    if (this->GetMatrixArray() != source.GetMatrixArray()) {
01761       TObject::operator=(source);
01762       memcpy(fElements,source.GetMatrixArray(),this->fNelems*sizeof(Element));
01763       this->fTol = source.GetTol();
01764    }
01765    return *this;
01766 }
01767 
01768 //______________________________________________________________________________
01769 template<class Element>
01770 TMatrixT<Element> &TMatrixT<Element>::operator=(const TMatrixTSparse<Element> &source)
01771 {
01772 // Assignment operator
01773 
01774    if ((gMatrixCheck &&
01775         this->GetNrows()  != source.GetNrows())  || this->GetNcols()  != source.GetNcols() ||
01776         this->GetRowLwb() != source.GetRowLwb() || this->GetColLwb() != source.GetColLwb()) {
01777       Error("operator=(const TMatrixTSparse &","matrices not compatible");
01778       return *this;
01779    }
01780 
01781    if (this->GetMatrixArray() != source.GetMatrixArray()) {
01782       TObject::operator=(source);
01783       memset(fElements,0,this->fNelems*sizeof(Element));
01784 
01785       const Element * const sp = source.GetMatrixArray();
01786             Element *       tp = this->GetMatrixArray();
01787 
01788       const Int_t * const pRowIndex = source.GetRowIndexArray();
01789       const Int_t * const pColIndex = source.GetColIndexArray();
01790 
01791       for (Int_t irow = 0; irow < this->fNrows; irow++ ) {
01792          const Int_t off = irow*this->fNcols;
01793          const Int_t sIndex = pRowIndex[irow];
01794          const Int_t eIndex = pRowIndex[irow+1];
01795          for (Int_t index = sIndex; index < eIndex; index++)
01796             tp[off+pColIndex[index]] = sp[index];
01797       }
01798       this->fTol = source.GetTol();
01799    }
01800    return *this;
01801 }
01802 
01803 //______________________________________________________________________________
01804 template<class Element>
01805 TMatrixT<Element> &TMatrixT<Element>::operator=(const TMatrixTLazy<Element> &lazy_constructor)
01806 {
01807 // Assignment operator
01808 
01809    R__ASSERT(this->IsValid());
01810 
01811    if (lazy_constructor.GetRowUpb() != this->GetRowUpb() ||
01812        lazy_constructor.GetColUpb() != this->GetColUpb() ||
01813        lazy_constructor.GetRowLwb() != this->GetRowLwb() ||
01814        lazy_constructor.GetColLwb() != this->GetColLwb()) {
01815       Error("operator=(const TMatrixTLazy&)", "matrix is incompatible with "
01816             "the assigned Lazy matrix");
01817       return *this;
01818    }
01819 
01820    lazy_constructor.FillIn(*this);
01821    return *this;
01822 }
01823 
01824 //______________________________________________________________________________
01825 template<class Element>
01826 TMatrixT<Element> &TMatrixT<Element>::operator=(Element val)
01827 {
01828 // Assign val to every element of the matrix.
01829 
01830    R__ASSERT(this->IsValid());
01831 
01832    Element *ep = this->GetMatrixArray();
01833    const Element * const ep_last = ep+this->fNelems;
01834    while (ep < ep_last)
01835       *ep++ = val;
01836 
01837    return *this;
01838 }
01839 
01840 //______________________________________________________________________________
01841 template<class Element>
01842 TMatrixT<Element> &TMatrixT<Element>::operator+=(Element val)
01843 {
01844 // Add val to every element of the matrix.
01845 
01846    R__ASSERT(this->IsValid());
01847 
01848    Element *ep = this->GetMatrixArray();
01849    const Element * const ep_last = ep+this->fNelems;
01850    while (ep < ep_last)
01851       *ep++ += val;
01852 
01853    return *this;
01854 }
01855 
01856 //______________________________________________________________________________
01857 template<class Element>
01858 TMatrixT<Element> &TMatrixT<Element>::operator-=(Element val)
01859 {
01860 // Subtract val from every element of the matrix.
01861 
01862    R__ASSERT(this->IsValid());
01863 
01864    Element *ep = this->GetMatrixArray();
01865    const Element * const ep_last = ep+this->fNelems;
01866    while (ep < ep_last)
01867       *ep++ -= val;
01868 
01869    return *this;
01870 }
01871 
01872 //______________________________________________________________________________
01873 template<class Element>
01874 TMatrixT<Element> &TMatrixT<Element>::operator*=(Element val)
01875 {
01876 // Multiply every element of the matrix with val.
01877 
01878    R__ASSERT(this->IsValid());
01879 
01880    Element *ep = this->GetMatrixArray();
01881    const Element * const ep_last = ep+this->fNelems;
01882    while (ep < ep_last)
01883       *ep++ *= val;
01884 
01885    return *this;
01886 }
01887 
01888 //______________________________________________________________________________
01889 template<class Element>
01890 TMatrixT<Element> &TMatrixT<Element>::operator+=(const TMatrixT<Element> &source)
01891 {
01892 // Add the source matrix.
01893 
01894    if (gMatrixCheck && !AreCompatible(*this,source)) {
01895       Error("operator+=(const TMatrixT &)","matrices not compatible");
01896       return *this;
01897    }
01898 
01899    const Element *sp = source.GetMatrixArray();
01900    Element *tp = this->GetMatrixArray();
01901    const Element * const tp_last = tp+this->fNelems;
01902    while (tp < tp_last)
01903       *tp++ += *sp++;
01904 
01905    return *this;
01906 }
01907 
01908 //______________________________________________________________________________
01909 template<class Element>
01910 TMatrixT<Element> &TMatrixT<Element>::operator+=(const TMatrixTSym<Element> &source)
01911 {
01912 // Add the source matrix.
01913 
01914    if (gMatrixCheck && !AreCompatible(*this,source)) {
01915       Error("operator+=(const TMatrixTSym &)","matrices not compatible");
01916       return *this;
01917    }
01918 
01919    const Element *sp = source.GetMatrixArray();
01920    Element *tp = this->GetMatrixArray();
01921    const Element * const tp_last = tp+this->fNelems;
01922    while (tp < tp_last)
01923       *tp++ += *sp++;
01924 
01925    return *this;
01926 }
01927 
01928 //______________________________________________________________________________
01929 template<class Element>
01930 TMatrixT<Element> &TMatrixT<Element>::operator-=(const TMatrixT<Element> &source)
01931 {
01932 // Subtract the source matrix.
01933 
01934    if (gMatrixCheck && !AreCompatible(*this,source)) {
01935       Error("operator=-(const TMatrixT &)","matrices not compatible");
01936       return *this;
01937    }
01938 
01939    const Element *sp = source.GetMatrixArray();
01940    Element *tp = this->GetMatrixArray();
01941    const Element * const tp_last = tp+this->fNelems;
01942    while (tp < tp_last)
01943       *tp++ -= *sp++;
01944 
01945    return *this;
01946 }
01947 
01948 //______________________________________________________________________________
01949 template<class Element>
01950 TMatrixT<Element> &TMatrixT<Element>::operator-=(const TMatrixTSym<Element> &source)
01951 {
01952 // Subtract the source matrix.
01953 
01954    if (gMatrixCheck && !AreCompatible(*this,source)) {
01955       Error("operator=-(const TMatrixTSym &)","matrices not compatible");
01956       return *this;
01957    }
01958 
01959    const Element *sp = source.GetMatrixArray();
01960    Element *tp = this->GetMatrixArray();
01961    const Element * const tp_last = tp+this->fNelems;
01962    while (tp < tp_last)
01963       *tp++ -= *sp++;
01964 
01965    return *this;
01966 }
01967 
01968 //______________________________________________________________________________
01969 template<class Element>
01970 TMatrixT<Element> &TMatrixT<Element>::operator*=(const TMatrixT<Element> &source)
01971 {
01972 // Compute target = target * source inplace. Strictly speaking, it can't be
01973 // done inplace, though only the row of the target matrix needs to be saved.
01974 // "Inplace" multiplication is only allowed when the 'source' matrix is square.
01975 
01976    if (gMatrixCheck) {
01977       R__ASSERT(this->IsValid());
01978       R__ASSERT(source.IsValid());
01979       if (this->fNcols != source.GetNrows() || this->fColLwb != source.GetRowLwb() ||
01980           this->fNcols != source.GetNcols() || this->fColLwb != source.GetColLwb()) {
01981          Error("operator*=(const TMatrixT &)","source matrix has wrong shape");
01982          return *this;
01983       }
01984    }
01985 
01986    // Check for A *= A;
01987    const Element *sp;
01988    TMatrixT<Element> tmp;
01989    if (this->GetMatrixArray() == source.GetMatrixArray()) {
01990       tmp.ResizeTo(source);
01991       tmp = source;
01992       sp = tmp.GetMatrixArray();
01993    }
01994    else
01995       sp = source.GetMatrixArray();
01996 
01997    // One row of the old_target matrix
01998    Element work[kWorkMax];
01999    Bool_t isAllocated = kFALSE;
02000    Element *trp = work;
02001    if (this->fNcols > kWorkMax) {
02002       isAllocated = kTRUE;
02003       trp = new Element[this->fNcols];
02004    }
02005 
02006          Element *cp   = this->GetMatrixArray();
02007    const Element *trp0 = cp; // Pointer to  target[i,0];
02008    const Element * const trp0_last = trp0+this->fNelems;
02009    while (trp0 < trp0_last) {
02010       memcpy(trp,trp0,this->fNcols*sizeof(Element));        // copy the i-th row of target, Start at target[i,0]
02011       for (const Element *scp = sp; scp < sp+this->fNcols; ) {  // Pointer to the j-th column of source,
02012                                                            // Start scp = source[0,0]
02013          Element cij = 0;
02014          for (Int_t j = 0; j < this->fNcols; j++) {
02015             cij += trp[j] * *scp;                        // the j-th col of source
02016             scp += this->fNcols;
02017          }
02018          *cp++ = cij;
02019          scp -= source.GetNoElements()-1;               // Set bcp to the (j+1)-th col
02020       }
02021       trp0 += this->fNcols;                            // Set trp0 to the (i+1)-th row
02022       R__ASSERT(trp0 == cp);
02023    }
02024 
02025    R__ASSERT(cp == trp0_last && trp0 == trp0_last);
02026    if (isAllocated)
02027       delete [] trp;
02028 
02029    return *this;
02030 }
02031 
02032 //______________________________________________________________________________
02033 template<class Element>
02034 TMatrixT<Element> &TMatrixT<Element>::operator*=(const TMatrixTSym<Element> &source)
02035 {
02036 // Compute target = target * source inplace. Strictly speaking, it can't be
02037 // done inplace, though only the row of the target matrix needs to be saved.
02038 
02039    if (gMatrixCheck) {
02040       R__ASSERT(this->IsValid());
02041       R__ASSERT(source.IsValid());
02042       if (this->fNcols != source.GetNrows() || this->fColLwb != source.GetRowLwb()) {
02043          Error("operator*=(const TMatrixTSym &)","source matrix has wrong shape");
02044          return *this;
02045       }
02046    }
02047 
02048    // Check for A *= A;
02049    const Element *sp;
02050    TMatrixT<Element> tmp;
02051    if (this->GetMatrixArray() == source.GetMatrixArray()) {
02052       tmp.ResizeTo(source);
02053       tmp = source;
02054       sp = tmp.GetMatrixArray();
02055    }
02056    else
02057       sp = source.GetMatrixArray();
02058 
02059    // One row of the old_target matrix
02060    Element work[kWorkMax];
02061    Bool_t isAllocated = kFALSE;
02062    Element *trp = work;
02063    if (this->fNcols > kWorkMax) {
02064       isAllocated = kTRUE;
02065       trp = new Element[this->fNcols];
02066    }
02067 
02068          Element *cp   = this->GetMatrixArray();
02069    const Element *trp0 = cp; // Pointer to  target[i,0];
02070    const Element * const trp0_last = trp0+this->fNelems;
02071    while (trp0 < trp0_last) {
02072       memcpy(trp,trp0,this->fNcols*sizeof(Element));        // copy the i-th row of target, Start at target[i,0]
02073       for (const Element *scp = sp; scp < sp+this->fNcols; ) {  // Pointer to the j-th column of source,
02074                                                            // Start scp = source[0,0]
02075          Element cij = 0;
02076          for (Int_t j = 0; j < this->fNcols; j++) {
02077             cij += trp[j] * *scp;                        // the j-th col of source
02078             scp += this->fNcols;
02079          }
02080          *cp++ = cij;
02081          scp -= source.GetNoElements()-1;               // Set bcp to the (j+1)-th col
02082       }
02083       trp0 += this->fNcols;                            // Set trp0 to the (i+1)-th row
02084       R__ASSERT(trp0 == cp);
02085    } 
02086 
02087    R__ASSERT(cp == trp0_last && trp0 == trp0_last);
02088    if (isAllocated)
02089       delete [] trp;
02090 
02091    return *this;
02092 }
02093 
02094 //______________________________________________________________________________
02095 template<class Element>
02096 TMatrixT<Element> &TMatrixT<Element>::operator*=(const TMatrixTDiag_const<Element> &diag)
02097 {
02098 // Multiply a matrix row by the diagonal of another matrix
02099 // matrix(i,j) *= diag(j), j=0,fNcols-1
02100 
02101    if (gMatrixCheck) {
02102       R__ASSERT(this->IsValid());
02103       R__ASSERT(diag.GetMatrix()->IsValid());
02104       if (this->fNcols != diag.GetNdiags()) {
02105          Error("operator*=(const TMatrixTDiag_const &)","wrong diagonal length");
02106          return *this;
02107       }
02108    }
02109 
02110    Element *mp = this->GetMatrixArray();  // Matrix ptr
02111    const Element * const mp_last = mp+this->fNelems;
02112    const Int_t inc = diag.GetInc();
02113    while (mp < mp_last) {
02114       const Element *dp = diag.GetPtr();
02115       for (Int_t j = 0; j < this->fNcols; j++) {
02116          *mp++ *= *dp;
02117          dp += inc;
02118       }
02119    }
02120 
02121    return *this;
02122 }
02123 
02124 //______________________________________________________________________________
02125 template<class Element>
02126 TMatrixT<Element> &TMatrixT<Element>::operator/=(const TMatrixTDiag_const<Element> &diag)
02127 {
02128 // Divide a matrix row by the diagonal of another matrix
02129 // matrix(i,j) /= diag(j)
02130 
02131    if (gMatrixCheck) {
02132       R__ASSERT(this->IsValid());
02133       R__ASSERT(diag.GetMatrix()->IsValid());
02134       if (this->fNcols != diag.GetNdiags()) {
02135          Error("operator/=(const TMatrixTDiag_const &)","wrong diagonal length");
02136          return *this;
02137       }
02138    }
02139 
02140    Element *mp = this->GetMatrixArray();  // Matrix ptr
02141    const Element * const mp_last = mp+this->fNelems;
02142    const Int_t inc = diag.GetInc();
02143    while (mp < mp_last) {
02144       const Element *dp = diag.GetPtr();
02145       for (Int_t j = 0; j < this->fNcols; j++) {
02146          if (*dp != 0.0)
02147             *mp++ /= *dp;
02148          else {
02149             Error("operator/=","%d-diagonal element is zero",j);
02150             mp++;
02151          }
02152          dp += inc;
02153       }
02154    }
02155 
02156    return *this;
02157 }
02158 
02159 //______________________________________________________________________________
02160 template<class Element>
02161 TMatrixT<Element> &TMatrixT<Element>::operator*=(const TMatrixTColumn_const<Element> &col)
02162 {
02163 // Multiply a matrix by the column of another matrix
02164 // matrix(i,j) *= another(i,k) for fixed k
02165 
02166    const TMatrixTBase<Element> *mt = col.GetMatrix();
02167 
02168    if (gMatrixCheck) {
02169       R__ASSERT(this->IsValid());
02170       R__ASSERT(mt->IsValid());
02171       if (this->fNrows != mt->GetNrows()) {
02172          Error("operator*=(const TMatrixTColumn_const &)","wrong column length");
02173          return *this;
02174       }
02175    }
02176 
02177    const Element * const endp = col.GetPtr()+mt->GetNoElements();
02178    Element *mp = this->GetMatrixArray();  // Matrix ptr
02179    const Element * const mp_last = mp+this->fNelems;
02180    const Element *cp = col.GetPtr();      //  ptr
02181    const Int_t inc = col.GetInc();
02182    while (mp < mp_last) {
02183       R__ASSERT(cp < endp);
02184       for (Int_t j = 0; j < this->fNcols; j++)
02185          *mp++ *= *cp;
02186       cp += inc;
02187    }
02188 
02189    return *this;
02190 }
02191 
02192 //______________________________________________________________________________
02193 template<class Element>
02194 TMatrixT<Element> &TMatrixT<Element>::operator/=(const TMatrixTColumn_const<Element> &col)
02195 {
02196 // Divide a matrix by the column of another matrix
02197 // matrix(i,j) /= another(i,k) for fixed k
02198 
02199    const TMatrixTBase<Element> *mt = col.GetMatrix();
02200 
02201    if (gMatrixCheck) {
02202       R__ASSERT(this->IsValid());
02203       R__ASSERT(mt->IsValid());
02204       if (this->fNrows != mt->GetNrows()) {
02205          Error("operator/=(const TMatrixTColumn_const &)","wrong column matrix");
02206          return *this;
02207       }
02208    }
02209 
02210    const Element * const endp = col.GetPtr()+mt->GetNoElements();
02211    Element *mp = this->GetMatrixArray();  // Matrix ptr
02212    const Element * const mp_last = mp+this->fNelems;
02213    const Element *cp = col.GetPtr();      //  ptr
02214    const Int_t inc = col.GetInc();
02215    while (mp < mp_last) {
02216       R__ASSERT(cp < endp);
02217       if (*cp != 0.0) {
02218          for (Int_t j = 0; j < this->fNcols; j++)
02219             *mp++ /= *cp;
02220       } else {
02221          const Int_t icol = (cp-mt->GetMatrixArray())/inc;
02222          Error("operator/=","%d-row of matrix column is zero",icol);
02223          mp += this->fNcols;
02224       }
02225       cp += inc;
02226    }
02227 
02228    return *this;
02229 }
02230 
02231 //______________________________________________________________________________
02232 template<class Element>
02233 TMatrixT<Element> &TMatrixT<Element>::operator*=(const TMatrixTRow_const<Element> &row)
02234 {
02235 // Multiply a matrix by the row of another matrix
02236 // matrix(i,j) *= another(k,j) for fixed k
02237 
02238    const TMatrixTBase<Element> *mt = row.GetMatrix();
02239 
02240    if (gMatrixCheck) {
02241       R__ASSERT(this->IsValid());
02242       R__ASSERT(mt->IsValid());
02243       if (this->fNcols != mt->GetNcols()) {
02244          Error("operator*=(const TMatrixTRow_const &)","wrong row length");
02245          return *this;
02246       }
02247    }
02248 
02249    const Element * const endp = row.GetPtr()+mt->GetNoElements();
02250    Element *mp = this->GetMatrixArray();  // Matrix ptr
02251    const Element * const mp_last = mp+this->fNelems;
02252    const Int_t inc = row.GetInc();
02253    while (mp < mp_last) {
02254       const Element *rp = row.GetPtr();    // Row ptr
02255       for (Int_t j = 0; j < this->fNcols; j++) {
02256          R__ASSERT(rp < endp);
02257          *mp++ *= *rp;
02258          rp += inc;
02259       }
02260    }
02261 
02262    return *this;
02263 }
02264 
02265 //______________________________________________________________________________
02266 template<class Element>
02267 TMatrixT<Element> &TMatrixT<Element>::operator/=(const TMatrixTRow_const<Element> &row)
02268 {
02269 // Divide a matrix by the row of another matrix
02270 // matrix(i,j) /= another(k,j) for fixed k
02271 
02272    const TMatrixTBase<Element> *mt = row.GetMatrix();
02273    R__ASSERT(this->IsValid());
02274    R__ASSERT(mt->IsValid());
02275  
02276    if (this->fNcols != mt->GetNcols()) {
02277       Error("operator/=(const TMatrixTRow_const &)","wrong row length");
02278       return *this;
02279    }
02280 
02281    const Element * const endp = row.GetPtr()+mt->GetNoElements();
02282    Element *mp = this->GetMatrixArray();  // Matrix ptr
02283    const Element * const mp_last = mp+this->fNelems;
02284    const Int_t inc = row.GetInc();
02285    while (mp < mp_last) {
02286       const Element *rp = row.GetPtr();    // Row ptr
02287       for (Int_t j = 0; j < this->fNcols; j++) {
02288          R__ASSERT(rp < endp);
02289          if (*rp != 0.0) {
02290            *mp++ /= *rp;
02291          } else {
02292             Error("operator/=","%d-col of matrix row is zero",j);
02293             mp++;
02294          }
02295          rp += inc;
02296       }
02297    }
02298 
02299    return *this;
02300 }
02301 
02302 //______________________________________________________________________________
02303 template<class Element>
02304 const TMatrixT<Element> TMatrixT<Element>::EigenVectors(TVectorT<Element> &eigenValues) const
02305 {
02306 // Return a matrix containing the eigen-vectors ordered by descending values
02307 // of Re^2+Im^2 of the complex eigen-values .
02308 // If the matrix is asymmetric, only the real part of the eigen-values is
02309 // returned . For full functionality use TMatrixDEigen .
02310 
02311    if (!this->IsSymmetric())
02312       Warning("EigenVectors(TVectorT &)","Only real part of eigen-values will be returned");
02313    TMatrixDEigen eigen(*this);
02314    eigenValues.ResizeTo(this->fNrows);
02315    eigenValues = eigen.GetEigenValuesRe();
02316    return eigen.GetEigenVectors();
02317 }
02318 
02319 //______________________________________________________________________________
02320 template<class Element>
02321 TMatrixT<Element> operator+(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02322 {
02323 // operation this = source1+source2
02324 
02325    TMatrixT<Element> target(source1);
02326    target += source2;
02327    return target;
02328 }
02329 
02330 //______________________________________________________________________________
02331 template<class Element>
02332 TMatrixT<Element> operator+(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02333 {
02334 // operation this = source1+source2
02335 
02336    TMatrixT<Element> target(source1);
02337    target += source2;
02338    return target;
02339 }
02340 
02341 //______________________________________________________________________________
02342 template<class Element>
02343 TMatrixT<Element> operator+(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02344 {
02345 // operation this = source1+source2
02346 
02347    return operator+(source2,source1);
02348 }
02349 
02350 //______________________________________________________________________________
02351 template<class Element>
02352 TMatrixT<Element> operator+(const TMatrixT<Element> &source,Element val)
02353 {
02354 // operation this = source+val
02355 
02356    TMatrixT<Element> target(source);
02357    target += val;
02358    return target;
02359 }
02360 
02361 //______________________________________________________________________________
02362 template<class Element>
02363 TMatrixT<Element> operator+(Element val,const TMatrixT<Element> &source)
02364 {
02365 // operation this = val+source
02366 
02367    return operator+(source,val);
02368 }
02369 
02370 //______________________________________________________________________________
02371 template<class Element>
02372 TMatrixT<Element> operator-(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02373 {
02374 // operation this = source1-source2
02375 
02376    TMatrixT<Element> target(source1);
02377    target -= source2;
02378    return target;
02379 }
02380 
02381 //______________________________________________________________________________
02382 template<class Element>
02383 TMatrixT<Element> operator-(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02384 {
02385 // operation this = source1-source2
02386 
02387    TMatrixT<Element> target(source1);
02388    target -= source2;
02389    return target;
02390 }
02391 
02392 //______________________________________________________________________________
02393 template<class Element>
02394 TMatrixT<Element> operator-(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02395 {
02396 // operation this = source1-source2
02397 
02398    return Element(-1.0)*(operator-(source2,source1));
02399 }
02400 
02401 //______________________________________________________________________________
02402 template<class Element>
02403 TMatrixT<Element> operator-(const TMatrixT<Element> &source,Element val)
02404 {
02405 // operation this = source-val
02406 
02407    TMatrixT<Element> target(source);
02408    target -= val;
02409    return target;
02410 }
02411 
02412 //______________________________________________________________________________
02413 template<class Element>
02414 TMatrixT<Element> operator-(Element val,const TMatrixT<Element> &source)
02415 {
02416 // operation this = val-source
02417 
02418    return Element(-1.0)*operator-(source,val);
02419 }
02420 
02421 //______________________________________________________________________________
02422 template<class Element>
02423 TMatrixT<Element> operator*(Element val,const TMatrixT<Element> &source)
02424 {
02425 // operation this = val*source
02426 
02427    TMatrixT<Element> target(source);
02428    target *= val;
02429    return target;
02430 }
02431 
02432 //______________________________________________________________________________
02433 template<class Element>
02434 TMatrixT<Element> operator*(const TMatrixT<Element> &source,Element val)
02435 {
02436 // operation this = val*source
02437 
02438    return operator*(val,source);
02439 }
02440 
02441 //______________________________________________________________________________
02442 template<class Element>
02443 TMatrixT<Element> operator*(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02444 {
02445 // operation this = source1*source2
02446 
02447    TMatrixT<Element> target(source1,TMatrixT<Element>::kMult,source2);
02448    return target;
02449 }
02450 
02451 //______________________________________________________________________________
02452 template<class Element>
02453 TMatrixT<Element> operator*(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02454 {
02455 // operation this = source1*source2
02456 
02457    TMatrixT<Element> target(source1,TMatrixT<Element>::kMult,source2);
02458    return target;
02459 }
02460 
02461 //______________________________________________________________________________
02462 template<class Element>
02463 TMatrixT<Element> operator*(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02464 {
02465 // operation this = source1*source2
02466 
02467    TMatrixT<Element> target(source1,TMatrixT<Element>::kMult,source2);
02468    return target;
02469 }
02470 
02471 //______________________________________________________________________________
02472 template<class Element>
02473 TMatrixT<Element> operator*(const TMatrixTSym<Element> &source1,const TMatrixTSym<Element> &source2)
02474 {
02475 // operation this = source1*source2
02476 
02477    TMatrixT<Element> target(source1,TMatrixT<Element>::kMult,source2);
02478    return target;
02479 }
02480 
02481 //______________________________________________________________________________
02482 template<class Element>
02483 TMatrixT<Element> operator&&(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02484 {
02485 // Logical AND
02486 
02487    TMatrixT<Element> target;
02488 
02489    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02490       Error("operator&&(const TMatrixT&,const TMatrixT&)","matrices not compatible");
02491       return target;
02492    }
02493 
02494    target.ResizeTo(source1);
02495 
02496    const Element *sp1 = source1.GetMatrixArray();
02497    const Element *sp2 = source2.GetMatrixArray();
02498          Element *tp  = target.GetMatrixArray();
02499    const Element * const tp_last = tp+target.GetNoElements();
02500    while (tp < tp_last)
02501       *tp++ = (*sp1++ != 0.0 && *sp2++ != 0.0);
02502 
02503    return target;
02504 }
02505 
02506 //______________________________________________________________________________
02507 template<class Element>
02508 TMatrixT<Element> operator&&(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02509 {
02510 // Logical AND
02511 
02512    TMatrixT<Element> target;
02513 
02514    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02515       Error("operator&&(const TMatrixT&,const TMatrixTSym&)","matrices not compatible");
02516       return target;
02517    }
02518 
02519    target.ResizeTo(source1);
02520 
02521    const Element *sp1 = source1.GetMatrixArray();
02522    const Element *sp2 = source2.GetMatrixArray();
02523          Element *tp  = target.GetMatrixArray();
02524    const Element * const tp_last = tp+target.GetNoElements();
02525    while (tp < tp_last)
02526       *tp++ = (*sp1++ != 0.0 && *sp2++ != 0.0);
02527 
02528    return target;
02529 }
02530 
02531 //______________________________________________________________________________
02532 template<class Element>
02533 TMatrixT<Element> operator&&(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02534 {
02535 // Logical AND
02536    return operator&&(source2,source1);
02537 }
02538 
02539 //______________________________________________________________________________
02540 template<class Element>
02541 TMatrixT<Element> operator||(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02542 {
02543 // Logical OR
02544 
02545    TMatrixT<Element> target;
02546 
02547    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02548       Error("operator||(const TMatrixT&,const TMatrixT&)","matrices not compatible");
02549       return target;
02550    }
02551 
02552    target.ResizeTo(source1);
02553 
02554    const Element *sp1 = source1.GetMatrixArray();
02555    const Element *sp2 = source2.GetMatrixArray();
02556          Element *tp  = target.GetMatrixArray();
02557    const Element * const tp_last = tp+target.GetNoElements();
02558    while (tp < tp_last)
02559       *tp++ = (*sp1++ != 0.0 || *sp2++ != 0.0);
02560 
02561    return target;
02562 }
02563 
02564 //______________________________________________________________________________
02565 template<class Element>
02566 TMatrixT<Element> operator||(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02567 {
02568 // Logical OR
02569 
02570    TMatrixT<Element> target;
02571 
02572    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02573       Error("operator||(const TMatrixT&,const TMatrixTSym&)","matrices not compatible");
02574       return target;
02575    }
02576 
02577    target.ResizeTo(source1);
02578 
02579    const Element *sp1 = source1.GetMatrixArray();
02580    const Element *sp2 = source2.GetMatrixArray();
02581          Element *tp  = target.GetMatrixArray();
02582    const Element * const tp_last = tp+target.GetNoElements();
02583    while (tp < tp_last)
02584       *tp++ = (*sp1++ != 0.0 || *sp2++ != 0.0);
02585 
02586    return target;
02587 }
02588 
02589 //______________________________________________________________________________
02590 template<class Element>
02591 TMatrixT<Element> operator||(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02592 {
02593 // Logical OR
02594 
02595    return operator||(source2,source1);
02596 }
02597 
02598 //______________________________________________________________________________
02599 template<class Element>
02600 TMatrixT<Element> operator>(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02601 {
02602 // logical operation source1 > source2
02603 
02604    TMatrixT<Element> target;
02605 
02606    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02607       Error("operator|(const TMatrixT&,const TMatrixT&)","matrices not compatible");
02608       return target;
02609    }
02610 
02611    target.ResizeTo(source1);
02612 
02613    const Element *sp1 = source1.GetMatrixArray();
02614    const Element *sp2 = source2.GetMatrixArray();
02615          Element *tp  = target.GetMatrixArray();
02616    const Element * const tp_last = tp+target.GetNoElements();
02617    while (tp < tp_last) {
02618       *tp++ = (*sp1) > (*sp2); sp1++; sp2++;
02619    }
02620 
02621    return target;
02622 }
02623 
02624 //______________________________________________________________________________
02625 template<class Element>
02626 TMatrixT<Element> operator>(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02627 {
02628 // logical operation source1 > source2
02629 
02630    TMatrixT<Element> target;
02631 
02632    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02633       Error("operator>(const TMatrixT&,const TMatrixTSym&)","matrices not compatible");
02634       return target;
02635    }
02636 
02637    target.ResizeTo(source1);
02638 
02639    const Element *sp1 = source1.GetMatrixArray();
02640    const Element *sp2 = source2.GetMatrixArray();
02641          Element *tp  = target.GetMatrixArray();
02642    const Element * const tp_last = tp+target.GetNoElements();
02643    while (tp < tp_last) {
02644       *tp++ = (*sp1) > (*sp2); sp1++; sp2++;
02645    }
02646 
02647    return target;
02648 }
02649 
02650 //______________________________________________________________________________
02651 template<class Element>
02652 TMatrixT<Element> operator>(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02653 {
02654 // logical operation source1 > source2
02655 
02656    return operator<=(source2,source1);
02657 }
02658 
02659 //______________________________________________________________________________
02660 template<class Element>
02661 TMatrixT<Element> operator>=(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02662 {
02663 // logical operation source1 >= source2
02664 
02665    TMatrixT<Element> target;
02666 
02667    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02668       Error("operator>=(const TMatrixT&,const TMatrixT&)","matrices not compatible");
02669       return target;
02670    }
02671 
02672    target.ResizeTo(source1);
02673 
02674    const Element *sp1 = source1.GetMatrixArray();
02675    const Element *sp2 = source2.GetMatrixArray();
02676          Element *tp  = target.GetMatrixArray();
02677    const Element * const tp_last = tp+target.GetNoElements();
02678    while (tp < tp_last) {
02679       *tp++ = (*sp1) >= (*sp2); sp1++; sp2++;
02680    }
02681 
02682    return target;
02683 }
02684 
02685 //______________________________________________________________________________
02686 template<class Element>
02687 TMatrixT<Element> operator>=(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02688 {
02689 // logical operation source1 >= source2
02690 
02691    TMatrixT<Element> target;
02692 
02693    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02694       Error("operator>=(const TMatrixT&,const TMatrixTSym&)","matrices not compatible");
02695       return target;
02696    }
02697 
02698    target.ResizeTo(source1);
02699 
02700    const Element *sp1 = source1.GetMatrixArray();
02701    const Element *sp2 = source2.GetMatrixArray();
02702          Element *tp  = target.GetMatrixArray();
02703    const Element * const tp_last = tp+target.GetNoElements();
02704    while (tp < tp_last) {
02705       *tp++ = (*sp1) >= (*sp2); sp1++; sp2++;
02706    }
02707 
02708    return target;
02709 }
02710 
02711 //______________________________________________________________________________
02712 template<class Element>
02713 TMatrixT<Element> operator>=(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02714 {
02715 // logical operation source1 >= source2
02716 
02717    return operator<(source2,source1);
02718 }
02719 
02720 //______________________________________________________________________________
02721 template<class Element>
02722 TMatrixT<Element> operator<=(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02723 {
02724 // logical operation source1 <= source2
02725 
02726    TMatrixT<Element> target;
02727 
02728    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02729       Error("operator<=(const TMatrixT&,const TMatrixT&)","matrices not compatible");
02730       return target;
02731    }
02732 
02733    target.ResizeTo(source1);
02734 
02735    const Element *sp1 = source1.GetMatrixArray();
02736    const Element *sp2 = source2.GetMatrixArray();
02737          Element *tp  = target.GetMatrixArray();
02738    const Element * const tp_last = tp+target.GetNoElements();
02739    while (tp < tp_last) {
02740       *tp++ = (*sp1) <= (*sp2); sp1++; sp2++;
02741    }
02742 
02743    return target;
02744 }
02745 
02746 //______________________________________________________________________________
02747 template<class Element>
02748 TMatrixT<Element> operator<=(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02749 {
02750 // logical operation source1 <= source2
02751 
02752    TMatrixT<Element> target;
02753 
02754    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02755       Error("operator<=(const TMatrixT&,const TMatrixTSym&)","matrices not compatible");
02756       return target;
02757    }
02758 
02759    target.ResizeTo(source1);
02760 
02761    const Element *sp1 = source1.GetMatrixArray();
02762    const Element *sp2 = source2.GetMatrixArray();
02763          Element *tp  = target.GetMatrixArray();
02764    const Element * const tp_last = tp+target.GetNoElements();
02765    while (tp < tp_last) {
02766       *tp++ = (*sp1) <= (*sp2); sp1++; sp2++;
02767    }
02768 
02769    return target;
02770 }
02771 
02772 //______________________________________________________________________________
02773 template<class Element>
02774 TMatrixT<Element> operator<=(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02775 {
02776 // logical operation source1 <= source2
02777 
02778    return operator>(source2,source1);
02779 }
02780 
02781 //______________________________________________________________________________
02782 template<class Element>
02783 TMatrixT<Element> operator<(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02784 {
02785 // logical operation source1 < source2
02786 
02787    TMatrixT<Element> target;
02788 
02789    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02790       Error("operator<(const TMatrixT&,const TMatrixT&)","matrices not compatible");
02791       return target;
02792    }
02793 
02794    const Element *sp1 = source1.GetMatrixArray();
02795    const Element *sp2 = source2.GetMatrixArray();
02796          Element *tp  = target.GetMatrixArray();
02797    const Element * const tp_last = tp+target.GetNoElements();
02798    while (tp < tp_last) {
02799       *tp++ = (*sp1) < (*sp2); sp1++; sp2++;
02800    }
02801 
02802    return target;
02803 }
02804 
02805 //______________________________________________________________________________
02806 template<class Element>
02807 TMatrixT<Element> operator<(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02808 {
02809 // logical operation source1 < source2
02810 
02811   TMatrixT<Element> target;
02812 
02813    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02814       Error("operator<(const TMatrixT&,const TMatrixTSym&)","matrices not compatible");
02815       return target;
02816    }
02817 
02818    target.ResizeTo(source1);
02819 
02820    const Element *sp1 = source1.GetMatrixArray();
02821    const Element *sp2 = source2.GetMatrixArray();
02822          Element *tp  = target.GetMatrixArray();
02823    const Element * const tp_last = tp+target.GetNoElements();
02824    while (tp < tp_last) {
02825       *tp++ = (*sp1) < (*sp2); sp1++; sp2++;
02826    }
02827 
02828    return target;
02829 }
02830 
02831 //______________________________________________________________________________
02832 template<class Element>
02833 TMatrixT<Element> operator<(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02834 {
02835 // logical operation source1 < source2
02836 
02837    return operator>=(source2,source1);
02838 }
02839 
02840 //______________________________________________________________________________
02841 template<class Element>
02842 TMatrixT<Element> operator!=(const TMatrixT<Element> &source1,const TMatrixT<Element> &source2)
02843 {
02844 // logical operation source1 != source2
02845 
02846    TMatrixT<Element> target;
02847 
02848    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02849       Error("operator!=(const TMatrixT&,const TMatrixT&)","matrices not compatible");
02850       return target;
02851    }
02852 
02853    target.ResizeTo(source1);
02854 
02855    const Element *sp1 = source1.GetMatrixArray();
02856    const Element *sp2 = source2.GetMatrixArray();
02857          Element *tp  = target.GetMatrixArray();
02858    const Element * const tp_last = tp+target.GetNoElements();
02859    while (tp != tp_last) {
02860       *tp++ = (*sp1) != (*sp2); sp1++; sp2++;
02861    }
02862 
02863    return target;
02864 }
02865 
02866 //______________________________________________________________________________
02867 template<class Element>
02868 TMatrixT<Element> operator!=(const TMatrixT<Element> &source1,const TMatrixTSym<Element> &source2)
02869 {
02870 // logical operation source1 != source2
02871 
02872    TMatrixT<Element> target;
02873 
02874    if (gMatrixCheck && !AreCompatible(source1,source2)) {
02875       Error("operator!=(const TMatrixT&,const TMatrixTSym&)","matrices not compatible");
02876       return target;
02877    }
02878 
02879    target.ResizeTo(source1);
02880 
02881    const Element *sp1 = source1.GetMatrixArray();
02882    const Element *sp2 = source2.GetMatrixArray();
02883          Element *tp  = target.GetMatrixArray();
02884    const Element * const tp_last = tp+target.GetNoElements();
02885    while (tp != tp_last) {
02886       *tp++ = (*sp1) != (*sp2); sp1++; sp2++;
02887    }
02888 
02889    return target;
02890 }
02891 
02892 //______________________________________________________________________________
02893 template<class Element>
02894 TMatrixT<Element> operator!=(const TMatrixTSym<Element> &source1,const TMatrixT<Element> &source2)
02895 {
02896 // logical operation source1 != source2
02897 
02898    return operator!=(source2,source1);
02899 }
02900 
02901 /*
02902 //______________________________________________________________________________
02903 template<class Element>
02904 TMatrixT<Element> operator!=(const TMatrixT<Element> &source1,Element val)
02905 {
02906 // logical operation source1 != val
02907 
02908    TMatrixT<Element> target; target.ResizeTo(source1);
02909 
02910    const Element *sp = source1.GetMatrixArray();
02911          Element *tp = target.GetMatrixArray();
02912    const Element * const tp_last = tp+target.GetNoElements();
02913    while (tp != tp_last) {
02914       *tp++ = (*sp != val); sp++;
02915    }
02916 
02917    return target;
02918 }
02919 
02920 //______________________________________________________________________________
02921 template<class Element>
02922 TMatrixT<Element> operator!=(Element val,const TMatrixT<Element> &source1)
02923 {
02924 // logical operation source1 != val
02925 
02926    return operator!=(source1,val);
02927 }
02928 */
02929 
02930 //______________________________________________________________________________
02931 template<class Element>
02932 TMatrixT<Element> &Add(TMatrixT<Element> &target,Element scalar,const TMatrixT<Element> &source)
02933 {
02934 // Modify addition: target += scalar * source.
02935 
02936    if (gMatrixCheck && !AreCompatible(target,source)) {
02937       ::Error("Add(TMatrixT &,Element,const TMatrixT &)","matrices not compatible");
02938       return target;
02939    }
02940 
02941    const Element *sp  = source.GetMatrixArray();
02942          Element *tp  = target.GetMatrixArray();
02943    const Element *ftp = tp+target.GetNoElements();
02944    if (scalar == 0) {
02945        while ( tp < ftp )
02946           *tp++  = scalar * (*sp++);
02947    } else if (scalar == 1.) {
02948        while ( tp < ftp )
02949           *tp++ = (*sp++);
02950    } else {
02951        while ( tp < ftp )
02952           *tp++ += scalar * (*sp++);
02953    }
02954 
02955    return target;
02956 }
02957 
02958 //______________________________________________________________________________
02959 template<class Element>
02960 TMatrixT<Element> &Add(TMatrixT<Element> &target,Element scalar,const TMatrixTSym<Element> &source)
02961 {
02962 // Modify addition: target += scalar * source.
02963 
02964    if (gMatrixCheck && !AreCompatible(target,source)) {
02965       ::Error("Add(TMatrixT &,Element,const TMatrixTSym &)","matrices not compatible");
02966       return target;
02967    }
02968 
02969    const Element *sp  = source.GetMatrixArray();
02970          Element *tp  = target.GetMatrixArray();
02971    const Element *ftp = tp+target.GetNoElements();
02972    while ( tp < ftp )
02973       *tp++ += scalar * (*sp++);
02974 
02975    return target;
02976 }
02977 
02978 //______________________________________________________________________________
02979 template<class Element>
02980 TMatrixT<Element> &ElementMult(TMatrixT<Element> &target,const TMatrixT<Element> &source)
02981 {
02982 // Multiply target by the source, element-by-element.
02983 
02984    if (gMatrixCheck && !AreCompatible(target,source)) {
02985       ::Error("ElementMult(TMatrixT &,const TMatrixT &)","matrices not compatible");
02986       return target;
02987    }
02988 
02989    const Element *sp  = source.GetMatrixArray();
02990          Element *tp  = target.GetMatrixArray();
02991    const Element *ftp = tp+target.GetNoElements();
02992    while ( tp < ftp )
02993       *tp++ *= *sp++;
02994 
02995    return target;
02996 }
02997 
02998 //______________________________________________________________________________
02999 template<class Element>
03000 TMatrixT<Element> &ElementMult(TMatrixT<Element> &target,const TMatrixTSym<Element> &source)
03001 {
03002 // Multiply target by the source, element-by-element.
03003 
03004    if (gMatrixCheck && !AreCompatible(target,source)) {
03005       ::Error("ElementMult(TMatrixT &,const TMatrixTSym &)","matrices not compatible");
03006       return target;
03007    }
03008 
03009    const Element *sp  = source.GetMatrixArray();
03010          Element *tp  = target.GetMatrixArray();
03011    const Element *ftp = tp+target.GetNoElements();
03012    while ( tp < ftp )
03013       *tp++ *= *sp++;
03014 
03015    return target;
03016 }
03017 
03018 //______________________________________________________________________________
03019 template<class Element>
03020 TMatrixT<Element> &ElementDiv(TMatrixT<Element> &target,const TMatrixT<Element> &source)
03021 {
03022 // Divide target by the source, element-by-element.
03023 
03024    if (gMatrixCheck && !AreCompatible(target,source)) {
03025       ::Error("ElementDiv(TMatrixT &,const TMatrixT &)","matrices not compatible");
03026       return target;
03027    }
03028 
03029    const Element *sp  = source.GetMatrixArray();
03030          Element *tp  = target.GetMatrixArray();
03031    const Element *ftp = tp+target.GetNoElements();
03032    while ( tp < ftp ) {
03033       if (*sp != 0.0)
03034          *tp++ /= *sp++;
03035       else {
03036          const Int_t irow = (sp-source.GetMatrixArray())/source.GetNcols();
03037          const Int_t icol = (sp-source.GetMatrixArray())%source.GetNcols();
03038          Error("ElementDiv","source (%d,%d) is zero",irow,icol);
03039          tp++;
03040       }
03041    }
03042 
03043    return target;
03044 }
03045 
03046 //______________________________________________________________________________
03047 template<class Element>
03048 TMatrixT<Element> &ElementDiv(TMatrixT<Element> &target,const TMatrixTSym<Element> &source)
03049 {
03050 // Multiply target by the source, element-by-element.
03051 
03052    if (gMatrixCheck && !AreCompatible(target,source)) {
03053       ::Error("ElementDiv(TMatrixT &,const TMatrixTSym &)","matrices not compatible");
03054       return target;
03055    }
03056 
03057    const Element *sp  = source.GetMatrixArray();
03058          Element *tp  = target.GetMatrixArray();
03059    const Element *ftp = tp+target.GetNoElements();
03060    while ( tp < ftp ) {
03061       if (*sp != 0.0)
03062          *tp++ /= *sp++;
03063       else {
03064          const Int_t irow = (sp-source.GetMatrixArray())/source.GetNcols();
03065          const Int_t icol = (sp-source.GetMatrixArray())%source.GetNcols();
03066          Error("ElementDiv","source (%d,%d) is zero",irow,icol);
03067          *tp++ = 0.0;
03068       }
03069    }
03070 
03071    return target;
03072 }
03073 
03074 //______________________________________________________________________________
03075 template<class Element>
03076 void AMultB(const Element * const ap,Int_t na,Int_t ncolsa,
03077             const Element * const bp,Int_t nb,Int_t ncolsb,Element *cp)
03078 {
03079 // Elementary routine to calculate matrix multiplication A*B
03080 
03081    const Element *arp0 = ap;                     // Pointer to  A[i,0];
03082    while (arp0 < ap+na) {
03083       for (const Element *bcp = bp; bcp < bp+ncolsb; ) { // Pointer to the j-th column of B, Start bcp = B[0,0]
03084          const Element *arp = arp0;                       // Pointer to the i-th row of A, reset to A[i,0]
03085          Element cij = 0;
03086          while (bcp < bp+nb) {                     // Scan the i-th row of A and
03087             cij += *arp++ * *bcp;                   // the j-th col of B
03088             bcp += ncolsb;
03089          }
03090          *cp++ = cij;
03091          bcp -= nb-1;                              // Set bcp to the (j+1)-th col
03092       }
03093       arp0 += ncolsa;                             // Set ap to the (i+1)-th row
03094    }
03095 }
03096 
03097 //______________________________________________________________________________
03098 template<class Element>
03099 void AtMultB(const Element * const ap,Int_t ncolsa,
03100              const Element * const bp,Int_t nb,Int_t ncolsb,Element *cp)
03101 {
03102 // Elementary routine to calculate matrix multiplication A^T*B
03103 
03104    const Element *acp0 = ap;           // Pointer to  A[i,0];
03105    while (acp0 < ap+ncolsa) {
03106       for (const Element *bcp = bp; bcp < bp+ncolsb; ) { // Pointer to the j-th column of B, Start bcp = B[0,0]
03107          const Element *acp = acp0;                       // Pointer to the i-th column of A, reset to A[0,i]
03108          Element cij = 0;
03109          while (bcp < bp+nb) {           // Scan the i-th column of A and
03110             cij += *acp * *bcp;           // the j-th col of B
03111             acp += ncolsa;
03112             bcp += ncolsb;
03113          }
03114          *cp++ = cij;
03115          bcp -= nb-1;                    // Set bcp to the (j+1)-th col
03116       }
03117       acp0++;                           // Set acp0 to the (i+1)-th col
03118    }
03119 }
03120 
03121 //______________________________________________________________________________
03122 template<class Element>
03123 void AMultBt(const Element * const ap,Int_t na,Int_t ncolsa,
03124              const Element * const bp,Int_t nb,Int_t ncolsb,Element *cp)
03125 {
03126 // Elementary routine to calculate matrix multiplication A*B^T
03127 
03128    const Element *arp0 = ap;                    // Pointer to  A[i,0];
03129    while (arp0 < ap+na) {
03130       const Element *brp0 = bp;                  // Pointer to  B[j,0];
03131       while (brp0 < bp+nb) {
03132          const Element *arp = arp0;               // Pointer to the i-th row of A, reset to A[i,0]
03133          const Element *brp = brp0;               // Pointer to the j-th row of B, reset to B[j,0]
03134          Element cij = 0;
03135          while (brp < brp0+ncolsb)                 // Scan the i-th row of A and
03136             cij += *arp++ * *brp++;                 // the j-th row of B
03137          *cp++ = cij;
03138          brp0 += ncolsb;                           // Set brp0 to the (j+1)-th row
03139       }
03140       arp0 += ncolsa;                             // Set arp0 to the (i+1)-th row
03141    }
03142 }
03143 
03144 //______________________________________________________________________________
03145 template<class Element>
03146 void TMatrixT<Element>::Streamer(TBuffer &R__b)
03147 {
03148 // Stream an object of class TMatrixT.
03149 
03150    if (R__b.IsReading()) {
03151       UInt_t R__s, R__c;
03152       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
03153       if (R__v > 2) {
03154          Clear();
03155          R__b.ReadClassBuffer(TMatrixT<Element>::Class(),this,R__v,R__s,R__c);
03156       } else if (R__v == 2) { //process old version 2
03157          Clear();
03158          TObject::Streamer(R__b);
03159          this->MakeValid();
03160          R__b >> this->fNrows;
03161          R__b >> this->fNcols;
03162          R__b >> this->fNelems;
03163          R__b >> this->fRowLwb;
03164          R__b >> this->fColLwb;
03165          Char_t isArray;
03166          R__b >> isArray;
03167          if (isArray) {
03168             if (this->fNelems > 0) {
03169                fElements = new Element[this->fNelems];
03170                R__b.ReadFastArray(fElements,this->fNelems);
03171             } else
03172                fElements = 0;
03173          }
03174          R__b.CheckByteCount(R__s,R__c,TMatrixT<Element>::IsA());
03175       } else { //====process old versions before automatic schema evolution
03176          TObject::Streamer(R__b);
03177          this->MakeValid();
03178          R__b >> this->fNrows;
03179          R__b >> this->fNcols;
03180          R__b >> this->fRowLwb;
03181          R__b >> this->fColLwb;
03182          this->fNelems = R__b.ReadArray(fElements);
03183          R__b.CheckByteCount(R__s,R__c,TMatrixT<Element>::IsA());
03184       }
03185       // in version <=2 , the matrix was stored column-wise
03186       if (R__v <= 2 && fElements) {
03187          for (Int_t i = 0; i < this->fNrows; i++) {
03188             const Int_t off_i = i*this->fNcols;
03189             for (Int_t j = i; j < this->fNcols; j++) {
03190                const Int_t off_j = j*this->fNrows;
03191                const Element tmp = fElements[off_i+j];
03192                fElements[off_i+j] = fElements[off_j+i];
03193                fElements[off_j+i] = tmp;
03194             }
03195          }
03196       }
03197       if (this->fNelems > 0 && this->fNelems <= this->kSizeMax) {
03198          if (fElements) {
03199             memcpy(fDataStack,fElements,this->fNelems*sizeof(Element));
03200             delete [] fElements;
03201          }
03202          fElements = fDataStack;
03203       } else if (this->fNelems < 0)
03204          this->Invalidate();
03205       } else {
03206          R__b.WriteClassBuffer(TMatrixT<Element>::Class(),this);
03207    }
03208 }
03209 
03210 template class TMatrixT<Float_t>;
03211 
03212 #ifndef ROOT_TMatrixFfwd
03213 #include "TMatrixFfwd.h"
03214 #endif
03215 #ifndef ROOT_TMatrixFSymfwd
03216 #include "TMatrixFSymfwd.h"
03217 #endif
03218 
03219 template TMatrixF  operator+  <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03220 template TMatrixF  operator+  <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03221 template TMatrixF  operator+  <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03222 template TMatrixF  operator+  <Float_t>(const TMatrixF    &source ,      Float_t      val    );
03223 template TMatrixF  operator+  <Float_t>(      Float_t      val    ,const TMatrixF    &source );
03224 template TMatrixF  operator-  <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03225 template TMatrixF  operator-  <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03226 template TMatrixF  operator-  <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03227 template TMatrixF  operator-  <Float_t>(const TMatrixF    &source ,      Float_t      val    );
03228 template TMatrixF  operator-  <Float_t>(      Float_t      val    ,const TMatrixF    &source );
03229 template TMatrixF  operator*  <Float_t>(      Float_t      val    ,const TMatrixF    &source );
03230 template TMatrixF  operator*  <Float_t>(const TMatrixF    &source ,      Float_t      val    );
03231 template TMatrixF  operator*  <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03232 template TMatrixF  operator*  <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03233 template TMatrixF  operator*  <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03234 template TMatrixF  operator*  <Float_t>(const TMatrixFSym &source1,const TMatrixFSym &source2);
03235 template TMatrixF  operator&& <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03236 template TMatrixF  operator&& <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03237 template TMatrixF  operator&& <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03238 template TMatrixF  operator|| <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03239 template TMatrixF  operator|| <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03240 template TMatrixF  operator|| <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03241 template TMatrixF  operator>  <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03242 template TMatrixF  operator>  <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03243 template TMatrixF  operator>  <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03244 template TMatrixF  operator>= <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03245 template TMatrixF  operator>= <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03246 template TMatrixF  operator>= <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03247 template TMatrixF  operator<= <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03248 template TMatrixF  operator<= <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03249 template TMatrixF  operator<= <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03250 template TMatrixF  operator<  <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03251 template TMatrixF  operator<  <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03252 template TMatrixF  operator<  <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03253 template TMatrixF  operator!= <Float_t>(const TMatrixF    &source1,const TMatrixF    &source2);
03254 template TMatrixF  operator!= <Float_t>(const TMatrixF    &source1,const TMatrixFSym &source2);
03255 template TMatrixF  operator!= <Float_t>(const TMatrixFSym &source1,const TMatrixF    &source2);
03256 
03257 template TMatrixF &Add        <Float_t>(TMatrixF &target,      Float_t      scalar,const TMatrixF    &source);
03258 template TMatrixF &Add        <Float_t>(TMatrixF &target,      Float_t      scalar,const TMatrixFSym &source);
03259 template TMatrixF &ElementMult<Float_t>(TMatrixF &target,const TMatrixF    &source);
03260 template TMatrixF &ElementMult<Float_t>(TMatrixF &target,const TMatrixFSym &source);
03261 template TMatrixF &ElementDiv <Float_t>(TMatrixF &target,const TMatrixF    &source);
03262 template TMatrixF &ElementDiv <Float_t>(TMatrixF &target,const TMatrixFSym &source);
03263 
03264 template void AMultB <Float_t>(const Float_t * const ap,Int_t na,Int_t ncolsa,
03265                                const Float_t * const bp,Int_t nb,Int_t ncolsb,Float_t *cp);
03266 template void AtMultB<Float_t>(const Float_t * const ap,Int_t ncolsa,
03267                                const Float_t * const bp,Int_t nb,Int_t ncolsb,Float_t *cp);
03268 template void AMultBt<Float_t>(const Float_t * const ap,Int_t na,Int_t ncolsa,
03269                                const Float_t * const bp,Int_t nb,Int_t ncolsb,Float_t *cp);
03270 
03271 #ifndef ROOT_TMatrixDfwd
03272 #include "TMatrixDfwd.h"
03273 #endif
03274 #ifndef ROOT_TMatrixDSymfwd
03275 #include "TMatrixDSymfwd.h"
03276 #endif
03277 
03278 template class TMatrixT<Double_t>;
03279 
03280 template TMatrixD  operator+  <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03281 template TMatrixD  operator+  <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03282 template TMatrixD  operator+  <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03283 template TMatrixD  operator+  <Double_t>(const TMatrixD    &source ,      Double_t     val    );
03284 template TMatrixD  operator+  <Double_t>(      Double_t     val    ,const TMatrixD    &source );
03285 template TMatrixD  operator-  <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03286 template TMatrixD  operator-  <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03287 template TMatrixD  operator-  <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03288 template TMatrixD  operator-  <Double_t>(const TMatrixD    &source ,      Double_t     val    );
03289 template TMatrixD  operator-  <Double_t>(      Double_t     val    ,const TMatrixD    &source );
03290 template TMatrixD  operator*  <Double_t>(      Double_t     val    ,const TMatrixD    &source );
03291 template TMatrixD  operator*  <Double_t>(const TMatrixD    &source ,      Double_t     val    );
03292 template TMatrixD  operator*  <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03293 template TMatrixD  operator*  <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03294 template TMatrixD  operator*  <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03295 template TMatrixD  operator*  <Double_t>(const TMatrixDSym &source1,const TMatrixDSym &source2);
03296 template TMatrixD  operator&& <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03297 template TMatrixD  operator&& <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03298 template TMatrixD  operator&& <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03299 template TMatrixD  operator|| <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03300 template TMatrixD  operator|| <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03301 template TMatrixD  operator|| <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03302 template TMatrixD  operator>  <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03303 template TMatrixD  operator>  <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03304 template TMatrixD  operator>  <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03305 template TMatrixD  operator>= <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03306 template TMatrixD  operator>= <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03307 template TMatrixD  operator>= <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03308 template TMatrixD  operator<= <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03309 template TMatrixD  operator<= <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03310 template TMatrixD  operator<= <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03311 template TMatrixD  operator<  <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03312 template TMatrixD  operator<  <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03313 template TMatrixD  operator<  <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03314 template TMatrixD  operator!= <Double_t>(const TMatrixD    &source1,const TMatrixD    &source2);
03315 template TMatrixD  operator!= <Double_t>(const TMatrixD    &source1,const TMatrixDSym &source2);
03316 template TMatrixD  operator!= <Double_t>(const TMatrixDSym &source1,const TMatrixD    &source2);
03317 
03318 template TMatrixD &Add        <Double_t>(TMatrixD &target,      Double_t     scalar,const TMatrixD    &source);
03319 template TMatrixD &Add        <Double_t>(TMatrixD &target,      Double_t     scalar,const TMatrixDSym &source);
03320 template TMatrixD &ElementMult<Double_t>(TMatrixD &target,const TMatrixD    &source);
03321 template TMatrixD &ElementMult<Double_t>(TMatrixD &target,const TMatrixDSym &source);
03322 template TMatrixD &ElementDiv <Double_t>(TMatrixD &target,const TMatrixD    &source);
03323 template TMatrixD &ElementDiv <Double_t>(TMatrixD &target,const TMatrixDSym &source);
03324 
03325 template void AMultB <Double_t>(const Double_t * const ap,Int_t na,Int_t ncolsa,
03326                                 const Double_t * const bp,Int_t nb,Int_t ncolsb,Double_t *cp);
03327 template void AtMultB<Double_t>(const Double_t * const ap,Int_t ncolsa,
03328                                 const Double_t * const bp,Int_t nb,Int_t ncolsb,Double_t *cp);
03329 template void AMultBt<Double_t>(const Double_t * const ap,Int_t na,Int_t ncolsa,
03330                                 const Double_t * const bp,Int_t nb,Int_t ncolsb,Double_t *cp);

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