ROOT logo

/*********************************************************************************/
/* Symmetric Band Diagonal matrix with half band width W (+1 for diagonal)       */
/* Only lower triangle is stored in the "profile" format                         */ 
/*                                                                               */ 
/*                                                                               */
/* Author: ruben.shahoyan@cern.ch                                                */
/*                                                                               */ 
/*********************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <float.h>
//
#include "TClass.h"
#include "TMath.h"
#include "AliSymBDMatrix.h"
//

ClassImp(AliSymBDMatrix)


//___________________________________________________________
AliSymBDMatrix::AliSymBDMatrix() 
: fElems(0)
{
  // def. c-tor
  fSymmetric = kTRUE;
}

//___________________________________________________________
AliSymBDMatrix::AliSymBDMatrix(Int_t size, Int_t w)
  : AliMatrixSq(),fElems(0)
{
  // c-tor for given size
  //
  fNcols = size;    // number of rows
  if (w<0) w = 0;
  if (w>=size) w = size-1;
  fNrows = w;
  fRowLwb = w+1;
  fSymmetric = kTRUE;
  //
  // total number of stored elements
  fNelems = size*(w+1) - w*(w+1)/2;
  //
  fElems = new Double_t[fNcols*fRowLwb];
  memset(fElems,0,fNcols*fRowLwb*sizeof(Double_t));
  //
}

//___________________________________________________________
AliSymBDMatrix::AliSymBDMatrix(const AliSymBDMatrix &src) 
  : AliMatrixSq(src),fElems(0)
{
  // copy c-tor
  if (src.GetSize()<1) return;
  fNcols = src.GetSize();
  fNrows = src.GetBandHWidth();
  fRowLwb = fNrows+1;
  fNelems = src.GetNElemsStored();
  fElems = new Double_t[fNcols*fRowLwb];
  memcpy(fElems,src.fElems,fNcols*fRowLwb*sizeof(Double_t));
  //
}

//___________________________________________________________
AliSymBDMatrix::~AliSymBDMatrix() 
{
  // d-tor
  Clear();
}

//___________________________________________________________
AliSymBDMatrix&  AliSymBDMatrix::operator=(const AliSymBDMatrix& src)
{
  // assignment
  //
  if (this != &src) {
    TObject::operator=(src);
    if (fNcols!=src.fNcols) {
      // recreate the matrix
      if (fElems) delete[] fElems;
      fNcols = src.GetSize();
      fNrows = src.GetBandHWidth();
      fNelems = src.GetNElemsStored();
      fRowLwb = src.fRowLwb;
      fElems = new Double_t[fNcols*fRowLwb];
    }
    memcpy(fElems,src.fElems,fNcols*fRowLwb*sizeof(Double_t));     
    fSymmetric = kTRUE;
  }
  //
  return *this;
  //
}

//___________________________________________________________
void AliSymBDMatrix::Clear(Option_t*)
{
  // clear dynamic part
  if (fElems) {delete[] fElems; fElems = 0;}
  //  
  fNelems = fNcols = fNrows = fRowLwb = 0;
  //
}

//___________________________________________________________
Float_t AliSymBDMatrix::GetDensity() const
{
  // get fraction of non-zero elements
  if (!fNelems) return 0;
  Int_t nel = 0;
  for (int i=fNelems;i--;) if (!IsZero(fElems[i])) nel++;
  return nel/fNelems;
}

//___________________________________________________________
void AliSymBDMatrix::Print(Option_t* option) const
{
  // print data
  printf("Symmetric Band-Diagonal Matrix : Size = %d, half bandwidth = %d\n",
	 GetSize(),GetBandHWidth());
  TString opt = option; opt.ToLower();
  if (opt.IsNull()) return;
  opt = "%"; opt += 1+int(TMath::Log10(double(GetSize()))); opt+="d|";
  for (Int_t i=0;i<GetSize();i++) {
    printf(opt,i);
    for (Int_t j=TMath::Max(0,i-GetBandHWidth());j<=i;j++) printf("%+.3e|",GetEl(i,j));
    printf("\n");
  }
}

//___________________________________________________________
void AliSymBDMatrix::MultiplyByVec(const Double_t *vecIn,Double_t *vecOut) const
{
  // fill vecOut by matrix*vecIn
  // vector should be of the same size as the matrix
  if (IsDecomposed()) {
    for (int i=0;i<GetSize();i++) {
      double sm = 0;
      int jmax = TMath::Min(GetSize(),i+fRowLwb);
      for (int j=i+1;j<jmax;j++) sm += vecIn[j]*Query(j,i);
      vecOut[i] = QueryDiag(i)*(vecIn[i]+sm);
    }
    for (int i=GetSize();i--;) {
      double sm = 0;
      int jmin = TMath::Max(0,i - GetBandHWidth());
      int jmax = i-1;
      for (int j=jmin;j<jmax;j++) sm += vecOut[j]*Query(i,j);
      vecOut[i] += sm;
    }
  }
  else { // not decomposed
    for (int i=GetSize();i--;) {
      vecOut[i] = 0.0;
      int jmin = TMath::Max(0,i - GetBandHWidth());
      int jmax = TMath::Min(GetSize(),i + fRowLwb);
      for (int j=jmin;j<jmax;j++) vecOut[i] += vecIn[j]*Query(i,j);
    }
  }
  //
}

//___________________________________________________________
void AliSymBDMatrix::Reset()
{
  // set all elems to 0
  if (fElems) memset(fElems,0,fNcols*fRowLwb*sizeof(Double_t));
  SetDecomposed(kFALSE);
  //
}

//___________________________________________________________
void AliSymBDMatrix::AddToRow(Int_t r, Double_t *valc,Int_t *indc,Int_t n)
{
  // add list of elements to row r
  for (int i=0;i<n;i++) (*this)(r,indc[i]) = valc[i];
}

//___________________________________________________________
void AliSymBDMatrix::DecomposeLDLT()
{
  // decomposition to L Diag L^T
  if (IsDecomposed()) return;
  //
  Double_t eps = std::numeric_limits<double>::epsilon()*std::numeric_limits<double>::epsilon();
  //
  Double_t dtmp,gamma=0.0,xi=0.0;
  int iDiag;
  //
  // find max diag and number of non-0 diag.elements
  for (dtmp=0.0,iDiag=0;iDiag<GetSize();iDiag++) {
    if ( (dtmp=QueryDiag(iDiag)) <=0.0) break;
    if (gamma < dtmp) gamma = dtmp; 
  }
  //
  // find max. off-diag element
  for (int ir=1;ir<iDiag;ir++) {
    for (int ic=ir-GetBandHWidth();ic<ir;ic++) {
      if (ic<0) continue;
      dtmp = TMath::Abs(Query(ir,ic));
      if (xi<dtmp) xi = dtmp;
    }
  }
  double delta = eps*TMath::Max(1.0,xi+gamma);
  //
  double sn = GetSize()>1 ? 1.0/TMath::Sqrt( GetSize()*GetSize() - 1.0) : 1.0;
  double beta = TMath::Sqrt(TMath::Max(eps,TMath::Max(gamma,xi*sn))); 
  //
  for (int kr=1;kr<GetSize();kr++) {
    int colKmin = TMath::Max(0,kr - GetBandHWidth());
    double theta = 0.0;
    //
    for (int jr=colKmin;jr<=kr;jr++) {
      int colJmin = TMath::Max(0,jr - GetBandHWidth());
      //
      dtmp = 0.0;
      for (int i=TMath::Max(colKmin,colJmin);i<jr;i++) 
	dtmp += Query(kr,i)*QueryDiag(i)*Query(jr,i);
      dtmp = (*this)(kr,jr) -= dtmp;
      //
      theta = TMath::Max(theta, TMath::Abs(dtmp));
      //
      if (jr!=kr) {
	if (!IsZero(QueryDiag(jr))) (*this)(kr,jr) /= QueryDiag(jr);
	else                        (*this)(kr,jr) = 0.0;
      }
      else if (kr<iDiag) {
	dtmp = theta/beta;
	dtmp *= dtmp;
	dtmp = TMath::Max(dtmp, delta);
	(*this)(kr,jr) = TMath::Max( TMath::Abs(Query(kr,jr)), dtmp); 
      }
    } // jr
  } // kr
  //
  for (int i=0;i<GetSize();i++) {
    dtmp = QueryDiag(i);
    if (!IsZero(dtmp)) DiagElem(i) = 1./dtmp;
  }
  //
  SetDecomposed();
}

//___________________________________________________________
void AliSymBDMatrix::Solve(Double_t *rhs)
{
  // solve matrix equation
  //
  if (!IsDecomposed()) DecomposeLDLT();
  //
  for (int kr=0;kr<GetSize();kr++) 
    for (int jr=TMath::Max(0,kr-GetBandHWidth());jr<kr;jr++) rhs[kr] -= Query(kr,jr)*rhs[jr];
  //
  for (int kr=GetSize();kr--;) rhs[kr] *= QueryDiag(kr);
  //
  for (int kr=GetSize();kr--;)
    for (int jr=TMath::Max(0,kr - GetBandHWidth());jr<kr;jr++) rhs[jr] -= Query(kr,jr)*rhs[kr];
  //
}

//___________________________________________________________
void AliSymBDMatrix::Solve(const Double_t *rhs,Double_t *sol)
{
  // solve matrix equation
  memcpy(sol,rhs,GetSize()*sizeof(Double_t));
  Solve(sol);
  //
}
 AliSymBDMatrix.cxx:1
 AliSymBDMatrix.cxx:2
 AliSymBDMatrix.cxx:3
 AliSymBDMatrix.cxx:4
 AliSymBDMatrix.cxx:5
 AliSymBDMatrix.cxx:6
 AliSymBDMatrix.cxx:7
 AliSymBDMatrix.cxx:8
 AliSymBDMatrix.cxx:9
 AliSymBDMatrix.cxx:10
 AliSymBDMatrix.cxx:11
 AliSymBDMatrix.cxx:12
 AliSymBDMatrix.cxx:13
 AliSymBDMatrix.cxx:14
 AliSymBDMatrix.cxx:15
 AliSymBDMatrix.cxx:16
 AliSymBDMatrix.cxx:17
 AliSymBDMatrix.cxx:18
 AliSymBDMatrix.cxx:19
 AliSymBDMatrix.cxx:20
 AliSymBDMatrix.cxx:21
 AliSymBDMatrix.cxx:22
 AliSymBDMatrix.cxx:23
 AliSymBDMatrix.cxx:24
 AliSymBDMatrix.cxx:25
 AliSymBDMatrix.cxx:26
 AliSymBDMatrix.cxx:27
 AliSymBDMatrix.cxx:28
 AliSymBDMatrix.cxx:29
 AliSymBDMatrix.cxx:30
 AliSymBDMatrix.cxx:31
 AliSymBDMatrix.cxx:32
 AliSymBDMatrix.cxx:33
 AliSymBDMatrix.cxx:34
 AliSymBDMatrix.cxx:35
 AliSymBDMatrix.cxx:36
 AliSymBDMatrix.cxx:37
 AliSymBDMatrix.cxx:38
 AliSymBDMatrix.cxx:39
 AliSymBDMatrix.cxx:40
 AliSymBDMatrix.cxx:41
 AliSymBDMatrix.cxx:42
 AliSymBDMatrix.cxx:43
 AliSymBDMatrix.cxx:44
 AliSymBDMatrix.cxx:45
 AliSymBDMatrix.cxx:46
 AliSymBDMatrix.cxx:47
 AliSymBDMatrix.cxx:48
 AliSymBDMatrix.cxx:49
 AliSymBDMatrix.cxx:50
 AliSymBDMatrix.cxx:51
 AliSymBDMatrix.cxx:52
 AliSymBDMatrix.cxx:53
 AliSymBDMatrix.cxx:54
 AliSymBDMatrix.cxx:55
 AliSymBDMatrix.cxx:56
 AliSymBDMatrix.cxx:57
 AliSymBDMatrix.cxx:58
 AliSymBDMatrix.cxx:59
 AliSymBDMatrix.cxx:60
 AliSymBDMatrix.cxx:61
 AliSymBDMatrix.cxx:62
 AliSymBDMatrix.cxx:63
 AliSymBDMatrix.cxx:64
 AliSymBDMatrix.cxx:65
 AliSymBDMatrix.cxx:66
 AliSymBDMatrix.cxx:67
 AliSymBDMatrix.cxx:68
 AliSymBDMatrix.cxx:69
 AliSymBDMatrix.cxx:70
 AliSymBDMatrix.cxx:71
 AliSymBDMatrix.cxx:72
 AliSymBDMatrix.cxx:73
 AliSymBDMatrix.cxx:74
 AliSymBDMatrix.cxx:75
 AliSymBDMatrix.cxx:76
 AliSymBDMatrix.cxx:77
 AliSymBDMatrix.cxx:78
 AliSymBDMatrix.cxx:79
 AliSymBDMatrix.cxx:80
 AliSymBDMatrix.cxx:81
 AliSymBDMatrix.cxx:82
 AliSymBDMatrix.cxx:83
 AliSymBDMatrix.cxx:84
 AliSymBDMatrix.cxx:85
 AliSymBDMatrix.cxx:86
 AliSymBDMatrix.cxx:87
 AliSymBDMatrix.cxx:88
 AliSymBDMatrix.cxx:89
 AliSymBDMatrix.cxx:90
 AliSymBDMatrix.cxx:91
 AliSymBDMatrix.cxx:92
 AliSymBDMatrix.cxx:93
 AliSymBDMatrix.cxx:94
 AliSymBDMatrix.cxx:95
 AliSymBDMatrix.cxx:96
 AliSymBDMatrix.cxx:97
 AliSymBDMatrix.cxx:98
 AliSymBDMatrix.cxx:99
 AliSymBDMatrix.cxx:100
 AliSymBDMatrix.cxx:101
 AliSymBDMatrix.cxx:102
 AliSymBDMatrix.cxx:103
 AliSymBDMatrix.cxx:104
 AliSymBDMatrix.cxx:105
 AliSymBDMatrix.cxx:106
 AliSymBDMatrix.cxx:107
 AliSymBDMatrix.cxx:108
 AliSymBDMatrix.cxx:109
 AliSymBDMatrix.cxx:110
 AliSymBDMatrix.cxx:111
 AliSymBDMatrix.cxx:112
 AliSymBDMatrix.cxx:113
 AliSymBDMatrix.cxx:114
 AliSymBDMatrix.cxx:115
 AliSymBDMatrix.cxx:116
 AliSymBDMatrix.cxx:117
 AliSymBDMatrix.cxx:118
 AliSymBDMatrix.cxx:119
 AliSymBDMatrix.cxx:120
 AliSymBDMatrix.cxx:121
 AliSymBDMatrix.cxx:122
 AliSymBDMatrix.cxx:123
 AliSymBDMatrix.cxx:124
 AliSymBDMatrix.cxx:125
 AliSymBDMatrix.cxx:126
 AliSymBDMatrix.cxx:127
 AliSymBDMatrix.cxx:128
 AliSymBDMatrix.cxx:129
 AliSymBDMatrix.cxx:130
 AliSymBDMatrix.cxx:131
 AliSymBDMatrix.cxx:132
 AliSymBDMatrix.cxx:133
 AliSymBDMatrix.cxx:134
 AliSymBDMatrix.cxx:135
 AliSymBDMatrix.cxx:136
 AliSymBDMatrix.cxx:137
 AliSymBDMatrix.cxx:138
 AliSymBDMatrix.cxx:139
 AliSymBDMatrix.cxx:140
 AliSymBDMatrix.cxx:141
 AliSymBDMatrix.cxx:142
 AliSymBDMatrix.cxx:143
 AliSymBDMatrix.cxx:144
 AliSymBDMatrix.cxx:145
 AliSymBDMatrix.cxx:146
 AliSymBDMatrix.cxx:147
 AliSymBDMatrix.cxx:148
 AliSymBDMatrix.cxx:149
 AliSymBDMatrix.cxx:150
 AliSymBDMatrix.cxx:151
 AliSymBDMatrix.cxx:152
 AliSymBDMatrix.cxx:153
 AliSymBDMatrix.cxx:154
 AliSymBDMatrix.cxx:155
 AliSymBDMatrix.cxx:156
 AliSymBDMatrix.cxx:157
 AliSymBDMatrix.cxx:158
 AliSymBDMatrix.cxx:159
 AliSymBDMatrix.cxx:160
 AliSymBDMatrix.cxx:161
 AliSymBDMatrix.cxx:162
 AliSymBDMatrix.cxx:163
 AliSymBDMatrix.cxx:164
 AliSymBDMatrix.cxx:165
 AliSymBDMatrix.cxx:166
 AliSymBDMatrix.cxx:167
 AliSymBDMatrix.cxx:168
 AliSymBDMatrix.cxx:169
 AliSymBDMatrix.cxx:170
 AliSymBDMatrix.cxx:171
 AliSymBDMatrix.cxx:172
 AliSymBDMatrix.cxx:173
 AliSymBDMatrix.cxx:174
 AliSymBDMatrix.cxx:175
 AliSymBDMatrix.cxx:176
 AliSymBDMatrix.cxx:177
 AliSymBDMatrix.cxx:178
 AliSymBDMatrix.cxx:179
 AliSymBDMatrix.cxx:180
 AliSymBDMatrix.cxx:181
 AliSymBDMatrix.cxx:182
 AliSymBDMatrix.cxx:183
 AliSymBDMatrix.cxx:184
 AliSymBDMatrix.cxx:185
 AliSymBDMatrix.cxx:186
 AliSymBDMatrix.cxx:187
 AliSymBDMatrix.cxx:188
 AliSymBDMatrix.cxx:189
 AliSymBDMatrix.cxx:190
 AliSymBDMatrix.cxx:191
 AliSymBDMatrix.cxx:192
 AliSymBDMatrix.cxx:193
 AliSymBDMatrix.cxx:194
 AliSymBDMatrix.cxx:195
 AliSymBDMatrix.cxx:196
 AliSymBDMatrix.cxx:197
 AliSymBDMatrix.cxx:198
 AliSymBDMatrix.cxx:199
 AliSymBDMatrix.cxx:200
 AliSymBDMatrix.cxx:201
 AliSymBDMatrix.cxx:202
 AliSymBDMatrix.cxx:203
 AliSymBDMatrix.cxx:204
 AliSymBDMatrix.cxx:205
 AliSymBDMatrix.cxx:206
 AliSymBDMatrix.cxx:207
 AliSymBDMatrix.cxx:208
 AliSymBDMatrix.cxx:209
 AliSymBDMatrix.cxx:210
 AliSymBDMatrix.cxx:211
 AliSymBDMatrix.cxx:212
 AliSymBDMatrix.cxx:213
 AliSymBDMatrix.cxx:214
 AliSymBDMatrix.cxx:215
 AliSymBDMatrix.cxx:216
 AliSymBDMatrix.cxx:217
 AliSymBDMatrix.cxx:218
 AliSymBDMatrix.cxx:219
 AliSymBDMatrix.cxx:220
 AliSymBDMatrix.cxx:221
 AliSymBDMatrix.cxx:222
 AliSymBDMatrix.cxx:223
 AliSymBDMatrix.cxx:224
 AliSymBDMatrix.cxx:225
 AliSymBDMatrix.cxx:226
 AliSymBDMatrix.cxx:227
 AliSymBDMatrix.cxx:228
 AliSymBDMatrix.cxx:229
 AliSymBDMatrix.cxx:230
 AliSymBDMatrix.cxx:231
 AliSymBDMatrix.cxx:232
 AliSymBDMatrix.cxx:233
 AliSymBDMatrix.cxx:234
 AliSymBDMatrix.cxx:235
 AliSymBDMatrix.cxx:236
 AliSymBDMatrix.cxx:237
 AliSymBDMatrix.cxx:238
 AliSymBDMatrix.cxx:239
 AliSymBDMatrix.cxx:240
 AliSymBDMatrix.cxx:241
 AliSymBDMatrix.cxx:242
 AliSymBDMatrix.cxx:243
 AliSymBDMatrix.cxx:244
 AliSymBDMatrix.cxx:245
 AliSymBDMatrix.cxx:246
 AliSymBDMatrix.cxx:247
 AliSymBDMatrix.cxx:248
 AliSymBDMatrix.cxx:249
 AliSymBDMatrix.cxx:250
 AliSymBDMatrix.cxx:251
 AliSymBDMatrix.cxx:252
 AliSymBDMatrix.cxx:253
 AliSymBDMatrix.cxx:254
 AliSymBDMatrix.cxx:255
 AliSymBDMatrix.cxx:256
 AliSymBDMatrix.cxx:257
 AliSymBDMatrix.cxx:258
 AliSymBDMatrix.cxx:259
 AliSymBDMatrix.cxx:260
 AliSymBDMatrix.cxx:261
 AliSymBDMatrix.cxx:262
 AliSymBDMatrix.cxx:263
 AliSymBDMatrix.cxx:264
 AliSymBDMatrix.cxx:265
 AliSymBDMatrix.cxx:266
 AliSymBDMatrix.cxx:267
 AliSymBDMatrix.cxx:268
 AliSymBDMatrix.cxx:269
 AliSymBDMatrix.cxx:270