#line 1 "/user/cvsspst/ees1cg/RAVL/RAVL-0.7/Math/LinearAlgebra/General/TMatrix.hh" // This file is part of RAVL, Recognition And Vision Library // Copyright (C) 2001, University of Surrey // This code may be redistributed under the terms of the GNU Lesser // General Public License (LGPL). See the lgpl.licence file for details or // see http://www.gnu.org/copyleft/lesser.html // file-header-ends-here #ifndef RAVL_TMATRIXC_HEADER #define RAVL_TMATRIXC_HEADER 1 /////////////////////////////////////////////////////////// //! userlevel=Normal //! docentry="Ravl.Math.Linear Algebra" //! rcsid="$Id: TMatrix.hh,v 1.17 2002/08/08 14:34:08 craftit Exp $" //! file="Ravl/Math/LinearAlgebra/General/TMatrix.hh" //! author="Charles Galambos" //! date="10/09/1998" //! lib=RavlMath #include "Ravl/SArray2d.hh" #include "Ravl/SArr2Iter.hh" #include "Ravl/SArr2Iter2.hh" #include "Ravl/SArr2Iter3.hh" #include "Ravl/TVector.hh" #include "Ravl/BfAccIter.hh" namespace RavlN { //! userlevel=Advanced //: Templated matrix's. template class TMatrixC : public SArray2dC { public: inline TMatrixC() {} //: Default constructor. inline TMatrixC(const SArray2dC &oth) : SArray2dC(oth) {} //: Base class constructor. TMatrixC(const TVectorC &vec) : SArray2dC(vec.Buffer(),vec.Size(),1) {} //: Treat vector as column matrix. // Note: This does not copy the vector, changes // made to the matrix will appear in the vector. inline TMatrixC(SizeT rows,SizeT cols); //: Constructor. inline TMatrixC(SizeT rows,SizeT cols,const DataT *data); //: Constructor. // With row wise array of initalisations data. TMatrixC(DataT v1,DataT v2, DataT v3,DataT v4); //: Construct a 2 x 2 matrix from given values. TMatrixC(DataT v1,DataT v2,DataT v3, DataT v4,DataT v5,DataT v6, DataT v7,DataT v8,DataT v9); //: Construct a 3 x 3 matrix from given values. template TMatrixC(const TFMatrixC &fmat) : TMatrixC(N,M) { for(int i = 0;i < N;i++) for(int j = 0;j < M;j++) (*this)[i][j] = fmat[i][j]; } //: Construct from a fixed size matrix. template operator TFMatrixC () { RavlAssertMsg(Rows() == N && Cols() == M,"Size mismatch while converting to fixed size matrix. "); TFMatrixC ret; for(int i = 0;i < N;i++) for(int j = 0;j < M;j++) fmat[i][j] = (*this)[i][j]; return ret; } //: Convert to fixed size matrix. inline SizeT Rows() const { return Size1(); } //: Return the number of rows inline SizeT Cols() const { return Size2(); } //: Return the number of columns TMatrixC operator*(DataT val) const { return TMatrixC(SArray2dC::operator*(val)); } //: Multiply by a constant. TVectorC operator*(const TVectorC & vector) const; //: Multiplication "TVectorC" = "This" * vector TMatrixC operator*(const TMatrixC & mat) const; //: Multiplication "result" = "this" * "mat" TMatrixC MulT(const TMatrixC & B) const; //: Multiplication A * B.T() TMatrixC TMul(const TMatrixC & B) const; //: Multiplication A.T() * B TVectorC TMul(const TVectorC& vec) const; //: Multiplication A.T() * vec TMatrixC AAT() const { return MulT(*this); } //: Return A * A.T(). TMatrixC ATA() const { return TMul(*this); } //: Return A.T() * A. TMatrixC T() const; //: Get transpose of matrix. static TMatrixC Identity(UIntT n); //: Returns an identity matrx of n by n. // NB. This is a static function and should be called MatrixC::Identity(n). // where n is the size of the matrix. const TMatrixC &SetDiagonal(const TVectorC &d); //: Set the diagonal of this matrix. // If d.Size() != Cols() an error is given. const TMatrixC &AddDiagonal(const TVectorC &d); //: Add a vector to the diagonal of this matrix. // If d.Size() != Cols() an error is given. TMatrixC SubMatrix(SizeT size1,SizeT size2) { return TMatrixC(SArray2dC(*this,size1,size2)); } //: Get sub matrix of size1,size2. // The creates a new access, but does not copy the data itself. // The matrix always starts from 0,0. DataT SumOfAbs() const; //: Sum the absolute values of all members of the matrix. const TMatrixC &AddOuterProduct(const TVectorC &vec1,const TVectorC &vec2); //: Add outer product of vec1 and vec2 to this matrix. const TMatrixC &AddOuterProduct(const TVectorC &vec1,const TVectorC &vec2,const DataT &a); //: Add outer product of vec1 and vec2 multiplied by a to this matrix . const TMatrixC &SetSmallToBeZero(const DataT &min); //: Set values smaller than 'min' to zero in vector. void SwapRows(int i,int j); //: Swap two rows in the matrix. }; ////////////////////////////////////////////////////// template inline TMatrixC::TMatrixC(SizeT rows,SizeT cols) : SArray2dC(rows,cols) {} template inline TMatrixC::TMatrixC(SizeT rows,SizeT cols,const DataT *data) : SArray2dC(rows,cols) { const DataT *at = data; for(BufferAccess2dIterC it(*this,Size2());it;it++) *it = *(at++); } template TMatrixC::TMatrixC(DataT v1,DataT v2, DataT v3,DataT v4) : SArray2dC(2,2) { (*this)[0][0] = v1; (*this)[0][1] = v2; (*this)[1][0] = v3; (*this)[1][1] = v4; } template TMatrixC::TMatrixC(DataT v1,DataT v2,DataT v3, DataT v4,DataT v5,DataT v6, DataT v7,DataT v8,DataT v9) : SArray2dC(3,3) { (*this)[0][0] = v1; (*this)[0][1] = v2; (*this)[0][2] = v3; (*this)[1][0] = v4; (*this)[1][1] = v5; (*this)[1][2] = v6; (*this)[2][0] = v7; (*this)[2][1] = v8; (*this)[2][2] = v9; } template TVectorC TMatrixC::operator*(const TVectorC & vector) const { const SizeT rdim = Rows(); const SizeT cdim = Cols(); TVectorC out(rdim); for (UIntT i = 0; i < rdim; ++i) { DataT sum = 0.0; for (UIntT k = 0; k < cdim; k++) sum += (*this)[i][k] * vector[k]; out[i] = sum; } return out; } template TMatrixC TMatrixC::operator*(const TMatrixC & mat) const { RavlAssert(Cols() == mat.Rows()); #if 0 const SizeT rdim = Rows(); const SizeT cdim = mat.Cols(); const SizeT dim = Cols(); TMatrixC out(rdim, cdim); for (UIntT r = 0; r < rdim; r++) for (UIntT c = 0; c < cdim; c++) { RealT sum = 0.0; for (UIntT k = 0; k < dim; k++) sum += (*this)[r][k] * mat[k][c]; out[r][c] = sum; } #else // Do work. TMatrixC out(Rows(), mat.Cols()); if(Rows() == 0 || Cols() == 0) return out; // Nothing to do ! BufferAccess2dIterC it1(*this,Size2()); BufferAccess2dIterC it2(mat,mat.Size2()); BufferAccess2dIterC ot(out,mat.Size2()); out.Fill(0); do { do { do { ot.Data() += it1.Data() * it2.Data(); ot.NextCol(); } while(it2.Next()) ; ot.RowStart(); // Go back to begining of output row. } while(it1.Next()) ; ot.NextRow(); it2.First(mat,mat.Size2()); } while(it1) ; #endif return out; } //: Multiplication A * B.T() template TMatrixC TMatrixC::MulT(const TMatrixC & mat) const { // Check assumptions. RavlAssert(Cols() == mat.Cols()); // Do work. TMatrixC out(Rows(), mat.Rows()); if(Rows() == 0 || Cols() == 0) return out; // Nothing to do. BufferAccess2dIterC it1(*this,Size2()); BufferAccess2dIterC it2(mat,mat.Size2()); BufferAccess2dIterC ot(out,out.Size2()); do { do { RealT sum = 0; do { sum += it1.Data() * it2.Data(); it1.NextCol(); } while(it2.Next()); ot.Data() = sum; ot.Next(); if(!it2.IsElm()) break; it1.RowStart(); } while(1); if(!ot.IsElm()) break; it2.First(mat,Size2()); it1.NextRow(); } while(1) ; return out; } //: Multiplication A.T() * B template TMatrixC TMatrixC::TMul(const TMatrixC & mat) const { // Check assumptions. RavlAssert(Rows() == mat.Rows()); // Do work. TMatrixC out(Cols(), mat.Cols()); if(Rows() == 0 || Cols() == 0) return out; // Nothing to do. BufferAccess2dIterC it1(*this,Size2()); BufferAccess2dIterC it2(mat,Size2()); BufferAccess2dIterC ot(out,Size2()); out.Fill(0); do { do { do { ot.Data() += it1.Data() * it2.Data(); it2.NextCol(); } while(ot.Next()) ; it1.Next(); if(!ot.IsElm()) break; it2.RowStart(); } while(1) ; if(!it1.IsElm()) break; it2.NextRow(); ot.First(out,Size2()); } while(1) ; return(out); } //: Get transpose of matrix. template TMatrixC TMatrixC::T() const { TMatrixC ret(Cols(),Rows()); for(IndexC i = 0;i < Rows();i++) for(IndexC j = 0;j < Cols();j++) ret[j][i] = (*this)[i][j]; return ret; } template DataT TMatrixC::SumOfAbs() const { BufferAccess2dIterC it(*this,Size2()); if(!it) return DataT(); DataT ret(*it); for(it++;it;it++) ret += Abs(*it); return ret; } template const TMatrixC &TMatrixC::AddOuterProduct(const TVectorC &vec1,const TVectorC &vec2) { RavlAssert(Size1() == vec1.Size()); RavlAssert(Size2() == vec2.Size()); BufferAccessIterC v1(vec1); BufferAccess2dIterC it(*this,Size2()); while(it) { BufferAccessIterC v2(vec2); RealT r1 = (*v1); do { *it += r1 * (*v2); v2++; } while(it.Next()) ; v1++; } return *this; } template const TMatrixC &TMatrixC::AddOuterProduct(const TVectorC &vec1,const TVectorC &vec2,const DataT &a) { RavlAssert(Size1() == vec1.Size()); RavlAssert(Size2() == vec2.Size()); BufferAccessIterC v1(vec1); BufferAccess2dIterC it(*this,Size2()); while(it) { BufferAccessIterC v2(vec2); DataT r1 = (*v1) * a; do { *it += r1 * (*v2); v2++; } while(it.Next()) ; v1++; } return *this; } template TMatrixC TMatrixC::Identity(UIntT n) { TMatrixC ret(n,n); ret.Fill(0); for(UIntT i = 0;i < n;i++) ret[i][i] = 1; return ret; } template const TMatrixC &TMatrixC::SetDiagonal(const TVectorC &d) { RavlAssert(d.Size() == Cols()); for(UIntT i = 0;i < Cols();i++) (*this)[i][i] = d[i]; return (*this); } template const TMatrixC &TMatrixC::AddDiagonal(const TVectorC &d) { RavlAssert(d.Size() == Cols()); for(UIntT i = 0;i < Cols();i++) (*this)[i][i] += d[i]; return (*this); } template const TMatrixC &TMatrixC::SetSmallToBeZero(const DataT &min) { for(BufferAccess2dIterC it(*this,Size2());it;it++) if(Abs(*it) < min) SetToZero(*it); return (*this); } template void TMatrixC::SwapRows(int i,int j) { for(BufferAccessIter2C it((*this)[i],(*this)[j]);it;it++) RavlN::Swap(it.Data1(),it.Data2()); } ///// Some functions from TVectorC<> that return matrixes. ////// template TMatrixC TVectorC::OuterProduct(const TVectorC &a) const { TMatrixC ret(Size(),a.Size()); BufferAccessIterC v1(*this); BufferAccess2dIterC it(ret,ret.Size2()); while(it) { BufferAccessIterC v2(a); RealT r1 = (*v1); do { *it = r1 * (*v2); v2++; } while(it.Next()) ; v1++; } return ret; } template TMatrixC TVectorC::OuterProduct(const TVectorC &a,RealT b) const { TMatrixC ret(Size(),a.Size()); BufferAccessIterC v1(*this); BufferAccess2dIterC it(ret,ret.Size2()); while(it) { BufferAccessIterC v2(a); RealT r1 = (*v1) * b; do { *it = r1 * (*v2); v2++; } while(it.Next()) ; v1++; } return ret; } template TMatrixC TVectorC::OuterProduct() const { return OuterProduct(*this); } template TMatrixC OuterProduct(const Slice1dC &a,const Slice1dC &b) { TMatrixC ret(a.Size(),b.Size()); Slice1dIterC v1(a); BufferAccess2dIterC it(ret,ret.Size2()); while(it) { Slice1dIterC v2(b); do { *it = (*v1) * (*v2); v2++; } while(it.Next()) ; v1++; } return ret; } //: Outer product of two slices. // This treats the slices as vectors. template TMatrixC OuterProduct(const Slice1dC &a) { return OuterProduct(a,a); } //: Outer product of a slice with itself. // This treats the slice as a vector. template void MulAdd(const TVectorC &vec,const TMatrixC &mat,const TVectorC &add,TVectorC &result) { result = vec * mat + add; } //: Compute result = vec * mat + add; // For compatibility with the fixed length vectors. template void Mul(const TVectorC &vec,const TMatrixC &mat,TVectorC &result) { result = vec * mat + add; } //: Compute result = vec * mat; // For compatibility with the fixed length vectors } #endif