// $Id: tmatrix.cc,v 1.24 2003-08-08 13:07:06 ansari Exp $ // C.Magneville 04/99 #include "machdefs.h" #include #include #include "pexceptions.h" #include "tmatrix.h" /*! \class SOPHYA::TMatrix \ingroup TArray The TMatrix class specializes the TArray class for representing two dimensional arrays as matrices. Matrix and vector operations, such as matrix multiplication or transposition is implemented. \b Matrix is a typedef for double precision floating point matrix ( TMatrix ). \sa SOPHYA::TArray SOPHYA::TVector \sa SOPHYA::Range \sa SOPHYA::Sequence \sa SOPHYA::MathArray \sa SOPHYA::SimpleMatrixOperation The following sample code illustrates vector-matrix multiplication and matrix inversion, using simple gauss inversion. \code #include "array.h" // .... int n = 5; // Size of matrix and vectors here Matrix a(n,n); a = RandomSequence(RandomSequence::Gaussian, 0., 2.5); Vector x(n); x = RegularSequence(1.,3.); Vector b = a*x; cout << " ----- Vector x = \n " << x << endl; cout << " ----- Vector b = a*x = \n " << b << endl; SimpleMatrixOperation smo; Matrix inva = smo.Inverse(a); cout << " ----- Matrix Inverse(a) = \n " << inva << endl; cout << " ----- Matrix a*Inverse(a) = \n " << inva*a << endl; cout << " ----- Matrix Inverse(a)*b (=Inv(a)*a*x) = \n " << inva*b << endl; cout << " ----- Matrix x-Inverse(a)*b = (=0 ?)\n " << x-inva*b << endl; \endcode */ //////////////////////////////////////////////////////////////// //**** Createur, Destructeur //! Default constructor template TMatrix::TMatrix() // Constructeur par defaut. : TArray() { arrtype_ = 1; // Type = Matrix } //! constructor of a matrix with r lines et c columns. /*! \param r : number of rows \param c : number of columns \param mm : define the memory mapping type \sa ReSize */ template TMatrix::TMatrix(sa_size_t r,sa_size_t c, short mm) // Construit une matrice de r lignes et c colonnes. : TArray() { if ( (r == 0) || (c == 0) ) throw ParmError("TMatrix::TMatrix(sa_size_t r,sa_size_t c) NRows or NCols = 0"); arrtype_ = 1; // Type = Matrix ReSize(r, c, mm); } //! Constructor by copy /*! \warning datas are \b SHARED with \b a. \sa NDataBlock::NDataBlock(const NDataBlock&) */ template TMatrix::TMatrix(const TMatrix& a) // Constructeur par copie : TArray(a) { arrtype_ = 1; // Type = Matrix UpdateMemoryMapping(a, SameMemoryMapping); } //! Constructor by copy /*! \param share : if true, share data. If false copy data */ template TMatrix::TMatrix(const TMatrix& a, bool share) // Constructeur par copie avec possibilite de forcer le partage ou non. : TArray(a, share) { arrtype_ = 1; // Type = Matrix UpdateMemoryMapping(a, SameMemoryMapping); } //! Constructor of a matrix from a TArray \b a template TMatrix::TMatrix(const TArray& a) : TArray(a) { if (a.NbDimensions() > 2) throw SzMismatchError("TMatrix::TMatrix(const TArray& a) a.NbDimensions()>2 "); if (a.NbDimensions() == 1) { size_[1] = 1; step_[1] = size_[0]*step_[0]; ndim_ = 2; } arrtype_ = 1; // Type = Matrix UpdateMemoryMapping(a, SameMemoryMapping); } //! Constructor of a matrix from a TArray \b a /*! \param a : TArray to be copied or shared \param share : if true, share data. If false copy data \param mm : define the memory mapping type */ template TMatrix::TMatrix(const TArray& a, bool share, short mm ) : TArray(a, share) { if (a.NbDimensions() > 2) throw SzMismatchError("TMatrix::TMatrix(const TArray& a, ...) a.NbDimensions()>2"); if (a.NbDimensions() == 1) { size_[1] = 1; step_[1] = size_[0]*step_[0]; ndim_ = 2; } arrtype_ = 1; // Type = Matrix UpdateMemoryMapping(a, mm); } //! Constructor of a matrix from a TArray \b a , with a different data type template TMatrix::TMatrix(const BaseArray& a) : TArray() { arrtype_ = 1; // Type = Matrix UpdateMemoryMapping(a, SameMemoryMapping); SetBA(a); } //! Destructor template TMatrix::~TMatrix() { } //! Set matrix equal to \b a and return *this /*! \warning Datas are copied (cloned) from \b a. \sa NDataBlock::operator=(const NDataBlock&) */ template TArray& TMatrix::Set(const TArray& a) { if (a.NbDimensions() > 2) throw SzMismatchError("TMatrix::Set(const TArray& a) a.NbDimensions() > 2"); if ((arrtype_ == 2) && (a.NbDimensions() > 1) && (a.Size(0) > 1) && (a.Size(1) > 1) ) throw SzMismatchError("TMatrix::Set(const TArray& a) Size(0,1)>1 for Vector"); TArray::Set(a); if (NbDimensions() == 1) { size_[1] = 1; step_[1] = size_[0]*step_[0]; ndim_ = 2; } UpdateMemoryMapping(*this, SameMemoryMapping); return(*this); } template TArray& TMatrix::SetBA(const BaseArray& a) { if (a.NbDimensions() > 2) throw SzMismatchError("TMatrix::SetBA(const BaseArray& a) a.NbDimensions() > 2"); if ((arrtype_ == 2) && (a.NbDimensions() > 1) && (a.Size(0) > 1) && (a.Size(1) > 1) ) throw SzMismatchError("TMatrix::Set(const TArray& a) Size(0,1)>1 for Vector"); TArray::SetBA(a); if (NbDimensions() == 1) { size_[1] = 1; step_[1] = size_[0]*step_[0]; ndim_ = 2; } UpdateMemoryMapping(*this, SameMemoryMapping); return(*this); } //! Resize the matrix /*! \param r : number of rows \param c : number of columns \param mm : define the memory mapping type (SameMemoryMapping,CMemoryMapping ,FortranMemoryMapping,DefaultMemoryMapping) */ template void TMatrix::ReSize(sa_size_t r, sa_size_t c, short mm) { if(r==0||c==0) throw(SzMismatchError("TMatrix::ReSize r or c==0 ")); if ((arrtype_ == 2) && (r > 1) && (c > 1)) throw(SzMismatchError("TMatrix::ReSize r>1&&c>1 for Vector ")); sa_size_t size[BASEARRAY_MAXNDIMS]; for(int_4 kk=0; kk::ReSize(2, size, 1); UpdateMemoryMapping(mm); } //! Re-allocate space for the matrix /*! \param r : number of rows \param c : number of columns \param mm : define the memory mapping type \param force : if true re-allocation is forced, if not it occurs only if the required space is greater than the old one. \sa ReSize */ template void TMatrix::Realloc(sa_size_t r,sa_size_t c, short mm, bool force) { if(r==0||c==0) throw(SzMismatchError("TMatrix::Realloc r or c==0 ")); if ((arrtype_ == 2) && (r > 1) && (c > 1)) throw(SzMismatchError("TMatrix::Realloc r>1&&c>1 for Vector ")); sa_size_t size[BASEARRAY_MAXNDIMS]; for(int_4 kk=0; kk::Realloc(2, size, 1, force); UpdateMemoryMapping(mm); } // $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ? //! Return a submatrix define by \b Range \b rline and \b rcol template TMatrix TMatrix::SubMatrix(Range rline, Range rcol) const { short mm = GetMemoryMapping(); Range rx, ry; if (mm == CMemoryMapping) { rx = rcol; ry = rline; } else { ry = rcol; rx = rline; } TMatrix sm(SubArray(rx, ry, Range(0), Range(0), Range(0)),true, mm); sm.UpdateMemoryMapping(mm); return(sm); } //////////////////////////////////////////////////////////////// // Transposition //! Transpose matrix in place, by changing the memory mapping template TMatrix& TMatrix::TransposeSelf() { short vt = (marowi_ == veceli_) ? ColumnVector : RowVector; int_4 rci = macoli_; macoli_ = marowi_; marowi_ = rci; veceli_ = (vt == ColumnVector ) ? marowi_ : macoli_; return(*this); } //! Returns the transpose of the original matrix. /*! The data is shared between the two matrices \return return a new matrix */ template TMatrix TMatrix::Transpose() const { TMatrix tm(*this); tm.TransposeSelf(); return tm; } //! Returns a new matrix, corresponding to the transpose of the original matrix /*! \param mm : define the memory mapping type (SameMemoryMapping,CMemoryMapping,FortranMemoryMapping) \return return a new matrix */ template TMatrix TMatrix::Transpose(short mm) const { if (mm == SameMemoryMapping) mm = GetMemoryMapping(); TMatrix tm(NCols(), NRows(), mm); for(sa_size_t i=0; i TMatrix TMatrix::Rearrange(short mm) const { if ( mm == SameMemoryMapping) mm = GetMemoryMapping(); else if ( (mm != CMemoryMapping) && (mm != FortranMemoryMapping) ) mm = GetDefaultMemoryMapping(); if (mm == GetMemoryMapping()) return (TMatrix(*this, true)); TMatrix tm(NRows(), NCols(), mm); for(sa_size_t i=0; i TMatrix& TMatrix::SetIdentity(IdentityMatrix imx) { if (ndim_ == 0) { sa_size_t sz = imx.Size(); if (sz < 1) sz = 1; ReSize(sz, sz); } T diag = (T)imx.Diag(); if (NRows() != NCols()) throw SzMismatchError("TMatrix::operator= (IdentityMatrix) NRows() != NCols()") ; *this = (T) 0; for(sa_size_t i=0; i string TMatrix::InfoString() const { string rs = "TMatrix<"; rs += typeid(T).name(); char buff[64]; sprintf(buff, ">(NRows=%ld, NCols=%ld)", (long)NRows(), (long)NCols()); rs += buff; return(rs); } //! Print matrix /*! \param os : output stream \param maxprt : maximum numer of print \param si : if true, display attached DvList \param ascd : if true, suppresses the display of line numbers, suitable for ascii dump format. \sa SetMaxPrint */ template void TMatrix::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const { if (maxprt < 0) maxprt = max_nprt_; sa_size_t npr = 0; Show(os, si); if (ndim_ < 1) return; sa_size_t kc,kr; for(kr=0; kr 1) && (size_[macoli_] > 10) && ascd) cout << "----- Line= " << kr << endl; for(kc=0; kc 0) os << " "; os << (*this)(kr, kc); npr++; if (npr >= (sa_size_t) maxprt) { if (npr < totsize_) os << "\n .... " << endl; return; } } os << endl; } os << endl; } //////////////////////////////////////////////////////////////// //**** Multiplication matricielle ***** //////////////////////////////////////////////////////////////// //! Return the matrix product C = (*this)*B /*! \param mm : define the memory mapping type for the return matrix */ template TMatrix TMatrix::Multiply(const TMatrix& b, short mm) const { if (NCols() != b.NRows()) throw(SzMismatchError("TMatrix::Multiply(b) NCols() != b.NRows() ") ); if (mm == SameMemoryMapping) mm = GetMemoryMapping(); TMatrix rm(NRows(), b.NCols(), mm); const T * pea; const T * peb; T sum; sa_size_t r,c,k; sa_size_t stepa = Step(ColsKA()); sa_size_t stepb = b.Step(b.RowsKA()); // Calcul de C=rm = A*B (A=*this) for(r=0; r #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix< complex > #pragma define_template TMatrix< complex > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix< complex >; template class TMatrix< complex >; #endif