// This may look like C code, but it is really -*- C++ -*- #ifndef SOpeMatrix_SEEN #define SOpeMatrix_SEEN #include "machdefs.h" #include "tmatrix.h" #include "tvector.h" namespace SOPHYA { ///////////////////////////////////////////////////////////////////////// // Classe de lignes/colonnes de matrices enum TRCKind {TmatrixRow=0, TmatrixCol=1, TmatrixDiag=2}; template class TMatrixRC { public: TMatrixRC(); TMatrixRC(TMatrix& m, TRCKind kind, uint_4 index=0); virtual ~TMatrixRC() {} // Acces aux rangees et colonnes de matrices static TMatrixRC Row(TMatrix & m, uint_4 r); static TMatrixRC Col(TMatrix & m, uint_4 c); static TMatrixRC Diag(TMatrix & m); int_4 Next(); int_4 Prev(); int_4 SetCol(int_4 c); int_4 SetRow(int_4 r); int_4 SetDiag(); static uint_4 Step(const TMatrix& m, TRCKind rckind); static T* Org(const TMatrix&, TRCKind rckind, uint_4 ind=0); TRCKind Kind() const { return kind; } uint_4 NElts() const; T& operator()(uint_4 i); T operator()(uint_4 i) const; TMatrixRC& operator = (const TMatrixRC& rc); TVector GetVect() const; TMatrixRC& operator += (const TMatrixRC& rc); TMatrixRC& operator -= (const TMatrixRC& rc); TMatrixRC& operator *= (T x); TMatrixRC& operator /= (T x); TMatrixRC& operator -= (T x); TMatrixRC& operator += (T x); TMatrixRC& LinComb(T a, T b, const TMatrixRC& rc, uint_4 first=0); TMatrixRC& LinComb(T b, const TMatrixRC& rc, uint_4 first=0); uint_4 IMaxAbs(uint_4 first=0); static void Swap(TMatrixRC& rc1, TMatrixRC& rc2); inline static double Abs_Value(uint_1 v) {return (double) v;} inline static double Abs_Value(uint_2 v) {return (double) v;} inline static double Abs_Value(int_2 v) {return (v>0)? (double) v: (double) -v;} inline static double Abs_Value(int_4 v) {return (v>0)? (double) v: (double) -v;} inline static double Abs_Value(int_8 v) {return (v>0)? (double) v: (double) -v;} inline static double Abs_Value(uint_4 v) {return (double) v;} inline static double Abs_Value(uint_8 v) {return (double) v;} inline static double Abs_Value(r_4 v) {return (double) fabsf(v);} inline static double Abs_Value(r_8 v) {return fabs(v);} inline static double Abs_Value(complex v) {return sqrt(v.real()*v.real()+v.imag()*v.imag());} inline static double Abs_Value(complex v) {return sqrt(v.real()*v.real()+v.imag()*v.imag());} protected: TMatrix* matrix; T* data; int_4 index; uint_4 step; TRCKind kind; }; template inline T operator * (const TMatrixRC& a, const TMatrixRC& b) { if ( a.NElts() != b.NElts() ) throw(SzMismatchError("TMatrixRC::operator * size mismatch\n")); if ( a.Kind() != b.Kind() ) throw(SzMismatchError("TMatrixRC::operator * type mismatch\n")); T sum = 0; for(uint_4 i=0; i inline uint_4 TMatrixRC::Step(const TMatrix& m, TRCKind rckind) { switch (rckind) { case TmatrixRow : return 1; case TmatrixCol : return m.NCols(); case TmatrixDiag : return m.NCols()+1; } return 0; } template inline T* TMatrixRC::Org(const TMatrix& m, TRCKind rckind, uint_4 index) { switch (rckind) { case TmatrixRow : return const_cast(m.Data()) + index * m.NCols(); case TmatrixCol : return const_cast(m.Data()) + index; case TmatrixDiag : return const_cast(m.Data()); } return NULL; } template inline uint_4 TMatrixRC::NElts() const { if (!matrix) return 0; switch (kind) { case TmatrixRow : return matrix->NCols(); case TmatrixCol : return matrix->NRows(); case TmatrixDiag : return matrix->NCols(); } return 0; } template inline T& TMatrixRC::operator()(uint_4 i) {return data[i*step];} template inline T TMatrixRC::operator()(uint_4 i) const {return data[i*step];} //////////////////////////////////////////////////////////////// // Typedef pour simplifier et compatibilite Peida typedef TMatrixRC MatrixRC; //////////////////////////////////////////////////////////////// template class SimpleMatrixOperation { public: // Pivot de Gauss : diagonalise la matrice A, en effectuant les memes // operations sur la matrice B static TMatrix Inverse(TMatrix const & A); static T GausPiv(TMatrix& A, TMatrix& B); }; // Resolution du systeme A*C = B inline r_8 LinSolveInPlace(TMatrix& a, TVector& b) { if(a.NCols() != b.NRows() || a.NCols() != a.NRows()) throw(SzMismatchError("LinSolveInPlace(TMatrix,TVector) size mismatch")); return SimpleMatrixOperation::GausPiv(a,b); } // Resolution du systeme A*C = B, avec C retourne dans B inline r_8 LinSolve(const TMatrix& a, const TVector& b, TVector& c) { if(a.NCols() != b.NRows() || a.NCols() != a.NRows()) throw(SzMismatchError("LinSolve(TMatrix,TVector) size mismatch")); c = b; TMatrix a1(a); return SimpleMatrixOperation::GausPiv(a1,c); } } // Fin du namespace #endif