// @(#)root/matrix:$Id$ // Authors: Fons Rademakers, Eddy Offermann Nov 2003 /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ /** \class TMatrixTUtils \ingroup Matrix Matrix utility classes. Templates of utility classes in the Linear Algebra Package. The following classes are defined here: Different matrix views without copying data elements : ~~~ TMatrixTRow_const TMatrixTRow TMatrixTColumn_const TMatrixTColumn TMatrixTDiag_const TMatrixTDiag TMatrixTFlat_const TMatrixTFlat TMatrixTSub_const TMatrixTSub TMatrixTSparseRow_const TMatrixTSparseRow TMatrixTSparseDiag_const TMatrixTSparseDiag TElementActionT TElementPosActionT ~~~ */ #include "TMatrixTUtils.h" #include "TMatrixT.h" #include "TMatrixTSym.h" #include "TMatrixTSparse.h" #include "TMath.h" #include "TVectorT.h" //////////////////////////////////////////////////////////////////////////////// /// Constructor with row "row" of matrix template TMatrixTRow_const::TMatrixTRow_const(const TMatrixT &matrix,Int_t row) { R__ASSERT(matrix.IsValid()); fRowInd = row-matrix.GetRowLwb(); if (fRowInd >= matrix.GetNrows() || fRowInd < 0) { Error("TMatrixTRow_const(const TMatrixT &,Int_t)","row index out of bounds"); fMatrix = nullptr; fPtr = nullptr; fInc = 0; return; } fMatrix = &matrix; fPtr = matrix.GetMatrixArray()+fRowInd*matrix.GetNcols(); fInc = 1; } //////////////////////////////////////////////////////////////////////////////// /// Constructor with row "row" of symmetric matrix template TMatrixTRow_const::TMatrixTRow_const(const TMatrixTSym &matrix,Int_t row) { R__ASSERT(matrix.IsValid()); fRowInd = row-matrix.GetRowLwb(); if (fRowInd >= matrix.GetNrows() || fRowInd < 0) { Error("TMatrixTRow_const(const TMatrixTSym &,Int_t)","row index out of bounds"); fMatrix = nullptr; fPtr = nullptr; fInc = 0; return; } fMatrix = &matrix; fPtr = matrix.GetMatrixArray()+fRowInd*matrix.GetNcols(); fInc = 1; } //////////////////////////////////////////////////////////////////////////////// /// Constructor with row "row" of symmetric matrix template TMatrixTRow::TMatrixTRow(TMatrixT &matrix,Int_t row) :TMatrixTRow_const(matrix,row) { } //////////////////////////////////////////////////////////////////////////////// /// Constructor with row "row" of symmetric matrix template TMatrixTRow::TMatrixTRow(TMatrixTSym &matrix,Int_t row) :TMatrixTRow_const(matrix,row) { } //////////////////////////////////////////////////////////////////////////////// /// Copy constructor template TMatrixTRow::TMatrixTRow(const TMatrixTRow &mr) : TMatrixTRow_const(mr) { *this = mr; } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every element of the matrix row. template void TMatrixTRow::Assign(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *rp = const_cast(this->fPtr); for ( ; rp < this->fPtr+this->fMatrix->GetNcols(); rp += this->fInc) *rp = val; } template void TMatrixTRow::operator=(std::initializer_list l) { R__ASSERT(this->fMatrix->IsValid()); Element *rp = const_cast(this->fPtr); auto litr = l.begin(); for ( ; rp < this->fPtr+this->fMatrix->GetNcols() && litr != l.end(); rp += this->fInc) *rp = *litr++; } //////////////////////////////////////////////////////////////////////////////// /// Add val to every element of the matrix row. template void TMatrixTRow::operator+=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *rp = const_cast(this->fPtr); for ( ; rp < this->fPtr+this->fMatrix->GetNcols(); rp += this->fInc) *rp += val; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix row with val. template void TMatrixTRow::operator*=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *rp = const_cast(this->fPtr); for ( ; rp < this->fPtr + this->fMatrix->GetNcols(); rp += this->fInc) *rp *= val; } //////////////////////////////////////////////////////////////////////////////// /// Assignment operator template void TMatrixTRow::operator=(const TMatrixTRow_const &mr) { const TMatrixTBase *mt = mr.GetMatrix(); if (this->fMatrix->GetMatrixArray() == mt->GetMatrixArray() && this->fRowInd == mr.GetRowIndex()) return; R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetNcols() != mt->GetNcols() || this->fMatrix->GetColLwb() != mt->GetColLwb()) { Error("operator=(const TMatrixTRow_const &)", "matrix rows not compatible"); return; } Element *rp1 = const_cast(this->fPtr); const Element *rp2 = mr.GetPtr(); for ( ; rp1 < this->fPtr+this->fMatrix->GetNcols(); rp1 += this->fInc,rp2 += mr.GetInc()) *rp1 = *rp2; } //////////////////////////////////////////////////////////////////////////////// /// Assign a vector to a matrix row. The vector is considered row-vector /// to allow the assignment in the strict sense. template void TMatrixTRow::operator=(const TVectorT &vec) { R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(vec.IsValid()); if (this->fMatrix->GetColLwb() != vec.GetLwb() || this->fMatrix->GetNcols() != vec.GetNrows()) { Error("operator=(const TVectorT &)","vector length != matrix-row length"); return; } Element *rp = const_cast(this->fPtr); const Element *vp = vec.GetMatrixArray(); for ( ; rp < this->fPtr+this->fMatrix->GetNcols(); rp += this->fInc) *rp = *vp++; } //////////////////////////////////////////////////////////////////////////////// /// Add to every element of the matrix row the corresponding element of row r. template void TMatrixTRow::operator+=(const TMatrixTRow_const &r) { const TMatrixTBase *mt = r.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetColLwb() != mt->GetColLwb() || this->fMatrix->GetNcols() != mt->GetNcols()) { Error("operator+=(const TMatrixTRow_const &)","different row lengths"); return; } Element *rp1 = const_cast(this->fPtr); const Element *rp2 = r.GetPtr(); for ( ; rp1 < this->fPtr+this->fMatrix->GetNcols(); rp1 += this->fInc,rp2 += r.GetInc()) *rp1 += *rp2; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix row with the /// corresponding element of row r. template void TMatrixTRow::operator*=(const TMatrixTRow_const &r) { const TMatrixTBase *mt = r.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetColLwb() != mt->GetColLwb() || this->fMatrix->GetNcols() != mt->GetNcols()) { Error("operator*=(const TMatrixTRow_const &)","different row lengths"); return; } Element *rp1 = const_cast(this->fPtr); const Element *rp2 = r.GetPtr(); for ( ; rp1 < this->fPtr+this->fMatrix->GetNcols(); rp1 += this->fInc,rp2 += r.GetInc()) *rp1 *= *rp2; } //////////////////////////////////////////////////////////////////////////////// /// Constructor with column "col" of matrix template TMatrixTColumn_const::TMatrixTColumn_const(const TMatrixT &matrix,Int_t col) { R__ASSERT(matrix.IsValid()); this->fColInd = col-matrix.GetColLwb(); if (this->fColInd >= matrix.GetNcols() || this->fColInd < 0) { Error("TMatrixTColumn_const(const TMatrixT &,Int_t)","column index out of bounds"); fMatrix = nullptr; fPtr = nullptr; fInc = 0; return; } fMatrix = &matrix; fPtr = matrix.GetMatrixArray()+fColInd; fInc = matrix.GetNcols(); } //////////////////////////////////////////////////////////////////////////////// /// Constructor with column "col" of matrix template TMatrixTColumn_const::TMatrixTColumn_const(const TMatrixTSym &matrix,Int_t col) { R__ASSERT(matrix.IsValid()); fColInd = col-matrix.GetColLwb(); if (fColInd >= matrix.GetNcols() || fColInd < 0) { Error("TMatrixTColumn_const(const TMatrixTSym &,Int_t)","column index out of bounds"); fMatrix = nullptr; fPtr = nullptr; fInc = 0; return; } fMatrix = &matrix; fPtr = matrix.GetMatrixArray()+fColInd; fInc = matrix.GetNcols(); } //////////////////////////////////////////////////////////////////////////////// /// Constructor with column "col" of matrix template TMatrixTColumn::TMatrixTColumn(TMatrixT &matrix,Int_t col) :TMatrixTColumn_const(matrix,col) { } //////////////////////////////////////////////////////////////////////////////// /// Constructor with column "col" of matrix template TMatrixTColumn::TMatrixTColumn(TMatrixTSym &matrix,Int_t col) :TMatrixTColumn_const(matrix,col) { } //////////////////////////////////////////////////////////////////////////////// /// Copy constructor template TMatrixTColumn::TMatrixTColumn(const TMatrixTColumn &mc) : TMatrixTColumn_const(mc) { *this = mc; } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every element of the matrix column. template void TMatrixTColumn::Assign(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *cp = const_cast(this->fPtr); for ( ; cp < this->fPtr+this->fMatrix->GetNoElements(); cp += this->fInc) *cp = val; } //////////////////////////////////////////////////////////////////////////////// /// Assign element of the matrix column using given initializer list template void TMatrixTColumn::operator=(std::initializer_list l) { R__ASSERT(this->fMatrix->IsValid()); Element *rp = const_cast(this->fPtr); auto litr = l.begin(); for ( ; rp < this->fPtr+this->fMatrix->GetNoElements() && litr != l.end(); rp += this->fInc) *rp = *litr++; } //////////////////////////////////////////////////////////////////////////////// /// Add val to every element of the matrix column. template void TMatrixTColumn::operator+=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *cp = const_cast(this->fPtr); for ( ; cp < this->fPtr+this->fMatrix->GetNoElements(); cp += this->fInc) *cp += val; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix column with val. template void TMatrixTColumn::operator*=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *cp = const_cast(this->fPtr); for ( ; cp < this->fPtr+this->fMatrix->GetNoElements(); cp += this->fInc) *cp *= val; } //////////////////////////////////////////////////////////////////////////////// /// Assignment operator template void TMatrixTColumn::operator=(const TMatrixTColumn_const &mc) { const TMatrixTBase *mt = mc.GetMatrix(); if (this->fMatrix->GetMatrixArray() == mt->GetMatrixArray() && this->fColInd == mc.GetColIndex()) return; R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetNrows() != mt->GetNrows() || this->fMatrix->GetRowLwb() != mt->GetRowLwb()) { Error("operator=(const TMatrixTColumn_const &)", "matrix columns not compatible"); return; } Element *cp1 = const_cast(this->fPtr); const Element *cp2 = mc.GetPtr(); for ( ; cp1 < this->fPtr+this->fMatrix->GetNoElements(); cp1 += this->fInc,cp2 += mc.GetInc()) *cp1 = *cp2; } //////////////////////////////////////////////////////////////////////////////// /// Assign a vector to a matrix column. template void TMatrixTColumn::operator=(const TVectorT &vec) { R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(vec.IsValid()); if (this->fMatrix->GetRowLwb() != vec.GetLwb() || this->fMatrix->GetNrows() != vec.GetNrows()) { Error("operator=(const TVectorT &)","vector length != matrix-column length"); return; } Element *cp = const_cast(this->fPtr); const Element *vp = vec.GetMatrixArray(); for ( ; cp < this->fPtr+this->fMatrix->GetNoElements(); cp += this->fInc) *cp = *vp++; R__ASSERT(vp == vec.GetMatrixArray()+vec.GetNrows()); } //////////////////////////////////////////////////////////////////////////////// /// Add to every element of the matrix row the corresponding element of row mc. template void TMatrixTColumn::operator+=(const TMatrixTColumn_const &mc) { const TMatrixTBase *mt = mc.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetRowLwb() != mt->GetRowLwb() || this->fMatrix->GetNrows() != mt->GetNrows()) { Error("operator+=(const TMatrixTColumn_const &)","different row lengths"); return; } Element *cp1 = const_cast(this->fPtr); const Element *cp2 = mc.GetPtr(); for ( ; cp1 < this->fPtr+this->fMatrix->GetNoElements(); cp1 += this->fInc,cp2 += mc.GetInc()) *cp1 += *cp2; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix column with the /// corresponding element of column mc. template void TMatrixTColumn::operator*=(const TMatrixTColumn_const &mc) { const TMatrixTBase *mt = mc.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetRowLwb() != mt->GetRowLwb() || this->fMatrix->GetNrows() != mt->GetNrows()) { Error("operator*=(const TMatrixTColumn_const &)","different row lengths"); return; } Element *cp1 = const_cast(this->fPtr); const Element *cp2 = mc.GetPtr(); for ( ; cp1 < this->fPtr+this->fMatrix->GetNoElements(); cp1 += this->fInc,cp2 += mc.GetInc()) *cp1 *= *cp2; } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTDiag_const::TMatrixTDiag_const(const TMatrixT &matrix) { R__ASSERT(matrix.IsValid()); fMatrix = &matrix; fNdiag = TMath::Min(matrix.GetNrows(),matrix.GetNcols()); fPtr = matrix.GetMatrixArray(); fInc = matrix.GetNcols()+1; } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTDiag_const::TMatrixTDiag_const(const TMatrixTSym &matrix) { R__ASSERT(matrix.IsValid()); fMatrix = &matrix; fNdiag = TMath::Min(matrix.GetNrows(),matrix.GetNcols()); fPtr = matrix.GetMatrixArray(); fInc = matrix.GetNcols()+1; } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTDiag::TMatrixTDiag(TMatrixT &matrix) :TMatrixTDiag_const(matrix) { } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTDiag::TMatrixTDiag(TMatrixTSym &matrix) :TMatrixTDiag_const(matrix) { } //////////////////////////////////////////////////////////////////////////////// /// Copy constructor template TMatrixTDiag::TMatrixTDiag(const TMatrixTDiag &md) : TMatrixTDiag_const(md) { *this = md; } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every element of the matrix diagonal. template void TMatrixTDiag::operator=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *dp = const_cast(this->fPtr); for (Int_t i = 0; i < this->fNdiag; i++, dp += this->fInc) *dp = val; } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every element of the matrix diagonal. template void TMatrixTDiag::operator+=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *dp = const_cast(this->fPtr); for (Int_t i = 0; i < this->fNdiag; i++, dp += this->fInc) *dp += val; } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every element of the matrix diagonal. template void TMatrixTDiag::operator*=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *dp = const_cast(this->fPtr); for (Int_t i = 0; i < this->fNdiag; i++, dp += this->fInc) *dp *= val; } //////////////////////////////////////////////////////////////////////////////// /// Assignment operator template void TMatrixTDiag::operator=(const TMatrixTDiag_const &md) { const TMatrixTBase *mt = md.GetMatrix(); if (this->fMatrix == mt) return; R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->GetNdiags() != md.GetNdiags()) { Error("operator=(const TMatrixTDiag_const &)","diagonals not compatible"); return; } Element *dp1 = const_cast(this->fPtr); const Element *dp2 = md.GetPtr(); for (Int_t i = 0; i < this->fNdiag; i++, dp1 += this->fInc, dp2 += md.GetInc()) *dp1 = *dp2; } //////////////////////////////////////////////////////////////////////////////// /// Assign a vector to the matrix diagonal. template void TMatrixTDiag::operator=(const TVectorT &vec) { R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(vec.IsValid()); if (this->fNdiag != vec.GetNrows()) { Error("operator=(const TVectorT &)","vector length != matrix-diagonal length"); return; } Element *dp = const_cast(this->fPtr); const Element *vp = vec.GetMatrixArray(); for ( ; vp < vec.GetMatrixArray()+vec.GetNrows(); dp += this->fInc) *dp = *vp++; } //////////////////////////////////////////////////////////////////////////////// /// Add to every element of the matrix diagonal the /// corresponding element of diagonal md. template void TMatrixTDiag::operator+=(const TMatrixTDiag_const &md) { const TMatrixTBase *mt = md.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fNdiag != md.GetNdiags()) { Error("operator=(const TMatrixTDiag_const &)","matrix-diagonal's different length"); return; } Element *dp1 = const_cast(this->fPtr); const Element *dp2 = md.GetPtr(); for (Int_t i = 0; i < this->fNdiag; i++, dp1 += this->fInc, dp2 += md.GetInc()) *dp1 += *dp2; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix diagonal with the /// corresponding element of diagonal md. template void TMatrixTDiag::operator*=(const TMatrixTDiag_const &md) { const TMatrixTBase *mt = md.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fNdiag != md.GetNdiags()) { Error("operator*=(const TMatrixTDiag_const &)","matrix-diagonal's different length"); return; } Element *dp1 = const_cast(this->fPtr); const Element *dp2 = md.GetPtr(); for (Int_t i = 0; i < this->fNdiag; i++, dp1 += this->fInc, dp2 += md.GetInc()) *dp1 *= *dp2; } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTFlat_const::TMatrixTFlat_const(const TMatrixT &matrix) { R__ASSERT(matrix.IsValid()); fMatrix = &matrix; fPtr = matrix.GetMatrixArray(); fNelems = matrix.GetNoElements(); } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTFlat_const::TMatrixTFlat_const(const TMatrixTSym &matrix) { R__ASSERT(matrix.IsValid()); fMatrix = &matrix; fPtr = matrix.GetMatrixArray(); fNelems = matrix.GetNoElements(); } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTFlat::TMatrixTFlat(TMatrixT &matrix) :TMatrixTFlat_const(matrix) { } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTFlat::TMatrixTFlat(TMatrixTSym &matrix) :TMatrixTFlat_const(matrix) { } //////////////////////////////////////////////////////////////////////////////// /// Copy constructor template TMatrixTFlat::TMatrixTFlat(const TMatrixTFlat &mf) : TMatrixTFlat_const(mf) { *this = mf; } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every element of the matrix. template void TMatrixTFlat::operator=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *fp = const_cast(this->fPtr); while (fp < this->fPtr+this->fMatrix->GetNoElements()) *fp++ = val; } //////////////////////////////////////////////////////////////////////////////// /// Add val to every element of the matrix. template void TMatrixTFlat::operator+=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *fp = const_cast(this->fPtr); while (fp < this->fPtr+this->fMatrix->GetNoElements()) *fp++ += val; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix with val. template void TMatrixTFlat::operator*=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *fp = const_cast(this->fPtr); while (fp < this->fPtr+this->fMatrix->GetNoElements()) *fp++ *= val; } //////////////////////////////////////////////////////////////////////////////// /// Assignment operator template void TMatrixTFlat::operator=(const TMatrixTFlat_const &mf) { const TMatrixTBase *mt = mf.GetMatrix(); if (this->fMatrix->GetMatrixArray() == mt->GetMatrixArray()) return; R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetNoElements() != mt->GetNoElements()) { Error("operator=(const TMatrixTFlat_const &)","matrix lengths different"); return; } Element *fp1 = const_cast(this->fPtr); const Element *fp2 = mf.GetPtr(); while (fp1 < this->fPtr+this->fMatrix->GetNoElements()) *fp1++ = *fp2++; } //////////////////////////////////////////////////////////////////////////////// /// Assign a vector to the matrix. The matrix is traversed row-wise template void TMatrixTFlat::operator=(const TVectorT &vec) { R__ASSERT(vec.IsValid()); if (this->fMatrix->GetNoElements() != vec.GetNrows()) { Error("operator=(const TVectorT &)","vector length != # matrix-elements"); return; } Element *fp = const_cast(this->fPtr); const Element *vp = vec.GetMatrixArray(); while (fp < this->fPtr+this->fMatrix->GetNoElements()) *fp++ = *vp++; } //////////////////////////////////////////////////////////////////////////////// /// Add to every element of the matrix the corresponding element of matrix mf. template void TMatrixTFlat::operator+=(const TMatrixTFlat_const &mf) { const TMatrixTBase *mt = mf.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetNoElements() != mt->GetNoElements()) { Error("operator+=(const TMatrixTFlat_const &)","matrices lengths different"); return; } Element *fp1 = const_cast(this->fPtr); const Element *fp2 = mf.GetPtr(); while (fp1 < this->fPtr + this->fMatrix->GetNoElements()) *fp1++ += *fp2++; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix with the corresponding element of diagonal mf. template void TMatrixTFlat::operator*=(const TMatrixTFlat_const &mf) { const TMatrixTBase *mt = mf.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetNoElements() != mt->GetNoElements()) { Error("operator*=(const TMatrixTFlat_const &)","matrices lengths different"); return; } Element *fp1 = const_cast(this->fPtr); const Element *fp2 = mf.GetPtr(); while (fp1 < this->fPtr + this->fMatrix->GetNoElements()) *fp1++ *= *fp2++; } //////////////////////////////////////////////////////////////////////////////// /// make a reference to submatrix [row_lwbs..row_upbs][col_lwbs..col_upbs]; /// The indexing range of the reference is /// [0..row_upbs-row_lwbs+1][0..col_upb-col_lwbs+1] (default) template TMatrixTSub_const::TMatrixTSub_const(const TMatrixT &matrix,Int_t row_lwbs,Int_t row_upbs, Int_t col_lwbs,Int_t col_upbs) { R__ASSERT(matrix.IsValid()); fRowOff = 0; fColOff = 0; fNrowsSub = 0; fNcolsSub = 0; fMatrix = &matrix; if (row_upbs < row_lwbs) { Error("TMatrixTSub_const","Request sub-matrix with row_upbs(%d) < row_lwbs(%d)",row_upbs,row_lwbs); return; } if (col_upbs < col_lwbs) { Error("TMatrixTSub_const","Request sub-matrix with col_upbs(%d) < col_lwbs(%d)",col_upbs,col_lwbs); return; } const Int_t rowLwb = matrix.GetRowLwb(); const Int_t rowUpb = matrix.GetRowUpb(); const Int_t colLwb = matrix.GetColLwb(); const Int_t colUpb = matrix.GetColUpb(); if (row_lwbs < rowLwb || row_lwbs > rowUpb) { Error("TMatrixTSub_const","Request row_lwbs sub-matrix(%d) outside matrix range of %d - %d",row_lwbs,rowLwb,rowUpb); return; } if (col_lwbs < colLwb || col_lwbs > colUpb) { Error("TMatrixTSub_const","Request col_lwbs sub-matrix(%d) outside matrix range of %d - %d",col_lwbs,colLwb,colUpb); return; } if (row_upbs < rowLwb || row_upbs > rowUpb) { Error("TMatrixTSub_const","Request row_upbs sub-matrix(%d) outside matrix range of %d - %d",row_upbs,rowLwb,rowUpb); return; } if (col_upbs < colLwb || col_upbs > colUpb) { Error("TMatrixTSub_const","Request col_upbs sub-matrix(%d) outside matrix range of %d - %d",col_upbs,colLwb,colUpb); return; } fRowOff = row_lwbs-rowLwb; fColOff = col_lwbs-colLwb; fNrowsSub = row_upbs-row_lwbs+1; fNcolsSub = col_upbs-col_lwbs+1; } //////////////////////////////////////////////////////////////////////////////// /// make a reference to submatrix [row_lwbs..row_upbs][col_lwbs..col_upbs]; /// The indexing range of the reference is /// [0..row_upbs-row_lwbs+1][0..col_upb-col_lwbs+1] (default) template TMatrixTSub_const::TMatrixTSub_const(const TMatrixTSym &matrix,Int_t row_lwbs,Int_t row_upbs, Int_t col_lwbs,Int_t col_upbs) { R__ASSERT(matrix.IsValid()); fRowOff = 0; fColOff = 0; fNrowsSub = 0; fNcolsSub = 0; fMatrix = &matrix; if (row_upbs < row_lwbs) { Error("TMatrixTSub_const","Request sub-matrix with row_upbs(%d) < row_lwbs(%d)",row_upbs,row_lwbs); return; } if (col_upbs < col_lwbs) { Error("TMatrixTSub_const","Request sub-matrix with col_upbs(%d) < col_lwbs(%d)",col_upbs,col_lwbs); return; } const Int_t rowLwb = matrix.GetRowLwb(); const Int_t rowUpb = matrix.GetRowUpb(); const Int_t colLwb = matrix.GetColLwb(); const Int_t colUpb = matrix.GetColUpb(); if (row_lwbs < rowLwb || row_lwbs > rowUpb) { Error("TMatrixTSub_const","Request row_lwbs sub-matrix(%d) outside matrix range of %d - %d",row_lwbs,rowLwb,rowUpb); return; } if (col_lwbs < colLwb || col_lwbs > colUpb) { Error("TMatrixTSub_const","Request col_lwbs sub-matrix(%d) outside matrix range of %d - %d",col_lwbs,colLwb,colUpb); return; } if (row_upbs < rowLwb || row_upbs > rowUpb) { Error("TMatrixTSub_const","Request row_upbs sub-matrix(%d) outside matrix range of %d - %d",row_upbs,rowLwb,rowUpb); return; } if (col_upbs < colLwb || col_upbs > colUpb) { Error("TMatrixTSub_const","Request col_upbs sub-matrix(%d) outside matrix range of %d - %d",col_upbs,colLwb,colUpb); return; } fRowOff = row_lwbs-rowLwb; fColOff = col_lwbs-colLwb; fNrowsSub = row_upbs-row_lwbs+1; fNcolsSub = col_upbs-col_lwbs+1; } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTSub::TMatrixTSub(TMatrixT &matrix,Int_t row_lwbs,Int_t row_upbs, Int_t col_lwbs,Int_t col_upbs) :TMatrixTSub_const(matrix,row_lwbs,row_upbs,col_lwbs,col_upbs) { } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTSub::TMatrixTSub(TMatrixTSym &matrix,Int_t row_lwbs,Int_t row_upbs, Int_t col_lwbs,Int_t col_upbs) :TMatrixTSub_const(matrix,row_lwbs,row_upbs,col_lwbs,col_upbs) { } //////////////////////////////////////////////////////////////////////////////// /// Copy constructor template TMatrixTSub::TMatrixTSub(const TMatrixTSub &ms) : TMatrixTSub_const(ms) { *this = ms; } //////////////////////////////////////////////////////////////////////////////// /// Perform a rank 1 operation on the matrix: /// A += alpha * v * v^T template void TMatrixTSub::Rank1Update(const TVectorT &v,Element alpha) { R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(v.IsValid()); if (v.GetNoElements() < TMath::Max(this->fNrowsSub,this->fNcolsSub)) { Error("Rank1Update","vector too short"); return; } const Element * const pv = v.GetMatrixArray(); Element *mp = (const_cast *>(this->fMatrix))->GetMatrixArray(); const Int_t ncols = this->fMatrix->GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off = (irow+this->fRowOff)*ncols+this->fColOff; const Element tmp = alpha*pv[irow]; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) mp[off+icol] += tmp*pv[icol]; } } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every element of the sub matrix. template void TMatrixTSub::operator=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *p = (const_cast *>(this->fMatrix))->GetMatrixArray(); const Int_t ncols = this->fMatrix->GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off = (irow+this->fRowOff)*ncols+this->fColOff; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) p[off+icol] = val; } } //////////////////////////////////////////////////////////////////////////////// /// Add val to every element of the sub matrix. template void TMatrixTSub::operator+=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *p = (const_cast *>(this->fMatrix))->GetMatrixArray(); const Int_t ncols = this->fMatrix->GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off = (irow+this->fRowOff)*ncols+this->fColOff; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) p[off+icol] += val; } } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the sub matrix by val . template void TMatrixTSub::operator*=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *p = (const_cast *>(this->fMatrix))->GetMatrixArray(); const Int_t ncols = this->fMatrix->GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off = (irow+this->fRowOff)*ncols+this->fColOff; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) p[off+icol] *= val; } } //////////////////////////////////////////////////////////////////////////////// /// Assignment operator template void TMatrixTSub::operator=(const TMatrixTSub_const &ms) { const TMatrixTBase *mt = ms.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix == mt && (this->GetNrows() == ms.GetNrows () && this->GetNcols() == ms.GetNcols () && this->GetRowOff() == ms.GetRowOff() && this->GetColOff() == ms.GetColOff()) ) return; if (this->GetNrows() != ms.GetNrows() || this->GetNcols() != ms.GetNcols()) { Error("operator=(const TMatrixTSub_const &)","sub matrices have different size"); return; } const Int_t rowOff2 = ms.GetRowOff(); const Int_t colOff2 = ms.GetColOff(); Bool_t overlap = (this->fMatrix == mt) && ( (rowOff2 >= this->fRowOff && rowOff2 < this->fRowOff+this->fNrowsSub) || (colOff2 >= this->fColOff && colOff2 < this->fColOff+this->fNcolsSub) ); Element *p1 = const_cast(this->fMatrix->GetMatrixArray()); if (!overlap) { const Element *p2 = mt->GetMatrixArray(); const Int_t ncols1 = this->fMatrix->GetNcols(); const Int_t ncols2 = mt->GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off1 = (irow+this->fRowOff)*ncols1+this->fColOff; const Int_t off2 = (irow+rowOff2)*ncols2+colOff2; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) p1[off1+icol] = p2[off2+icol]; } } else { const Int_t row_lwbs = rowOff2+mt->GetRowLwb(); const Int_t row_upbs = row_lwbs+this->fNrowsSub-1; const Int_t col_lwbs = colOff2+mt->GetColLwb(); const Int_t col_upbs = col_lwbs+this->fNcolsSub-1; TMatrixT tmp; mt->GetSub(row_lwbs,row_upbs,col_lwbs,col_upbs,tmp); const Element *p2 = tmp.GetMatrixArray(); const Int_t ncols1 = this->fMatrix->GetNcols(); const Int_t ncols2 = tmp.GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off1 = (irow+this->fRowOff)*ncols1+this->fColOff; const Int_t off2 = irow*ncols2; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) p1[off1+icol] = p2[off2+icol]; } } } //////////////////////////////////////////////////////////////////////////////// /// Assignment operator template void TMatrixTSub::operator=(const TMatrixTBase &m) { R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(m.IsValid()); if (this->fMatrix->GetMatrixArray() == m.GetMatrixArray()) return; if (this->fNrowsSub != m.GetNrows() || this->fNcolsSub != m.GetNcols()) { Error("operator=(const TMatrixTBase &)","sub matrices and matrix have different size"); return; } const Int_t row_lwbs = this->fRowOff+this->fMatrix->GetRowLwb(); const Int_t col_lwbs = this->fColOff+this->fMatrix->GetColLwb(); (const_cast *>(this->fMatrix))->SetSub(row_lwbs,col_lwbs,m); } //////////////////////////////////////////////////////////////////////////////// /// Add to every element of the submatrix the corresponding element of submatrix ms. template void TMatrixTSub::operator+=(const TMatrixTSub_const &ms) { const TMatrixTBase *mt = ms.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->GetNrows() != ms.GetNrows() || this->GetNcols() != ms.GetNcols()) { Error("operator+=(const TMatrixTSub_const &)","sub matrices have different size"); return; } const Int_t rowOff2 = ms.GetRowOff(); const Int_t colOff2 = ms.GetColOff(); Bool_t overlap = (this->fMatrix == mt) && ( (rowOff2 >= this->fRowOff && rowOff2 < this->fRowOff+this->fNrowsSub) || (colOff2 >= this->fColOff && colOff2 < this->fColOff+this->fNcolsSub) ); Element *p1 = const_cast(this->fMatrix->GetMatrixArray()); if (!overlap) { const Element *p2 = mt->GetMatrixArray(); const Int_t ncols1 = this->fMatrix->GetNcols(); const Int_t ncols2 = mt->GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off1 = (irow+this->fRowOff)*ncols1+this->fColOff; const Int_t off2 = (irow+rowOff2)*ncols2+colOff2; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) p1[off1+icol] += p2[off2+icol]; } } else { const Int_t row_lwbs = rowOff2+mt->GetRowLwb(); const Int_t row_upbs = row_lwbs+this->fNrowsSub-1; const Int_t col_lwbs = colOff2+mt->GetColLwb(); const Int_t col_upbs = col_lwbs+this->fNcolsSub-1; TMatrixT tmp; mt->GetSub(row_lwbs,row_upbs,col_lwbs,col_upbs,tmp); const Element *p2 = tmp.GetMatrixArray(); const Int_t ncols1 = this->fMatrix->GetNcols(); const Int_t ncols2 = tmp.GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off1 = (irow+this->fRowOff)*ncols1+this->fColOff; const Int_t off2 = irow*ncols2; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) p1[off1+icol] += p2[off2+icol]; } } } //////////////////////////////////////////////////////////////////////////////// /// Multiply submatrix with submatrix ms. template void TMatrixTSub::operator*=(const TMatrixTSub_const &ms) { if (this->fNcolsSub != ms.GetNrows() || this->fNcolsSub != ms.GetNcols()) { Error("operator*=(const TMatrixTSub_const &)","source sub matrix has wrong shape"); return; } const TMatrixTBase *source = ms.GetMatrix(); TMatrixT source_sub; { const Int_t row_lwbs = ms.GetRowOff()+source->GetRowLwb(); const Int_t row_upbs = row_lwbs+this->fNrowsSub-1; const Int_t col_lwbs = ms.GetColOff()+source->GetColLwb(); const Int_t col_upbs = col_lwbs+this->fNcolsSub-1; source->GetSub(row_lwbs,row_upbs,col_lwbs,col_upbs,source_sub); } const Element *sp = source_sub.GetMatrixArray(); const Int_t ncols = this->fMatrix->GetNcols(); // One row of the old_target matrix Element work[kWorkMax]; Bool_t isAllocated = kFALSE; Element *trp = work; if (this->fNcolsSub > kWorkMax) { isAllocated = kTRUE; trp = new Element[this->fNcolsSub]; } Element *cp = const_cast(this->fMatrix->GetMatrixArray())+this->fRowOff*ncols+this->fColOff; const Element *trp0 = cp; // Pointer to target[i,0]; const Element * const trp0_last = trp0+this->fNrowsSub*ncols; while (trp0 < trp0_last) { memcpy(trp,trp0,this->fNcolsSub*sizeof(Element)); // copy the i-th row of target, Start at target[i,0] for (const Element *scp = sp; scp < sp+this->fNcolsSub; ) { // Pointer to the j-th column of source, // Start scp = source[0,0] Element cij = 0; for (Int_t j = 0; j < this->fNcolsSub; j++) { cij += trp[j] * *scp; // the j-th col of source scp += this->fNcolsSub; } *cp++ = cij; scp -= source_sub.GetNoElements()-1; // Set bcp to the (j+1)-th col } cp += ncols-this->fNcolsSub; trp0 += ncols; // Set trp0 to the (i+1)-th row R__ASSERT(trp0 == cp); } R__ASSERT(cp == trp0_last && trp0 == trp0_last); if (isAllocated) delete [] trp; } //////////////////////////////////////////////////////////////////////////////// /// Add to every element of the submatrix the corresponding element of matrix mt. template void TMatrixTSub::operator+=(const TMatrixTBase &mt) { R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt.IsValid()); if (this->GetNrows() != mt.GetNrows() || this->GetNcols() != mt.GetNcols()) { Error("operator+=(const TMatrixTBase &)","sub matrix and matrix have different size"); return; } Element *p1 = const_cast(this->fMatrix->GetMatrixArray()); const Element *p2 = mt.GetMatrixArray(); const Int_t ncols1 = this->fMatrix->GetNcols(); const Int_t ncols2 = mt.GetNcols(); for (Int_t irow = 0; irow < this->fNrowsSub; irow++) { const Int_t off1 = (irow+this->fRowOff)*ncols1+this->fColOff; const Int_t off2 = irow*ncols2; for (Int_t icol = 0; icol < this->fNcolsSub; icol++) p1[off1+icol] += p2[off2+icol]; } } //////////////////////////////////////////////////////////////////////////////// /// Multiply submatrix with matrix source. template void TMatrixTSub::operator*=(const TMatrixT &source) { if (this->fNcolsSub != source.GetNrows() || this->fNcolsSub != source.GetNcols()) { Error("operator*=(const TMatrixT &)","source matrix has wrong shape"); return; } // Check for A *= A; const Element *sp; TMatrixT tmp; if (this->fMatrix->GetMatrixArray() == source.GetMatrixArray()) { tmp.ResizeTo(source); tmp = source; sp = tmp.GetMatrixArray(); } else sp = source.GetMatrixArray(); const Int_t ncols = this->fMatrix->GetNcols(); // One row of the old_target matrix Element work[kWorkMax]; Bool_t isAllocated = kFALSE; Element *trp = work; if (this->fNcolsSub > kWorkMax) { isAllocated = kTRUE; trp = new Element[this->fNcolsSub]; } Element *cp = const_cast(this->fMatrix->GetMatrixArray())+this->fRowOff*ncols+this->fColOff; const Element *trp0 = cp; // Pointer to target[i,0]; const Element * const trp0_last = trp0+this->fNrowsSub*ncols; while (trp0 < trp0_last) { memcpy(trp,trp0,this->fNcolsSub*sizeof(Element)); // copy the i-th row of target, Start at target[i,0] for (const Element *scp = sp; scp < sp+this->fNcolsSub; ) { // Pointer to the j-th column of source, // Start scp = source[0,0] Element cij = 0; for (Int_t j = 0; j < this->fNcolsSub; j++) { cij += trp[j] * *scp; // the j-th col of source scp += this->fNcolsSub; } *cp++ = cij; scp -= source.GetNoElements()-1; // Set bcp to the (j+1)-th col } cp += ncols-this->fNcolsSub; trp0 += ncols; // Set trp0 to the (i+1)-th row R__ASSERT(trp0 == cp); } R__ASSERT(cp == trp0_last && trp0 == trp0_last); if (isAllocated) delete [] trp; } //////////////////////////////////////////////////////////////////////////////// /// Multiply submatrix with matrix source. template void TMatrixTSub::operator*=(const TMatrixTSym &source) { if (this->fNcolsSub != source.GetNrows() || this->fNcolsSub != source.GetNcols()) { Error("operator*=(const TMatrixTSym &)","source matrix has wrong shape"); return; } // Check for A *= A; const Element *sp; TMatrixTSym tmp; if (this->fMatrix->GetMatrixArray() == source.GetMatrixArray()) { tmp.ResizeTo(source); tmp = source; sp = tmp.GetMatrixArray(); } else sp = source.GetMatrixArray(); const Int_t ncols = this->fMatrix->GetNcols(); // One row of the old_target matrix Element work[kWorkMax]; Bool_t isAllocated = kFALSE; Element *trp = work; if (this->fNcolsSub > kWorkMax) { isAllocated = kTRUE; trp = new Element[this->fNcolsSub]; } Element *cp = const_cast(this->fMatrix->GetMatrixArray())+this->fRowOff*ncols+this->fColOff; const Element *trp0 = cp; // Pointer to target[i,0]; const Element * const trp0_last = trp0+this->fNrowsSub*ncols; while (trp0 < trp0_last) { memcpy(trp,trp0,this->fNcolsSub*sizeof(Element)); // copy the i-th row of target, Start at target[i,0] for (const Element *scp = sp; scp < sp+this->fNcolsSub; ) { // Pointer to the j-th column of source, // Start scp = source[0,0] Element cij = 0; for (Int_t j = 0; j < this->fNcolsSub; j++) { cij += trp[j] * *scp; // the j-th col of source scp += this->fNcolsSub; } *cp++ = cij; scp -= source.GetNoElements()-1; // Set bcp to the (j+1)-th col } cp += ncols-this->fNcolsSub; trp0 += ncols; // Set trp0 to the (i+1)-th row R__ASSERT(trp0 == cp); } R__ASSERT(cp == trp0_last && trp0 == trp0_last); if (isAllocated) delete [] trp; } //////////////////////////////////////////////////////////////////////////////// /// Constructor with row "row" of matrix template TMatrixTSparseRow_const::TMatrixTSparseRow_const(const TMatrixTSparse &matrix,Int_t row) { R__ASSERT(matrix.IsValid()); fRowInd = row-matrix.GetRowLwb(); if (fRowInd >= matrix.GetNrows() || fRowInd < 0) { Error("TMatrixTSparseRow_const(const TMatrixTSparse &,Int_t)","row index out of bounds"); fMatrix = nullptr; fNindex = 0; fColPtr = nullptr; fDataPtr = nullptr; return; } const Int_t sIndex = matrix.GetRowIndexArray()[fRowInd]; const Int_t eIndex = matrix.GetRowIndexArray()[fRowInd+1]; fMatrix = &matrix; fNindex = eIndex-sIndex; fColPtr = matrix.GetColIndexArray()+sIndex; fDataPtr = matrix.GetMatrixArray()+sIndex; } //////////////////////////////////////////////////////////////////////////////// template Element TMatrixTSparseRow_const::operator()(Int_t i) const { if (!fMatrix) return TMatrixTBase::NaNValue(); R__ASSERT(fMatrix->IsValid()); const Int_t acoln = i-fMatrix->GetColLwb(); if (acoln < fMatrix->GetNcols() && acoln >= 0) { const Int_t index = TMath::BinarySearch(fNindex,fColPtr,acoln); if (index >= 0 && fColPtr[index] == acoln) return fDataPtr[index]; else return 0.0; } else { Error("operator()","Request col(%d) outside matrix range of %d - %d", i,fMatrix->GetColLwb(),fMatrix->GetColLwb()+fMatrix->GetNcols()); return TMatrixTBase::NaNValue(); } } //////////////////////////////////////////////////////////////////////////////// /// Constructor with row "row" of matrix template TMatrixTSparseRow::TMatrixTSparseRow(TMatrixTSparse &matrix,Int_t row) : TMatrixTSparseRow_const(matrix,row) { } //////////////////////////////////////////////////////////////////////////////// /// Copy constructor template TMatrixTSparseRow::TMatrixTSparseRow(const TMatrixTSparseRow &mr) : TMatrixTSparseRow_const(mr) { *this = mr; } //////////////////////////////////////////////////////////////////////////////// template Element TMatrixTSparseRow::operator()(Int_t i) const { if (!this->fMatrix) return TMatrixTBase::NaNValue(); R__ASSERT(this->fMatrix->IsValid()); const Int_t acoln = i-this->fMatrix->GetColLwb(); if (acoln < this->fMatrix->GetNcols() && acoln >= 0) { const Int_t index = TMath::BinarySearch(this->fNindex,this->fColPtr,acoln); if (index >= 0 && this->fColPtr[index] == acoln) return this->fDataPtr[index]; else return 0.0; } else { Error("operator()","Request col(%d) outside matrix range of %d - %d", i,this->fMatrix->GetColLwb(),this->fMatrix->GetColLwb()+this->fMatrix->GetNcols()); return TMatrixTBase::NaNValue(); } } //////////////////////////////////////////////////////////////////////////////// /// operator() : pick element row(i) template Element &TMatrixTSparseRow::operator()(Int_t i) { if (!this->fMatrix) return TMatrixTBase::NaNValue(); R__ASSERT(this->fMatrix->IsValid()); const Int_t acoln = i-this->fMatrix->GetColLwb(); if (acoln >= this->fMatrix->GetNcols() || acoln < 0) { Error("operator()(Int_t","Requested element %d outside range : %d - %d",i, this->fMatrix->GetColLwb(),this->fMatrix->GetColLwb()+this->fMatrix->GetNcols()); return TMatrixTBase::NaNValue(); } Int_t index = TMath::BinarySearch(this->fNindex,this->fColPtr,acoln); if (index >= 0 && this->fColPtr[index] == acoln) return (const_cast(this->fDataPtr))[index]; else { TMatrixTSparse *mt = const_cast *>(this->fMatrix); const Int_t row = this->fRowInd+mt->GetRowLwb(); Element val = 0.; mt->InsertRow(row,i,&val,1); const Int_t sIndex = mt->GetRowIndexArray()[this->fRowInd]; const Int_t eIndex = mt->GetRowIndexArray()[this->fRowInd+1]; this->fNindex = eIndex-sIndex; this->fColPtr = mt->GetColIndexArray()+sIndex; this->fDataPtr = mt->GetMatrixArray()+sIndex; index = TMath::BinarySearch(this->fNindex,this->fColPtr,acoln); if (index >= 0 && this->fColPtr[index] == acoln) return (const_cast(this->fDataPtr))[index]; else { Error("operator()(Int_t","Insert row failed"); return TMatrixTBase::NaNValue(); } } } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every non-zero (!) element of the matrix row. template void TMatrixTSparseRow::operator=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *rp = const_cast(this->fDataPtr); for ( ; rp < this->fDataPtr+this->fNindex; rp++) *rp = val; } //////////////////////////////////////////////////////////////////////////////// /// Add val to every non-zero (!) element of the matrix row. template void TMatrixTSparseRow::operator+=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *rp = const_cast(this->fDataPtr); for ( ; rp < this->fDataPtr+this->fNindex; rp++) *rp += val; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix row by val. template void TMatrixTSparseRow::operator*=(Element val) { R__ASSERT(this->fMatrix->IsValid()); Element *rp = const_cast(this->fDataPtr); for ( ; rp < this->fDataPtr+this->fNindex; rp++) *rp *= val; } //////////////////////////////////////////////////////////////////////////////// /// Assignment operator template void TMatrixTSparseRow::operator=(const TMatrixTSparseRow_const &mr) { const TMatrixTBase *mt = mr.GetMatrix(); if (this->fMatrix == mt) return; R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetColLwb() != mt->GetColLwb() || this->fMatrix->GetNcols() != mt->GetNcols()) { Error("operator=(const TMatrixTSparseRow_const &)","matrix rows not compatible"); return; } const Int_t ncols = this->fMatrix->GetNcols(); const Int_t row1 = this->fRowInd+this->fMatrix->GetRowLwb(); const Int_t row2 = mr.GetRowIndex()+mt->GetRowLwb(); const Int_t col = this->fMatrix->GetColLwb(); TVectorT v(ncols); mt->ExtractRow(row2,col,v.GetMatrixArray()); const_cast *>(this->fMatrix)->InsertRow(row1,col,v.GetMatrixArray()); const Int_t sIndex = this->fMatrix->GetRowIndexArray()[this->fRowInd]; const Int_t eIndex = this->fMatrix->GetRowIndexArray()[this->fRowInd+1]; this->fNindex = eIndex-sIndex; this->fColPtr = this->fMatrix->GetColIndexArray()+sIndex; this->fDataPtr = this->fMatrix->GetMatrixArray()+sIndex; } //////////////////////////////////////////////////////////////////////////////// /// Assign a vector to a matrix row. The vector is considered row-vector /// to allow the assignment in the strict sense. template void TMatrixTSparseRow::operator=(const TVectorT &vec) { R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(vec.IsValid()); if (this->fMatrix->GetColLwb() != vec.GetLwb() || this->fMatrix->GetNcols() != vec.GetNrows()) { Error("operator=(const TVectorT &)","vector length != matrix-row length"); return; } const Element *vp = vec.GetMatrixArray(); const Int_t row = this->fRowInd+this->fMatrix->GetRowLwb(); const Int_t col = this->fMatrix->GetColLwb(); const_cast *>(this->fMatrix)->InsertRow(row,col,vp,vec.GetNrows()); const Int_t sIndex = this->fMatrix->GetRowIndexArray()[this->fRowInd]; const Int_t eIndex = this->fMatrix->GetRowIndexArray()[this->fRowInd+1]; this->fNindex = eIndex-sIndex; this->fColPtr = this->fMatrix->GetColIndexArray()+sIndex; this->fDataPtr = this->fMatrix->GetMatrixArray()+sIndex; } //////////////////////////////////////////////////////////////////////////////// /// Add to every element of the matrix row the corresponding element of row r. template void TMatrixTSparseRow::operator+=(const TMatrixTSparseRow_const &r) { const TMatrixTBase *mt = r.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetColLwb() != mt->GetColLwb() || this->fMatrix->GetNcols() != mt->GetNcols()) { Error("operator+=(const TMatrixTRow_const &)","different row lengths"); return; } const Int_t ncols = this->fMatrix->GetNcols(); const Int_t row1 = this->fRowInd+this->fMatrix->GetRowLwb(); const Int_t row2 = r.GetRowIndex()+mt->GetRowLwb(); const Int_t col = this->fMatrix->GetColLwb(); TVectorT v1(ncols); TVectorT v2(ncols); this->fMatrix->ExtractRow(row1,col,v1.GetMatrixArray()); mt ->ExtractRow(row2,col,v2.GetMatrixArray()); v1 += v2; const_cast *>(this->fMatrix)->InsertRow(row1,col,v1.GetMatrixArray()); const Int_t sIndex = this->fMatrix->GetRowIndexArray()[this->fRowInd]; const Int_t eIndex = this->fMatrix->GetRowIndexArray()[this->fRowInd+1]; this->fNindex = eIndex-sIndex; this->fColPtr = this->fMatrix->GetColIndexArray()+sIndex; this->fDataPtr = this->fMatrix->GetMatrixArray()+sIndex; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix row with the /// corresponding element of row r. template void TMatrixTSparseRow::operator*=(const TMatrixTSparseRow_const &r) { const TMatrixTBase *mt = r.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fMatrix->GetColLwb() != mt->GetColLwb() || this->fMatrix->GetNcols() != mt->GetNcols()) { Error("operator+=(const TMatrixTRow_const &)","different row lengths"); return; } const Int_t ncols = this->fMatrix->GetNcols(); const Int_t row1 = r.GetRowIndex()+mt->GetRowLwb(); const Int_t row2 = r.GetRowIndex()+mt->GetRowLwb(); const Int_t col = this->fMatrix->GetColLwb(); TVectorT v1(ncols); TVectorT v2(ncols); this->fMatrix->ExtractRow(row1,col,v1.GetMatrixArray()); mt ->ExtractRow(row2,col,v2.GetMatrixArray()); ElementMult(v1,v2); const_cast *>(this->fMatrix)->InsertRow(row1,col,v1.GetMatrixArray()); const Int_t sIndex = this->fMatrix->GetRowIndexArray()[this->fRowInd]; const Int_t eIndex = this->fMatrix->GetRowIndexArray()[this->fRowInd+1]; this->fNindex = eIndex-sIndex; this->fColPtr = this->fMatrix->GetColIndexArray()+sIndex; this->fDataPtr = this->fMatrix->GetMatrixArray()+sIndex; } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTSparseDiag_const::TMatrixTSparseDiag_const(const TMatrixTSparse &matrix) { R__ASSERT(matrix.IsValid()); fMatrix = &matrix; fNdiag = TMath::Min(matrix.GetNrows(),matrix.GetNcols()); fDataPtr = matrix.GetMatrixArray(); } //////////////////////////////////////////////////////////////////////////////// template Element TMatrixTSparseDiag_const::operator()(Int_t i) const { R__ASSERT(fMatrix->IsValid()); if (i < fNdiag && i >= 0) { const Int_t * const pR = fMatrix->GetRowIndexArray(); const Int_t * const pC = fMatrix->GetColIndexArray(); const Element * const pD = fMatrix->GetMatrixArray(); const Int_t sIndex = pR[i]; const Int_t eIndex = pR[i+1]; const Int_t index = TMath::BinarySearch(eIndex-sIndex,pC+sIndex,i)+sIndex; if (index >= sIndex && pC[index] == i) return pD[index]; else return 0.0; } else { Error("operator()","Request diagonal(%d) outside matrix range of 0 - %d",i,fNdiag); return 0.0; } return 0.0; } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTSparseDiag::TMatrixTSparseDiag(TMatrixTSparse &matrix) :TMatrixTSparseDiag_const(matrix) { } //////////////////////////////////////////////////////////////////////////////// /// Constructor template TMatrixTSparseDiag::TMatrixTSparseDiag(const TMatrixTSparseDiag &md) : TMatrixTSparseDiag_const(md) { *this = md; } //////////////////////////////////////////////////////////////////////////////// template Element TMatrixTSparseDiag::operator()(Int_t i) const { R__ASSERT(this->fMatrix->IsValid()); if (i < this->fNdiag && i >= 0) { const Int_t * const pR = this->fMatrix->GetRowIndexArray(); const Int_t * const pC = this->fMatrix->GetColIndexArray(); const Element * const pD = this->fMatrix->GetMatrixArray(); const Int_t sIndex = pR[i]; const Int_t eIndex = pR[i+1]; const Int_t index = TMath::BinarySearch(eIndex-sIndex,pC+sIndex,i)+sIndex; if (index >= sIndex && pC[index] == i) return pD[index]; else return 0.0; } else { Error("operator()","Request diagonal(%d) outside matrix range of 0 - %d",i,this->fNdiag); return 0.0; } return 0.0; } //////////////////////////////////////////////////////////////////////////////// /// operator() : pick element diag(i) template Element &TMatrixTSparseDiag::operator()(Int_t i) { R__ASSERT(this->fMatrix->IsValid()); if (i < 0 || i >= this->fNdiag) { Error("operator()(Int_t","Requested element %d outside range : 0 - %d",i,this->fNdiag); return (const_cast(this->fDataPtr))[0]; } TMatrixTSparse *mt = const_cast *>(this->fMatrix); const Int_t *pR = mt->GetRowIndexArray(); const Int_t *pC = mt->GetColIndexArray(); Int_t sIndex = pR[i]; Int_t eIndex = pR[i+1]; Int_t index = TMath::BinarySearch(eIndex-sIndex,pC+sIndex,i)+sIndex; if (index >= sIndex && pC[index] == i) return (const_cast(this->fDataPtr))[index]; else { const Int_t row = i+mt->GetRowLwb(); const Int_t col = i+mt->GetColLwb(); Element val = 0.; mt->InsertRow(row,col,&val,1); this->fDataPtr = mt->GetMatrixArray(); pR = mt->GetRowIndexArray(); pC = mt->GetColIndexArray(); sIndex = pR[i]; eIndex = pR[i+1]; index = TMath::BinarySearch(eIndex-sIndex,pC+sIndex,i)+sIndex; if (index >= sIndex && pC[index] == i) return (const_cast(this->fDataPtr))[index]; else { Error("operator()(Int_t","Insert row failed"); return (const_cast(this->fDataPtr))[0]; } } } //////////////////////////////////////////////////////////////////////////////// /// Assign val to every element of the matrix diagonal. template void TMatrixTSparseDiag::operator=(Element val) { R__ASSERT(this->fMatrix->IsValid()); for (Int_t i = 0; i < this->fNdiag; i++) (*this)(i) = val; } //////////////////////////////////////////////////////////////////////////////// /// Add val to every element of the matrix diagonal. template void TMatrixTSparseDiag::operator+=(Element val) { R__ASSERT(this->fMatrix->IsValid()); for (Int_t i = 0; i < this->fNdiag; i++) (*this)(i) += val; } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix diagonal by val. template void TMatrixTSparseDiag::operator*=(Element val) { R__ASSERT(this->fMatrix->IsValid()); for (Int_t i = 0; i < this->fNdiag; i++) (*this)(i) *= val; } //////////////////////////////////////////////////////////////////////////////// /// Assignment operator template void TMatrixTSparseDiag::operator=(const TMatrixTSparseDiag_const &md) { const TMatrixTBase *mt = md.GetMatrix(); if (this->fMatrix == mt) return; R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fNdiag != md.GetNdiags()) { Error("operator=(const TMatrixTSparseDiag_const &)","matrix-diagonal's different length"); return; } for (Int_t i = 0; i < this->fNdiag; i++) (*this)(i) = md(i); } //////////////////////////////////////////////////////////////////////////////// /// Assign a vector to the matrix diagonal. template void TMatrixTSparseDiag::operator=(const TVectorT &vec) { R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(vec.IsValid()); if (this->fNdiag != vec.GetNrows()) { Error("operator=(const TVectorT &)","vector length != matrix-diagonal length"); return; } const Element *vp = vec.GetMatrixArray(); for (Int_t i = 0; i < this->fNdiag; i++) (*this)(i) = vp[i]; } //////////////////////////////////////////////////////////////////////////////// /// Add to every element of the matrix diagonal the /// corresponding element of diagonal md. template void TMatrixTSparseDiag::operator+=(const TMatrixTSparseDiag_const &md) { const TMatrixTBase *mt = md.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fNdiag != md.GetNdiags()) { Error("operator+=(const TMatrixTSparseDiag_const &)","matrix-diagonal's different length"); return; } for (Int_t i = 0; i < this->fNdiag; i++) (*this)(i) += md(i); } //////////////////////////////////////////////////////////////////////////////// /// Multiply every element of the matrix diagonal with the /// corresponding element of diagonal md. template void TMatrixTSparseDiag::operator*=(const TMatrixTSparseDiag_const &md) { const TMatrixTBase *mt = md.GetMatrix(); R__ASSERT(this->fMatrix->IsValid()); R__ASSERT(mt->IsValid()); if (this->fNdiag != md.GetNdiags()) { Error("operator*=(const TMatrixTSparseDiag_const &)","matrix-diagonal's different length"); return; } for (Int_t i = 0; i < this->fNdiag; i++) (*this)(i) *= md(i); } //////////////////////////////////////////////////////////////////////////////// /// Random number generator [0....1] with seed ix Double_t Drand(Double_t &ix) { const Double_t a = 16807.0; const Double_t b15 = 32768.0; const Double_t b16 = 65536.0; const Double_t p = 2147483647.0; Double_t xhi = ix/b16; Int_t xhiint = (Int_t) xhi; xhi = xhiint; Double_t xalo = (ix-xhi*b16)*a; Double_t leftlo = xalo/b16; Int_t leftloint = (int) leftlo; leftlo = leftloint; Double_t fhi = xhi*a+leftlo; Double_t k = fhi/b15; Int_t kint = (Int_t) k; k = kint; ix = (((xalo-leftlo*b16)-p)+(fhi-k*b15)*b16)+k; if (ix < 0.0) ix = ix+p; return (ix*4.656612875e-10); } template class TMatrixTRow_const ; template class TMatrixTColumn_const ; template class TMatrixTDiag_const ; template class TMatrixTFlat_const ; template class TMatrixTSub_const ; template class TMatrixTSparseRow_const ; template class TMatrixTSparseDiag_const; template class TMatrixTRow ; template class TMatrixTColumn ; template class TMatrixTDiag ; template class TMatrixTFlat ; template class TMatrixTSub ; template class TMatrixTSparseRow ; template class TMatrixTSparseDiag ; template class TElementActionT ; template class TElementPosActionT ; template class TMatrixTRow_const ; template class TMatrixTColumn_const ; template class TMatrixTDiag_const ; template class TMatrixTFlat_const ; template class TMatrixTSub_const ; template class TMatrixTSparseRow_const ; template class TMatrixTSparseDiag_const; template class TMatrixTRow ; template class TMatrixTColumn ; template class TMatrixTDiag ; template class TMatrixTFlat ; template class TMatrixTSub ; template class TMatrixTSparseRow ; template class TMatrixTSparseDiag ; template class TElementActionT ; template class TElementPosActionT ;