/**********************************************************************************************/ /* Fast symmetric matrix with dynamically expandable size. */ /* Only part can be used for matrix operations. It is defined as: */ /* fNCols: rows built by constructor (GetSizeBooked) */ /* fNRows: number of rows added dynamically (automatically added on assignment to row) */ /* GetNRowAdded */ /* fNRowIndex: total size (fNCols+fNRows), GetSize */ /* fRowLwb : actual size to used for given operation, by default = total size, GetSizeUsed */ /* */ /* Author: ruben.shahoyan@cern.ch */ /* */ /**********************************************************************************************/ #include #include #include #include #include // #include #include #include "AliSymMatrix.h" #include "AliLog.h" // using namespace std; ClassImp(AliSymMatrix) AliSymMatrix* AliSymMatrix::fgBuffer = 0; Int_t AliSymMatrix::fgCopyCnt = 0; //___________________________________________________________ AliSymMatrix::AliSymMatrix() : fElems(0),fElemsAdd(0) { // default constructor fSymmetric = kTRUE; fgCopyCnt++; } //___________________________________________________________ AliSymMatrix::AliSymMatrix(Int_t size) : AliMatrixSq(),fElems(0),fElemsAdd(0) { //constructor for matrix with defined size fNrows = 0; fNrowIndex = fNcols = fRowLwb = size; fElems = new Double_t[fNcols*(fNcols+1)/2]; fSymmetric = kTRUE; Reset(); fgCopyCnt++; // } //___________________________________________________________ AliSymMatrix::AliSymMatrix(const AliSymMatrix &src) : AliMatrixSq(src),fElems(0),fElemsAdd(0) { // copy constructor fNrowIndex = fNcols = src.GetSize(); fNrows = 0; fRowLwb = src.GetSizeUsed(); if (fNcols) { int nmainel = fNcols*(fNcols+1)/2; fElems = new Double_t[nmainel]; nmainel = src.fNcols*(src.fNcols+1)/2; memcpy(fElems,src.fElems,nmainel*sizeof(Double_t)); if (src.GetSizeAdded()) { // transfer extra rows to main matrix Double_t *pnt = fElems + nmainel; int ncl = src.GetSizeBooked() + 1; for (int ir=0;irGetSizeUsed()!=GetSizeUsed()) { delete fgBuffer; try { fgBuffer = new AliSymMatrix(*this); } catch(bad_alloc&) { AliInfo("Failed to allocate memory for Choleski decompostions"); return 0; } } else (*fgBuffer) = *this; // AliSymMatrix& mchol = *fgBuffer; // for (int i=0;i=0;k--) if (rowi[k]&&rowj[k]) sum -= rowi[k]*rowj[k]; if (i == j) { if (sum <= 0.0) { // not positive-definite AliInfo(Form("The matrix is not positive definite [%e]\n" "Choleski decomposition is not possible",sum)); Print("l"); return 0; } rowi[i] = TMath::Sqrt(sum); // } else rowj[i] = sum/rowi[i]; } } return fgBuffer; } //___________________________________________________________ Bool_t AliSymMatrix::InvertChol() { // Invert matrix using Choleski decomposition // AliSymMatrix* mchol = DecomposeChol(); if (!mchol) { AliInfo("Failed to invert the matrix"); return kFALSE; } // InvertChol(mchol); return kTRUE; // } //___________________________________________________________ void AliSymMatrix::InvertChol(AliSymMatrix* pmchol) { // Invert matrix using Choleski decomposition, provided the Cholseki's L matrix // Double_t sum; AliSymMatrix& mchol = *pmchol; // // Invert decomposed triangular L matrix (Lower triangle is filled) for (int i=0;i=0;k--) if (rowi[k]&&b[k]) sum -= rowi[k]*b[k]; b[i]=sum/rowi[i]; } // for (i=GetSizeUsed()-1;i>=0;i--) { for (sum=b[i],k=i+1;k=fNrowIndex) { AddRows(r-fNrowIndex+1); row = &((fElemsAdd[r-fNcols])[0]); } else row = &fElems[GetIndex(r,0)]; // int nadd = 0; for (int i=n;i--;) { if (indc[i]>r) continue; row[indc[i]] += valc[i]; nadd++; } if (nadd == n) return; // // add to col>row for (int i=n;i--;) { if (indc[i]>r) (*this)(indc[i],r) += valc[i]; } // } */ //___________________________________________________________ Double_t* AliSymMatrix::GetRow(Int_t r) { // get pointer on the row if (r>=GetSize()) { int nn = GetSize(); AddRows(r-GetSize()+1); AliDebug(2,Form("create %d of %d\n",r, nn)); return &((fElemsAdd[r-GetSizeBooked()])[0]); } else return &fElems[GetIndex(r,0)]; } //___________________________________________________________ int AliSymMatrix::SolveSpmInv(double *vecB, Bool_t stabilize) { // Solution a la MP1: gaussian eliminations /// Obtain solution of a system of linear equations with symmetric matrix /// and the inverse (using 'singular-value friendly' GAUSS pivot) // Int_t nRank = 0; int iPivot; double vPivot = 0.; double eps = 1e-14; int nGlo = GetSizeUsed(); bool *bUnUsed = new bool[nGlo]; double *rowMax,*colMax=0; rowMax = new double[nGlo]; // if (stabilize) { colMax = new double[nGlo]; for (Int_t i=nGlo; i--;) rowMax[i] = colMax[i] = 0.0; for (Int_t i=nGlo; i--;) for (Int_t j=i+1;j--;) { double vl = TMath::Abs(Query(i,j)); if (IsZero(vl)) continue; if (vl > rowMax[i]) rowMax[i] = vl; // Max elemt of row i if (vl > colMax[j]) colMax[j] = vl; // Max elemt of column j if (i==j) continue; if (vl > rowMax[j]) rowMax[j] = vl; // Max elemt of row j if (vl > colMax[i]) colMax[i] = vl; // Max elemt of column i } // for (Int_t i=nGlo; i--;) { if (!IsZero(rowMax[i])) rowMax[i] = 1./rowMax[i]; // Max elemt of row i if (!IsZero(colMax[i])) colMax[i] = 1./colMax[i]; // Max elemt of column i } // } // for (Int_t i=nGlo; i--;) bUnUsed[i] = true; // if (!fgBuffer || fgBuffer->GetSizeUsed()!=GetSizeUsed()) { delete fgBuffer; try { fgBuffer = new AliSymMatrix(*this); } catch(bad_alloc&) { AliError("Failed to allocate memory for matrix inversion buffer"); return 0; } } else (*fgBuffer) = *this; // if (stabilize) for (int i=0;iSetEl(j,i,TMath::Sqrt(rowMax[i])*vl*TMath::Sqrt(colMax[j]) ); // Equilibrate the V matrix } } // for (Int_t j=nGlo; j--;) fgBuffer->DiagElem(j) = TMath::Abs(QueryDiag(j)); // save diagonal elem absolute values // for (Int_t i=0; iTMath::Max(TMath::Abs(vPivot),eps*fgBuffer->QueryDiag(j)))) { vPivot = vl; iPivot = j; } } // if (iPivot >= 0) { // pivot found nRank++; bUnUsed[iPivot] = false; // This value is used vPivot = 1.0/vPivot; DiagElem(iPivot) = -vPivot; // Replace pivot by its inverse // for (Int_t j=0; j=jj ? (*this)(j,jj) : (*fgBuffer)(jj,j); r -= vPivot* ( j>iPivot ? Query(j,iPivot) : fgBuffer->Query(iPivot,j) ) * ( iPivot>jj ? Query(iPivot,jj) : fgBuffer->Query(jj,iPivot)); } } } // for (Int_t j=0; j=j) (*this)(i,j) *= vl; else (*fgBuffer)(j,i) *= vl; } // for (Int_t j=0; j=jj) vl = (*this)(j,jj) = -Query(j,jj); else vl = (*fgBuffer)(j,jj) = -fgBuffer->Query(j,jj); rowMax[j] += vl*vecB[jj]; } } for (Int_t j=0; j