/* Copyright (C) 2001 R. Balasubramanian (Sort by S. Babak) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /****************** CVS info ************************ #define CVSTAG "$Name: $" #define CVSHEADER "$Header: /afs/.aei-potsdam.mpg.de/u/stba/cvs/LISA/LISAWP/base/src/Matrix.cc,v 1.5 2006/05/17 11:03:03 stba Exp $" */ #include "Matrix.hh" #include namespace LISAWP{ template Matrix::Matrix():std::vector(0) { const_origin = origin = 0; rows=cols=subR=subC=0; offset=0; stride = 0; offsetP=0; } template Matrix::Matrix(const unsigned c):std::vector(c) { LISAWPAssert(c,"The number of elemenets must be non zero for constructor"); unsigned r=1; const_origin = origin = &((*this)[0]); offset=offsetP=0; rows=subR=r; cols=subC=c; stride = c; } template Matrix::Matrix(const unsigned r, const unsigned c):std::vector(r*c) { LISAWPAssert(r*c,"There product of number of rows and columns must be non zero"); const_origin = origin = &((*this)[0]); offset=offsetP=0; rows=subR=r; cols=subC=c; stride = c; } template Matrix::Matrix(const Matrix &mat, unsigned nr, unsigned nc, unsigned orX, unsigned orY) { LISAWPAssert( ((orX+nr) <= mat.subR) && ((orY+nc) <= mat.subC), "Submatrix size inconsistent with parent Matrix"); rows = mat.subR; cols = mat.subC; stride = mat.stride; offsetP = mat.offset; offset = offsetP + orX*stride + orY; subR = nr; subC = nc; const_origin = mat.const_origin + orX*stride + orY;; origin=0; } template Matrix::Matrix(Matrix &mat, unsigned nr, unsigned nc, unsigned orX, unsigned orY) { LISAWPAssert(mat.Size() > 0, " you cant attach to a zero size Matrix "); LISAWPAssert( ((orX+nr) <= mat.subR) && ((orY+nc) <= mat.subC), "Submatrix size inconsistent with parent Matrix"); rows = mat.subR; cols = mat.subC; offsetP = mat.offset; stride = mat.stride; offset = offsetP + orX*stride + orY; subR = nr; subC = nc; if(mat.origin){ origin = mat.origin + orX*stride + orY; const_origin=origin; } else{ const_origin = mat.const_origin + orX*stride + orY; origin=0; } } template Matrix::Matrix(const Matrix &mat):std::vector(mat) { rows = mat.rows; cols = mat.cols; stride=mat.stride; offset=mat.offset; offsetP=mat.offsetP; subR=mat.subR; subC=mat.subC; if(mat.IsSubMatrix()==true){ origin = mat.origin; const_origin = mat.const_origin; } else{ origin = &((*this)[0]); const_origin=origin; } } template void Matrix::ExpandEmpty( const unsigned r, const unsigned c) { LISAWPAssert((rows==0)&&(cols==0), " Matrix has to be zero size before it can be expanded"); LISAWPAssert(r*c,"The rows and columns of the matrix to be expanded cant be zero"); offset=offsetP=0; this->resize(r*c); origin=&((*this)[0]); const_origin=origin; rows=subR=r; cols=subC=c; stride = c; } template void Matrix::ExpandEmpty(const unsigned c) { unsigned r = 1; LISAWPAssert((rows==0)&&(cols==0), " Matrix has to be zero size before it can be expanded"); offset=offsetP=0; this->resize(r*c); origin=&((*this)[0]); const_origin=origin; rows=subR=r; cols=subC=c; stride = c; } template void Matrix::MakeEmpty() { this->resize(0); rows=subR=0; cols=subC=0; offset=0; offsetP=0; stride = 0; const_origin = origin=0; } template bool Matrix::ShiftCValid(const int c){ LISAWPAssert(IsSubMatrix()==true,"You can only shift submatrices"); unsigned myC = offset % stride; unsigned pC = offsetP % stride; int cc1 = c + myC + subC; int cc2 = myC+c; if( (cc1>(int)(pC+cols)) ||(cc2 < (int) pC)) return false; else{ offset += c; const_origin +=c; if(origin) origin += c; return true; } } template bool Matrix::ShiftRValid(const int r){ LISAWPAssert(IsSubMatrix()==true,"You can only shift submatrices"); unsigned myR = offset/stride; unsigned pR = offsetP/stride; int rr1 = r + myR + subR; int rr2 = r + myR; int tmp = rows+pR; int tmp2 = pR; if( (rr1>tmp) || (rr2 < tmp2) ) return false; else{ offset += r*stride; const_origin += r*stride; if(origin) origin += r*stride; return true; } } template void Matrix::Attach(Matrix &mat, unsigned nR, unsigned nC, unsigned oX, unsigned oY) { LISAWPAssert(this!=&mat,"You cant attach a matrix to itself"); LISAWPAssert( ((oX+nR) <= mat.subR) && ((oY+nC) <= mat.subC), "Incorrect attachment of matrix"); LISAWPAssert((rows==0)&&(cols==0), "You can attach only a empty matrix"); LISAWPAssert(mat.Size()>0, " You cant attach to a zero size Matrix "); rows = mat.subR; cols = mat.subC; stride = mat.stride; offsetP = mat.offset; offset = offsetP + oX*stride + oY; subR = nR; subC = nC; if (mat.origin){ origin = mat.origin + oX*stride + oY; const_origin=origin; } else{ const_origin = mat.const_origin + oX*stride + oY; origin=0; } } template void Matrix::Attach(const Matrix &mat, unsigned nR, unsigned nC, unsigned oX, unsigned oY) { LISAWPAssert(this!=&mat,"You cant attach a matrix to itself"); LISAWPAssert( ((oX+nR) <= mat.subR) && ((oY+nC) <= mat.subC), "Incorrect attachment of matrix"); LISAWPAssert((rows==0)&&(cols==0), "You can attach only a empty matrix"); LISAWPAssert(mat.Size()>0, " You cant attach to a zero size Matrix "); rows = mat.subR; cols = mat.subC; stride = mat.stride; offsetP = mat.offset; offset = offsetP + oX*stride + oY; subR = nR; subC = nC; const_origin=mat.const_origin +oX*stride + oY; origin = 0; } template void Matrix::ReAttach(const Matrix &mat, unsigned oX, unsigned oY) { LISAWPAssert(IsSubMatrix() == true, " you can reattach only submatrices"); unsigned nRows = GetNRows(); unsigned nCols = GetNCols(); MakeEmpty(); Attach(mat, nRows, nCols, oX, oY); } template void Matrix::ReAttach(Matrix &mat, unsigned oX, unsigned oY) { LISAWPAssert(IsSubMatrix() == true, " you can reattach only submatrices"); unsigned nRows = GetNRows(); unsigned nCols = GetNCols(); MakeEmpty(); Attach(mat, nRows, nCols, oX, oY); } template Matrix& Matrix::operator=(const Matrix &mat2) { { if(IsSubMatrix() == false){ if((subR!=mat2.GetNRows())||(subC!=mat2.GetNCols())){ MakeEmpty(); ExpandEmpty(mat2.GetNRows(),mat2.GetNCols()); } } LISAWPAssert((subR==mat2.GetNRows())&&(subC==mat2.GetNCols()) , "Matrix Sizes dont match"); LISAWPAssert(origin, "Write operation attempted on read only submatrix"); for(unsigned i=0;i Matrix & Matrix::operator=(const T &var) { LISAWPAssert(origin, "Write attempt to read only Matrix"); for(unsigned i=0; i Matrix Matrix::operator+(const Matrix &mat) const { LISAWPAssert((subR==mat.subR)&&(subC==mat.subC)," Matrix sizes must be consistent for addition"); Matrix out(subR,subC); for(unsigned i=0; i Matrix & Matrix::operator+=(const Matrix &mat) { LISAWPAssert(origin, "Write attempt to read only Matrix"); LISAWPAssert((subR==mat.subR)&&(subC==mat.subC)," Matrix sizes must be consistent for addition"); for(unsigned i=0; i Matrix Matrix::operator-(const Matrix &mat) const { LISAWPAssert((subR==mat.subR)&&(subC==mat.subC)," Matrix sizes must be consistent for addition"); Matrix out(subR,subC); for(unsigned i=0; i Matrix & Matrix::operator-=(const Matrix &mat) { LISAWPAssert(origin, "Write attempt to read only Matrix"); LISAWPAssert((subR==mat.subR)&&(subC==mat.subC)," Matrix sizes must be consistent for addition"); for(unsigned i=0; i Matrix Matrix::operator*(const T &var) const { Matrix out(subR,subC); for(unsigned i=0; i Matrix & Matrix::operator*=(const T &var) { LISAWPAssert(origin, "Write attempt to read only Matrix"); for(unsigned i=0; i Matrix Matrix::operator*(const Matrix &mat) const { LISAWPAssert((subC==mat.subR),"Matrices sizes must be consistent for multiplication"); Matrix out(subR,mat.subC); out.Multiply(*this, mat); return out; } /*void Matrix::Multiply(const Matrix &m1, const Matrix &m2) { unsigned i,j,k; const double *a1,*a2; double *o; LISAWPAssert(m1.subC==m2.subR, "Matrix Sizes must be consistent for multiplication"); LISAWPAssert((subR==m1.subR)&&(subC==m2.subC), "The product matrix is not of right size"); for(i=0;i void Matrix::Multiply(const Matrix &m1, const Matrix &m2) { Matrix out(subR,subC); unsigned i,j,k; const_iterator a1,a2; double *o; LISAWPAssert(m1.subC==m2.subR, "Matrix Sizes must be consistent for multiplication"); LISAWPAssert((subR==m1.subR)&&(subC==m2.subC), "The product matrix is not of right size"); for(i=0;i Matrix Matrix::QSort() { int i,j,k; const unsigned int m = 7; const unsigned int nstack = 50; int indxt, itemp, l=0; int jstack=-1; T a; LISAWPAssert(subR == 1 || subC == 1, "number of rows or number of columns must be 1"); unsigned int ir = Size()-1; Matrix indx(ir+1); for (i=0; i<(int)(ir+1); i++){ indx(i) = i; } Matrix istack(nstack+1); for(;;){ if(ir-l=l;i--){ if((*this)(indx(i)) <= a) break; indx(i+1) = indx(i); } indx(i+1) = indxt; } if(jstack < 0) break; ir = istack(jstack--); l = istack(jstack--); } else{ k = (l+ir) >> 1; itemp = indx(k); indx(k) = indx(l+1); indx(l+1) = itemp; if((*this)(indx(l)) > (*this)(indx(ir))){ itemp = indx(ir); indx(ir) = indx(l); indx(l) = itemp; } if((*this)(indx(l+1)) > (*this)(indx(ir))){ itemp = indx(ir); indx(ir) = indx(l+1); indx(l+1) = itemp; } if((*this)(indx(l)) > (*this)(indx(l+1))){ itemp = indx(l); indx(l) = indx(l+1); indx(l+1) = itemp; } i = l+1; j = ir; indxt = indx(l+1); a = (*this)(indxt); for(;;){ do i++; while ((*this)(indx(i)) < a); do j--; while ((*this)(indx(j)) > a); if (j= j-l) { istack(jstack) = ir; istack(jstack-1) = i; ir = j-1; } else{ istack(jstack) = j-1; istack(jstack-1) = l; l = i; } } } return(indx); } template Matrix Matrix::Transpose() const { Matrix out (subC,subR); for(unsigned i=0;i Matrix Matrix::operator()(const IndexSet &ir, const IndexSet &ic) const { LISAWPAssert((ir.upper out; out.Attach(*this, ir.length, ic.length, ir.lower, ic.lower); return out; } template Matrix Matrix::operator()(const IndexSet &ir, const IndexSet &ic) { LISAWPAssert((ir.upper out; out.Attach(*this, ir.length, ic.length, ir.lower, ic.lower); return out; } template Matrix Matrix::operator()(const IndexSet &iSet) const { LISAWPAssert(iSet.step==1, "Index Set not contiguous"); LISAWPAssert((subR==1) || (subC==1), "The matrix must be single column or row"); if(subR==1){ LISAWPAssert(iSet.upper < subC,"Index Set not of proper sizes "); Matrix out; out.Attach(*this, 1, iSet.length, 0, iSet.lower); return out; } else{ LISAWPAssert(iSet.upper < subR,"Index Set not of proper sizes "); Matrix out; out.Attach(*this, iSet.length, 1, iSet.lower, 0); return out; } } template Matrix Matrix::operator()(const IndexSet &iSet) { LISAWPAssert(iSet.step==1, "Index Set not contiguous"); LISAWPAssert((subR==1) || (subC==1), "The matrix must be single column or row"); if(subR==1){ LISAWPAssert(iSet.upper < subC,"Index Set not of proper sizes "); Matrix out; out.Attach(*this, 1, iSet.length, 0, iSet.lower); return out; } else{ LISAWPAssert(iSet.upper < subR,"Index Set not of proper sizes "); Matrix out; out.Attach(*this, iSet.length, 1, iSet.lower, 0); return out; } } template Matrix Matrix::operator()(unsigned r,const IndexSet &iSet) const { LISAWPAssert(iSet.step==1, "Index Set not contiguous"); LISAWPAssert(r out; out.Attach(*this, 1, iSet.length, r, iSet.lower); return out; } template Matrix Matrix::operator()(unsigned r,const IndexSet &iSet) { LISAWPAssert(iSet.step==1, "Index Set not contiguous"); LISAWPAssert(r out; out.Attach(*this, 1, iSet.length, r, iSet.lower); return out; } template Matrix Matrix::operator()(const IndexSet &iSet, unsigned c) const { LISAWPAssert(iSet.step==1, "Index Set not contiguous"); LISAWPAssert(c out; out.Attach(*this, iSet.length, 1, iSet.lower, c); return out; } template Matrix Matrix::operator()(const IndexSet &iSet, unsigned c) { LISAWPAssert(iSet.step==1,"Index Set not contiguous"); LISAWPAssert(c out; out.Attach(*this, iSet.length, 1, iSet.lower, c); return out; } template void Matrix::SetValue(const IndexSet &iRow, const IndexSet &iCol, const T &val) { unsigned r,c; LISAWPAssert((iRow.upper < subR)&&(iCol.upper < subC),"Index Set Sizes are not correct"); r = iRow.start; for(unsigned i=0;i void Matrix::SetValue(const IndexSet &iRow, const IndexSet &iCol, const Matrix &mat) { unsigned r,c; LISAWPAssert((iRow.upper < subR)&&(iCol.upper < subC), "Index Set Sizes are not correct"); LISAWPAssert((iRow.length == mat.subR) && ( iCol.length == mat.subC),"Index Set Sizes are not correct"); r = iRow.start; for(unsigned i=0;i Matrix Matrix::GetSubMatrix(const IndexSet &iRow, const IndexSet &iCol) const { unsigned r,c; LISAWPAssert((iRow.upper < subR)&&(iCol.upper < subC),"Index Set Sizes are not correct"); Matrix out(iRow.length, iCol.length); r = iRow.start; for(unsigned i=0;i void Matrix::MultiplyT(const Matrix &m1, const Matrix &m2) { LISAWPAssert(m1.subC == m2.subC,"Matrix Sizes not consistent"); LISAWPAssert((subR==m1.subR)&&(subR==m2.subR), "Output matrix not of correct size"); for(unsigned i=0; i (sum); } } } template double Matrix::NormS() const { const_iterator it; double sum=0.0; for(unsigned i=0;i double Matrix::Sum() const { const_iterator it; double sum=0; for(unsigned i=0;i double Matrix::Rms() const { if(Size()==1) return 0.0; const_iterator it; double sum=0; for(unsigned i=0;i int Matrix::MinIndex() const { LISAWPAssert(Size(),"The minimum function can be called only for a non zero-size matrix"); LISAWPAssert(subR==1||subC==1,"The minimum function can be called only for a row or column matrix"); if(subR==1){ T min = *const_origin; int ind = 0; for(unsigned j=1;j *(const_origin + j)){ ind = j; min = *(const_origin + j); } return ind; } else{ T min = *const_origin; int ind = 0; for(unsigned j=1;j *(const_origin + j*stride)){ ind = j; min = *(const_origin + j*stride); } return ind; } } template int Matrix::MaxIndex() const { LISAWPAssert(Size(),"The maximum function can be called only for a non zero-size matrix"); LISAWPAssert(subR==1||subC==1,"The maximum function can be called only for a row or column matrix"); if(subR==1){ T max = *const_origin; int ind = 0; for(unsigned j=1;j Matrix::~Matrix() { this->resize(0); return; } // Template Instantiations template class Matrix; template class Matrix; template class Matrix; template class Matrix; } // namespace LISAWP ends