#include #include #include // #include "TClass.h" #include "TMath.h" #include "AliSymMatrix.h" // using namespace std; ClassImp(AliSymMatrix) AliSymMatrix* AliSymMatrix::fgBuffer = 0; Int_t AliSymMatrix::fgCopyCnt = 0; //___________________________________________________________ AliSymMatrix::AliSymMatrix() : fElems(0),fElemsAdd(0) { fSymmetric = kTRUE; fgCopyCnt++; } //___________________________________________________________ AliSymMatrix::AliSymMatrix(Int_t size) : AliMatrixSq(),fElems(0),fElemsAdd(0) { // fNrows = 0; fNrowIndex = fNcols = size; fElems = new Double_t[fNcols*(fNcols+1)/2]; fSymmetric = kTRUE; Reset(); fgCopyCnt++; // } //___________________________________________________________ AliSymMatrix::AliSymMatrix(const AliSymMatrix &src) : AliMatrixSq(src),fElems(0),fElemsAdd(0) { fNrowIndex = fNcols = src.GetSize(); fNrows = 0; 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.fNrows) { // transfer extra rows to main matrix Double_t *pnt = fElems + nmainel; int ncl = src.fNcols + 1; for (int ir=0;irGetSize()!=GetSize()) { delete fgBuffer; try { fgBuffer = new AliSymMatrix(*this); } catch(bad_alloc&) { printf("Failed to allocate memory for Choleski decompostions\n"); 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 printf("The matrix is not positive definite [%e]\n" "Choleski decomposition is not possible\n",sum); 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) { printf("Failed to invert the matrix\n"); 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=fNrowIndex-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) { if (r>=fNrowIndex) { int nn = fNrowIndex; AddRows(r-fNrowIndex+1); printf("create %d of %d\n",r, nn); return &((fElemsAdd[r-fNcols])[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 = 0.00000000000001; int nGlo = GetSize(); 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 (vl==0) 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 (0.0 != rowMax[i]) rowMax[i] = 1./rowMax[i]; // Max elemt of row i if (0.0 != colMax[i]) colMax[i] = 1./colMax[i]; // Max elemt of column i } // } // for (Int_t i=nGlo; i--;) bUnUsed[i] = true; // if (!fgBuffer || fgBuffer->GetSize()!=GetSize()) { delete fgBuffer; try { fgBuffer = new AliSymMatrix(*this); } catch(bad_alloc&) { printf("Failed to allocate memory for matrix inversion buffer\n"); 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