#include "AliMatrixSparse.h"
#include "TStopwatch.h"
ClassImp(AliMatrixSparse)
AliMatrixSparse::AliMatrixSparse(Int_t sz)
: AliMatrixSq(),fVecs(0)
{
fNcols=fNrows=sz;
fVecs = new AliVectorSparse*[sz];
for (int i=GetSize();i--;) fVecs[i] = new AliVectorSparse();
}
AliMatrixSparse::AliMatrixSparse(const AliMatrixSparse& src)
: AliMatrixSq(src),fVecs(0)
{
fVecs = new AliVectorSparse*[src.GetSize()];
for (int i=GetSize();i--;) fVecs[i] = new AliVectorSparse( *src.GetRow(i));
}
AliVectorSparse* AliMatrixSparse::GetRowAdd(Int_t ir)
{
if (ir>=fNrows) {
AliVectorSparse** arrv = new AliVectorSparse*[ir+1];
for (int i=GetSize();i--;) arrv[i] = fVecs[i];
delete [] fVecs;
fVecs = arrv;
for (int i=GetSize();i<=ir;i++) fVecs[i] = new AliVectorSparse();
fNrows = ir+1;
if (IsSymmetric() && fNcols<fNrows) fNcols = fNrows;
}
return fVecs[ir];
}
AliMatrixSparse& AliMatrixSparse::operator=(const AliMatrixSparse& src)
{
if (this == &src) return *this;
AliMatrixSq::operator=(src);
Clear();
fNcols = src.GetNCols();
fNrows = src.GetNRows();
SetSymmetric(src.IsSymmetric());
fVecs = new AliVectorSparse*[fNrows];
for (int i=fNrows;i--;) fVecs[i] = new AliVectorSparse( *src.GetRow(i));
return *this;
}
void AliMatrixSparse::Clear(Option_t*)
{
for (int i=fNrows;i--;) delete GetRow(i);
delete [] fVecs;
fNcols = fNrows = 0;
}
void AliMatrixSparse::Print(Option_t* opt) const
{
printf("Sparse Matrix of size %d x %d %s\n",fNrows,fNcols,IsSymmetric() ? " (Symmetric)":"");
for (int i=0;i<fNrows;i++) {
AliVectorSparse* row = GetRow(i);
if (!row->GetNElems()) continue;
printf("%3d: ",i);
row->Print(opt);
}
}
void AliMatrixSparse::MultiplyByVec(const Double_t* vecIn, Double_t* vecOut) const
{
memset(vecOut,0,GetSize()*sizeof(Double_t));
for (int rw=GetSize();rw--;) {
const AliVectorSparse* rowV = GetRow(rw);
Int_t nel = rowV->GetNElems();
if (!nel) continue;
UShort_t* indV = rowV->GetIndices();
Double_t* elmV = rowV->GetElems();
if (IsSymmetric()) {
if (indV[--nel]==rw) vecOut[rw] += vecIn[rw]*elmV[nel];
else nel = rowV->GetNElems();
for (int iel=nel;iel--;) {
if (elmV[iel]) {
vecOut[rw] += vecIn[indV[iel]]*elmV[iel];
vecOut[indV[iel]] += vecIn[rw]*elmV[iel];
}
}
}
else for (int iel=nel;iel--;) if (elmV[iel]) vecOut[rw] += vecIn[indV[iel]]*elmV[iel];
}
}
void AliMatrixSparse::SortIndices(Bool_t valuesToo)
{
TStopwatch sw;
sw.Start();
printf("AliMatrixSparse:sort>>\n");
for (int i=GetSize();i--;) GetRow(i)->SortIndices(valuesToo);
sw.Stop();
sw.Print();
printf("AliMatrixSparse:sort<<\n");
}
void AliMatrixSparse::AddToRow(Int_t r, Double_t *valc,Int_t *indc,Int_t n)
{
for (int i=n;i--;) {
for (int j=i;j>=0;j--) {
if (indc[j]>indc[i]) {
int ti = indc[i]; indc[i] = indc[j]; indc[j] = ti;
double tv = valc[i]; valc[i] = valc[j]; valc[j] = tv;
}
}
}
int ni=n;
if (IsSymmetric()) {
while(ni--) {
if (indc[ni]>r) (*this)(indc[ni],r) += valc[ni];
else break;
}
}
if (ni<0) return;
AliVectorSparse* row = GetRowAdd(r);
row->Add(valc,indc,ni+1);
}
Float_t AliMatrixSparse::GetDensity() const
{
Int_t nel = 0;
for (int i=GetSize();i--;) nel += GetRow(i)->GetNElems();
int den = IsSymmetric() ? (GetSize()+1)*GetSize()/2 : GetSize()*GetSize();
return float(nel)/den;
}