Mat.h

Go to the documentation of this file.
00001 /*
00002  * Expression Template Matrix Library
00003  *
00004  * Copyright (C) 2004 - 2006 Ricky Lung <mtlung@users.sourceforge.net>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 
00030 #ifdef _MSC_VER
00031 //  Disable the annoying warning of VC6
00032 #   if _MSC_VER < 1300
00033 #       pragma warning( disable : 4786 )
00034 #   endif   // VC6
00035 #   pragma once
00036 #   pragma warning( push )
00037 #   pragma warning( disable : 4100 4127 4239 4244 4512 4786 )
00038 #endif  // _MSC_VER
00039 
00040 
00041 #ifndef _EXMAT_MAT_H
00042 #define _EXMAT_MAT_H
00043 
00044 #include <iterator>
00045 #include <sstream>
00046 #include <iostream>
00047 #include <algorithm>
00048 #include "PlatformSpec.h"
00049 #include "Config.h"
00050 #include "ErrorCheck.h"
00051 #include "TypeTraits.h"
00052 #include "Commainit.h"
00053 #include "Assignment.h"
00054 #include "SIMD/SIMD.h"
00055 
00056 // Forward declaration of Mat and Vec
00057 namespace exmat {
00058     template<class Rep, class ErrChecker_> class Mat;
00059     template<class Rep, class ErrChecker_> class Vec;
00060 }   // namespace exmat
00061 
00062 /************************************************/
00064 namespace exmat {
00065 
00067 namespace PNS {
00068     template<class Mat, typename IdxT> EXMAT_INLINE2 static
00069     void IOResize(Mat& m, IdxT r, IdxT c, Int2Type<true>, Int2Type<true>) {
00070         m.resize(r, c);
00071     }
00072     template<class Mat, typename IdxT> EXMAT_INLINE2 static
00073     void IOResize(Mat& m, IdxT r, IdxT c, Int2Type<true>, Int2Type<false>) {
00074         m.resizeRow(r);
00075     }
00076     template<class Mat, typename IdxT> EXMAT_INLINE2 static
00077     void IOResize(Mat& m, IdxT r, IdxT c, Int2Type<false>, Int2Type<true>) {
00078         m.resizeCol(c);
00079     }
00080     template<class Mat, typename IdxT> EXMAT_INLINE2 static
00081     void IOResize(Mat& m, IdxT r, IdxT c, Int2Type<false>, Int2Type<false>) {
00082     }
00083 };};
00084 
00086 template<class Rep, class ErrChecker> EXMAT_INLINE0
00087 std::istream& operator>>(std::istream &is, exmat::Mat<Rep, ErrChecker>& mat) {
00088     typedef exmat::Mat<Rep, ErrChecker> mat_type;
00089     typedef typename mat_type::index_type index_type;
00090     index_type rs=0, cs=0;
00091     // Read the number of rows
00092     if(mat_type::IsDR) is >> rs;
00093     // Read the number of columns
00094     if(mat_type::IsDC) is >> cs;
00095     // Resize if needed
00096     exmat::PNS::IOResize(mat, rs, cs,
00097         exmat::Int2Type<mat_type::IsDR>(), exmat::Int2Type<mat_type::IsDC>());
00098     for(index_type i=0; i<mat.rows(); ++i) {
00099         for(index_type j=0; j<mat.cols(); ++j)
00100             is >> mat.setAt(i, j);
00101     }
00102     return is;
00103 }
00104 
00106 template<class Rep, class ErrChecker> EXMAT_INLINE0
00107 std::ostream& operator<<(std::ostream &os, const exmat::Mat<Rep, ErrChecker>& mat) {
00108     typedef typename exmat::Mat<Rep, ErrChecker>::index_type index_type;
00109     for(index_type i=0; i<mat.rows(); ++i) {
00110         for(index_type j=0; j<mat.cols(); ++j)
00111             os << mat.getAt(i, j) << " ";
00112         os << std::endl;
00113     }
00114     return os;
00115 }
00116 
00118 //template<class Rep, class ErrChecker> EXMAT_INLINE0
00119 //std::ostream& operator<<(std::ostream &os, const exmat::Vec<Rep, ErrChecker>& vec) {
00120 //  typedef typename exmat::Vec<Rep, ErrChecker>::index_type index_type;
00121 //  for(index_type i=0; i<vec.size(); ++i)
00122 //      os << vec.getAt(i) << " ";
00123 //
00124 //  return os;
00125 //}
00126 
00127 
00128 /************************************************/
00129 // Functional operators
00130 
00131 // VC6 and 7 have problems on using ExpMat<>::rep_type
00132 #if EXMAT_VC6 || EXMAT_VC7
00133 
00134 //  Macro to create operators for 2 Mat
00135 #define Mak_Op(LT, RT, OT, op, OpName)  \
00136 template<class L, class R, class LC, class RC> EXMAT_INLINE2    \
00137     const exmat::OT<exmat::ExpMat<exmat::OpName<L::rep_type, R::rep_type> >, exmat::ResultantChecker<LC,RC>::RET>   \
00138 op (const exmat::LT<L,LC>& A, const exmat::RT<R,RC>& B) {   \
00139     using namespace exmat;  \
00140     typedef ExpMat<OpName<L::rep_type, R::rep_type> > RETType;  \
00141     return RETType(A, B);   \
00142 }
00143 //  Macro to create operators for Mat and scalar
00144 #define Mak_ScalarOp1(OT, op, OpName)   \
00145 template<class L, class EC> EXMAT_INLINE2   \
00146     const exmat::OT<exmat::ExpMat<exmat::OpName<L::rep_type,exmat::ScalarCon<L::value_type> > >, EC>    \
00147 op (const exmat::OT<L,EC>& A, L::const_param_type scalar) { \
00148     using namespace exmat;  \
00149     typedef ExpMat<OpName<L::rep_type,ScalarCon<L::value_type> > > RETType; \
00150     return RETType(A, ScalarCon<L::value_type>(scalar));    \
00151 }
00152 //  Macro to create operators for scalar and Mat
00153 #define Mak_ScalarOp2(OT, op, OpName)   \
00154 template<class L, class EC> EXMAT_INLINE2   \
00155     const exmat::OT<exmat::ExpMat<exmat::OpName<exmat::ScalarCon<L::value_type>, L::rep_type> >, EC>    \
00156 op (typename L::const_param_type scalar, const exmat::OT<L,EC>& A) {    \
00157     using namespace exmat;  \
00158     typedef ExpMat<OpName<ScalarCon<L::value_type>, L::rep_type> > RETType; \
00159     return RETType(ScalarCon<L::value_type>(scalar), A);    \
00160 }
00161 
00162 #else
00163 
00165 #define Mak_Op(LT, RT, OT, op, OpName)  \
00166 template<class L, class R, class LC, class RC> EXMAT_INLINE2 static \
00167     const exmat::OT<exmat::ExpMat<typename exmat::OpName<typename L::rep_type, typename R::rep_type>::rep_type>, typename exmat::ResultantChecker<LC,RC>::RET>  \
00168 op (const exmat::LT<L,LC>& A, const exmat::RT<R,RC>& B) {   \
00169     using namespace exmat;  \
00170     typedef ExpMat<TTYPENAME OpName<TTYPENAME L::rep_type,TTYPENAME R::rep_type>::rep_type> RETType;    \
00171     return RETType(A, B);   \
00172 }
00173 
00174 #define Mak_ScalarOp1(OT, op, OpName)   \
00175 template<class L, class EC> EXMAT_INLINE2 static    \
00176     const exmat::OT<exmat::ExpMat<typename exmat::OpName<typename L::rep_type,exmat::ScalarCon<typename L::value_type> >::rep_type>, EC>    \
00177 op (const exmat::OT<L,EC>& A, typename L::const_param_type scalar) {    \
00178     using namespace exmat;  \
00179     typedef ExpMat<TTYPENAME OpName<TTYPENAME L::rep_type,ScalarCon<TTYPENAME L::value_type> >::rep_type> RETType;  \
00180     return RETType(A, ScalarCon<TTYPENAME L::value_type>(scalar));  \
00181 }
00182 
00183 #define Mak_ScalarOp2(OT, op, OpName)   \
00184 template<class L, class EC> EXMAT_INLINE2 static    \
00185     const exmat::OT<exmat::ExpMat<typename exmat::OpName<exmat::ScalarCon<typename L::value_type>, typename L::rep_type>::rep_type>, EC>    \
00186 op (typename L::const_param_type scalar, const exmat::OT<L,EC>& A) {    \
00187     using namespace exmat;  \
00188     typedef ExpMat<TTYPENAME OpName<ScalarCon<TTYPENAME L::value_type>, TTYPENAME L::rep_type>::rep_type> RETType;  \
00189     return RETType(ScalarCon<TTYPENAME L::value_type>(scalar), A);  \
00190 }
00191 
00192 #endif  // EXMAT_VC6 || EXMAT_VC7
00193 
00194 
00203 
00204 Mak_Op(Mat, Mat, Mat, operator+, AddExp);
00206 Mak_Op(Vec, Vec, Vec, operator+, AddExp);
00207 
00208 // Addition of Mat with scalar
00210 Mak_ScalarOp1(Mat, operator+, AddExp);
00212 Mak_ScalarOp2(Mat, operator+, AddExp);
00213 
00214 // Addition of Vec with scalar
00216 Mak_ScalarOp1(Vec, operator+, AddExp);
00218 Mak_ScalarOp2(Vec, operator+, AddExp);
00220 
00221 
00225 
00226 Mak_Op(Mat, Mat, Mat, operator-, SubExp);
00228 Mak_Op(Vec, Vec, Vec, operator-, SubExp);
00229 
00230 // Subtraction of Mat with scalar
00232 Mak_ScalarOp1(Mat, operator-, SubExp);
00234 Mak_ScalarOp2(Mat, operator-, SubExp);
00235 
00236 // Subtraction of Vec with scalar
00238 Mak_ScalarOp1(Vec, operator-, SubExp);
00240 Mak_ScalarOp2(Vec, operator-, SubExp);
00242 
00243 
00247 
00248 Mak_Op(Mat, Mat, Mat, operator*, MulExp);
00250 Mak_ScalarOp1(Mat, operator*, ScalarMulExp);
00252 Mak_ScalarOp2(Mat, operator*, ScalarMulExp);
00254 Mak_Op(Vec, Vec, Vec, operator*, MulExp);
00256 Mak_Op(Mat, Vec, Vec, operator*, MulExp);
00258 Mak_Op(Vec, Mat, Vec, operator*, MulExp);
00260 Mak_ScalarOp1(Vec, operator*, ScalarMulExp);
00262 Mak_ScalarOp2(Vec, operator*, ScalarMulExp);
00264 
00268 
00269 Mak_ScalarOp1(Mat, operator/, ScalarDivExp);
00271 Mak_ScalarOp1(Vec, operator/, ScalarDivExp);
00273 
00274 // Clean up the Macro
00275 #undef Mak_Op
00276 #undef Mak_ScalarOp1
00277 #undef Mak_ScalarOp2
00278 
00280 
00281 
00282 namespace exmat {
00283 
00285 
00288 template<class MAT>
00289 struct ConstErrChkedRow {
00290     typedef typename MAT::index_type        index_type;
00291     typedef typename MAT::reference         reference;
00292     typedef typename MAT::const_reference   const_reference;
00293     typedef typename MAT::ErrChecker        ErrChecker;
00294 
00295     EXMAT_INLINE2 ConstErrChkedRow(const MAT& mat_, index_type i)
00296         : mat(mat_), row(i) {}
00297     EXMAT_INLINE2 const_reference operator[](const index_type i) const {
00298         ErrChecker::AssertBounds(index_type(0), index_type(mat.cols()-1), i);
00299         return mat.getAt(row, i);
00300     }
00301     const MAT& mat;
00302     index_type row;
00303 };
00304 
00306 
00309 template<class MAT>
00310 struct ErrChkedRow {
00311     typedef typename MAT::index_type        index_type;
00312     typedef typename MAT::reference         reference;
00313     typedef typename MAT::const_reference   const_reference;
00314     typedef typename MAT::ErrChecker        ErrChecker;
00315 
00316     EXMAT_INLINE2 ErrChkedRow(MAT& mat_, index_type i)
00317         : mat(mat_), row(i) {}
00318     EXMAT_INLINE2 reference operator[](const index_type i) {
00319         ErrChecker::AssertBounds(index_type(0), index_type(mat.cols()-1), i);
00320         return mat.setAt(row, i);
00321     }
00322     EXMAT_INLINE2 const_reference operator[](const index_type i) const {
00323         ErrChecker::AssertBounds(index_type(0), index_type(mat.cols()-1), i);
00324         return mat.getAt(row, i);
00325     }
00326     MAT& mat;
00327     index_type row;
00328 };
00329 
00330 
00332 
00335 template<class Rep, class ErrChecker_=DefaultErrorChecker>
00336 class Mat : public Rep {
00337 public:
00338     typedef Rep                     super_type;
00339     typedef Mat<Rep, ErrChecker_>   self_type;
00340     enum {
00341         IsFullErrorChecker = ISSAMETYPE<ErrChecker_,FullErrorChecker>::RET,
00342 //      IsDense = HasTagOf<Rep, DenseTag>::RET,
00343         IsDR = (Rep::ROWS == 0),
00344         IsDC = (Rep::COLS == 0)
00345     };
00346     typedef typename
00347     IF<IsFullErrorChecker, ErrChkedRow<self_type>, typename Rep::row_type
00348     >::RET row_type;
00349     typedef typename
00350     IF<IsFullErrorChecker, ConstErrChkedRow<self_type>, typename Rep::const_row_type
00351     >::RET const_row_type;
00352     typedef typename Rep::col_type          col_type;
00353     typedef typename Rep::value_type        value_type;
00354     typedef typename Rep::index_type        index_type;
00355     typedef typename Rep::reference         reference;
00356     typedef typename Rep::const_reference   const_reference;
00357     typedef typename Rep::param_type        param_type;
00358     typedef typename Rep::const_param_type  const_param_type;
00359     typedef ErrChecker_                     ErrChecker;
00360     typedef typename Rep::rep_type          rep_type;
00361 
00362 private:
00364 
00367     EXMAT_INLINE2 row_type IndexOp(index_type i, Int2Type<true>) {  // Error checked
00368         ErrChecker::AssertBounds(index_type(0), index_type(Rep::rows()-1), i);
00369         return row_type(*this, i);
00370     }
00371     EXMAT_INLINE2 row_type IndexOp(index_type i, Int2Type<false>) { // No error checking
00372         return Rep::operator[](i);
00373     }
00374     EXMAT_INLINE2 const_row_type IndexOp(index_type i, Int2Type<true>) const {
00375         ErrChecker::AssertBounds(index_type(0), index_type(Rep::rows()-1), i);
00376         return const_row_type(*this, i);
00377     }
00378     EXMAT_INLINE2 const_row_type IndexOp(index_type i, Int2Type<false>) const {
00379         return Rep::operator[](i);
00380     }
00382 
00383 private:
00385 
00388     EXMAT_INLINE2 void CTORresizer(size_t r, size_t c, Int2Type<true>, Int2Type<true>)  // Dynamic row, dynamic col
00389     {   Rep::resize(r, c);  }
00390     EXMAT_INLINE2 void CTORresizer(size_t r, size_t c, Int2Type<true>, Int2Type<false>) // Dynamic row, static col
00391     {   Rep::resize(r); }
00392     EXMAT_INLINE2 void CTORresizer(size_t r, size_t c, Int2Type<false>, Int2Type<true>) // Static row, dynamic col
00393     {   Rep::resize(c); }
00394     EXMAT_INLINE2 void CTORresizer(size_t r, size_t c, Int2Type<false>, Int2Type<false>)// Static row, static col
00395     {}
00397 
00398 public:
00399     /************************************************/
00401     EXMAT_INLINE2 Mat() {}
00402 
00403     // Helper class for enable_if
00404     template<typename T>
00405     struct _AlwaysTrue {    enum {RET=true};    };
00410     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00411     Mat(const Mat<Rep2, ErrChk2>& A
00412 #if !EXMAT_NO_SFINAE
00413         ,typename DisableIf_c<  // The SFINAE principle need Rep2 to be referenced
00414             IsDerivedFrom<Rep,ViewTag>::RET && _AlwaysTrue<Rep2>::RET
00415         >::RET* dummy=NULL
00416 #endif  // !EXMAT_NO_SFINAE
00417     ) {
00418         // Do resizing of this matrix
00419         CTORresizer(A.rows(), A.cols(), Int2Type<IsDR>(), Int2Type<IsDC>());
00420         assign(*this, A);
00421 //      AssignDispatcher(*this, A);
00422     }
00423 
00425 
00426     template<class Rep2> EXMAT_INLINE2
00427     Mat(ExpMat<Rep2>& A) : Rep(A) {}
00428     template<class Rep2> EXMAT_INLINE2
00429     Mat(const ExpMat<Rep2>& A) : Rep(A) {}
00431 
00433 
00434 //  Mat(typename Rep::super_type& A) : Rep(A) {}
00435 //  Mat(const typename Rep::super_type& A) : Rep(A) {}
00437 
00441     EXMAT_INLINE2 Mat(const std::string& s) {
00442         // It's only for dense matrix!
00443 //      STATIC_CHECK(IsDense, Mat_StrCtrOnlyForDenseMat);
00444         std::istringstream ins(s);
00445         ::operator>>(ins, *this);
00446     }
00447 
00449 
00450     template<class T1, class T2>
00451     EXMAT_INLINE2 Mat(T1& t1, T2& t2) : Rep(t1, t2) {}
00452     template<class T1, class T2, class T3>
00453     EXMAT_INLINE2 Mat(T1& t1, T2& t2, T3& t3) : Rep(t1, t2, t3) {}
00454     template<class T1, class T2, class T3, class T4>
00455     EXMAT_INLINE2 Mat(T1& t1, T2& t2, T3& t3, T4& t4) : Rep(t1, t2, t3, t4) {}
00456     template<class T1, class T2, class T3, class T4, class T5>
00457     EXMAT_INLINE2 Mat(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) : Rep(t1, t2, t3, t4, t5) {}
00458     template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
00459     EXMAT_INLINE2 Mat(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9) : Rep(t1, t2, t3, t4, t5, t6, t7, t8, t9) {}
00460     template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16>
00461     EXMAT_INLINE2 Mat(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9, T10 t10, T11& t11, T12& t12, T13& t13, T14& t14, T15& t15, T16& t16) : Rep(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16) {}
00462     // Const version of generic constructor, fail in VC6
00463 #if HAVE_PARTIAL_SPECIALIZATION
00464     template<class T1, class T2>
00465     EXMAT_INLINE2 Mat(const T1& t1, const T2& t2) : Rep(t1, t2) {}
00466     template<class T1, class T2, class T3>
00467     EXMAT_INLINE2 Mat(const T1& t1, const T2& t2, const T3& t3) : Rep(t1, t2, t3) {}
00468     template<class T1, class T2, class T3, class T4>
00469     EXMAT_INLINE2 Mat(const T1& t1, const T2& t2, const T3& t3, const T4& t4) : Rep(t1, t2, t3, t4) {}
00470     template<class T1, class T2, class T3, class T4, class T5>
00471     EXMAT_INLINE2 Mat(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) : Rep(t1, t2, t3, t4, t5) {}
00472 #endif  // HAVE_PARTIAL_SPECIALIZATION
00473 
00474 
00476 
00477     EXMAT_INLINE2 explicit Mat(const Dim& d) : Rep(d) {}
00478     EXMAT_INLINE2 explicit Mat(const Dim& d1, const Dim& d2, const_param_type s) : Rep(d1, d2, s) {}
00480 
00481     EXMAT_INLINE2 Mat(const_param_type s) : Rep(s) {}
00482 
00483     /************************************************/
00487 
00488     // The scalar assignment operator is replaced by the CommaInitializer,
00489     // The same effect get be achieved by using ScalarInit
00490     //  EXMAT_INLINE2 self_type& operator=(const value_type& v_) {
00491     //      (*static_cast<Rep*>(this)) = v_;
00492     //      return *this;
00493     //  }
00494 
00495     EXMAT_INLINE2 self_type& ScalarInit(const_param_type s) {
00496         (*static_cast<Rep*>(this)) = s;
00497         return *this;
00498     }
00501     EXMAT_INLINE2 CommaInitializer<self_type> operator=(const_param_type s) {
00502         return CommaInitializer<self_type>(*this, s);
00503     }
00504 
00506     template<class Res, class Exp> EXMAT_INLINE2 static
00507     void AssignDispatcher(Res& res, const Exp& exp) {
00508         enum {
00509             IsSIMD =
00510                 // Both left and right hand side should have SIMDTag
00511                 IsDerivedFrom<Res,SIMDTag>::RET &&
00512                 IsDerivedFrom<Exp,SIMDTag>::RET &&
00513                 // If EXP is not linear then it needs ENABLE_TMP_ANALYSIS
00514                 (ENABLE_TMP_ANALYSIS || Exp::IsLinearRecursive)
00515         };
00516 #if ENABLE_UNROLLING
00517         typedef LinearBinExpSize<Res, Exp> BINEXPSize;
00518         enum {
00519             // Prefer unroll row before col for row major storage
00520             UnrollRow = 
00521                 BINEXPSize::ROWS > 0 &&
00522                 (unsigned int)(Exp::ENOP * BINEXPSize::COLS) < (unsigned int)MAX_UROLLROW_NOP
00523         };
00524         enum {
00525             UnrollCol =
00526                 BINEXPSize::COLS > 0 &&
00527                 (unsigned int)Exp::TNOP < (unsigned int)MAX_FULLUROLL_NOP
00528         };
00529 
00530         enum {
00531             AssignDispatchID =
00532                 IsSIMD ? exmat::PNS::ASSIGN_TYPE::Ass_SIMD : 
00533                 UnrollRow + 2*UnrollCol
00534         };
00535 #else
00536         enum {
00537             AssignDispatchID =
00538                 IsSIMD ? exmat::PNS::ASSIGN_TYPE::Ass_SIMD : 
00539                 PNS::ASSIGN_TYPE::Ass_NoUnRoll
00540         };
00541 #endif
00542 
00543         // Do compatibility check here, dimension should be the same
00544         ErrChecker::AssertCompat(res.rows() == exp.rows() && res.cols() == exp.cols());
00545 
00546         exmat::PNS::Assign(res, exp, Int2Type<AssignDispatchID>());
00547 //      exmat::PNS::Assign(res, exp, Int2Type<false>(), Int2Type<false>());
00548 
00549         // Original assignment loops
00550 //      for(index_type i=res.rows(); i--; ) {
00551 //          for(index_type j=res.cols(); j--; )
00552 //              res.setAt(i, j) = exp.getAt(i, j);
00553 //      }
00554     }
00555 
00557     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00558     Mat& AssignNoAna(const Mat<Rep2, ErrChk2>& A) {
00559         AssignDispatcher(*this, A);
00560         return *this;
00561     }
00563     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00564     Mat& operator=(const Mat<Rep2, ErrChk2>& A) {
00565         // Using the global assign function with the default analysis option
00566         assign(*this, A, EXMAT_DEFAULT_ANALYSIS);
00567         return *this;
00568     }
00570     EXMAT_INLINE2 Mat& operator=(const self_type& A) {
00571         // Forward the assignment operation to the rep_type
00572         *((Rep*)(this)) = A;
00573         return *this;
00574     }
00576 
00577     /************************************************/
00589     EXMAT_INLINE2 reference operator() (index_type r, index_type c) {
00590         ErrChecker::AssertBounds(index_type(0), index_type(Rep::rows()-1), r);
00591         ErrChecker::AssertBounds(index_type(0), index_type(Rep::cols()-1), c);
00592         return setAt(r, c);
00593     }
00594     EXMAT_INLINE2 const_reference operator() (index_type r, index_type c) const {
00595         ErrChecker::AssertBounds(index_type(0), index_type(Rep::rows()-1), r);
00596         ErrChecker::AssertBounds(index_type(0), index_type(Rep::cols()-1), c);
00597         return getAt(r, c);
00598     }
00600 
00610     EXMAT_INLINE2 row_type operator[] (index_type r) {
00611         return IndexOp(r, Int2Type<IsFullErrorChecker>());
00612     }
00613     EXMAT_INLINE2 const_row_type operator[] (index_type r) const {
00614         return IndexOp(r, Int2Type<IsFullErrorChecker>());
00615     }
00617 
00618     /************************************************/
00622 
00623     EXMAT_INLINE2 self_type& operator+=(const_param_type s) {
00624         *this = ::operator+(*this, s);
00625         return *this;
00626     }
00628     EXMAT_INLINE2 self_type& operator-=(const_param_type s) {
00629         *this = ::operator-(*this, s);
00630         return *this;
00631     }
00633     EXMAT_INLINE2 self_type& operator*=(const_param_type s) {
00634         *this = ::operator*(*this, s);
00635         return *this;
00636     }
00638     EXMAT_INLINE2 self_type& operator/=(const_param_type s) {
00639         *this = ::operator/(*this, s);
00640         return *this;
00641     }
00643     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00644     self_type& operator+=(const Mat<Rep2,ErrChk2>& A) {
00645         *this = ::operator+(*this, A);
00646         return *this;
00647     }
00649     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00650     self_type& operator-=(const Mat<Rep2,ErrChk2>& A) {
00651         *this = ::operator-(*this, A);
00652         return *this;
00653     }
00655     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00656     self_type& operator*=(const Mat<Rep2,ErrChk2>& A) {
00657         // Dynamic sized matrix is handled by using direct initialization
00658         self_type tmp( ::operator*(*this, A) );
00659         *this = tmp;
00660         return *this;
00661     }
00663 
00664     /************************************************/
00672     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00673     bool operator!=(const Mat<Rep2,ErrChk2>& A) const {
00674         return !(*this == A);
00675     }
00680     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00681     bool operator==(const Mat<Rep2,ErrChk2>& A) const
00682     {
00683         typedef typename Rep2::value_type T2;
00684         // At least the dimension should be the same
00685         if(Rep::rows() != A.rows() || Rep::cols() != A.cols())
00686             return false;
00687         typedef LEleType(value_type,T2) lower_type;
00688         for(index_type i=Rep::rows(); i--; ) {
00689             for(index_type j=Rep::cols(); j--; )
00690                 if( lower_type(getAt(i,j)) != lower_type(A.getAt(i,j)) )
00691                     return false;
00692         }
00693         return true;
00694     }
00699     EXMAT_INLINE2 bool operator!=(const value_type& s) const {
00700         return !(*this == s);
00701     }
00702     friend EXMAT_INLINE2 bool operator!=(const value_type& lhs, const self_type& rhs) {
00703         return rhs != lhs;
00704     }
00709     EXMAT_INLINE2 bool operator==(const value_type& s) const
00710     {
00711         for(index_type i=Rep::rows(); i--; ) {
00712             for(index_type j=Rep::cols(); j--; )
00713                 if( getAt(i,j) != s )
00714                     return false;
00715         }
00716         return true;
00717     }
00718     friend EXMAT_INLINE2 bool operator==(const value_type& lhs, const self_type& rhs) {
00719         return rhs == lhs;
00720     }
00722 
00723 //protected:
00724     /************************************************/
00730     EXMAT_INLINE2 reference setAt(index_type i)
00731     {   return Rep::setAt(i);   }
00732     EXMAT_INLINE2 const_reference getAt(index_type i) const
00733     {   return Rep::getAt(i);   }
00734     EXMAT_INLINE2 reference setAt(index_type r, index_type c)
00735     {   return Rep::setAt(r, c);    }
00736     EXMAT_INLINE2 const_reference getAt(index_type r, index_type c) const
00737     {   return Rep::getAt(r, c);    }
00739 
00740     /************************************************/
00741     // Make some friends
00742 //  friend std::ostream& operator<<(std::ostream &os, const self_type& mat);
00743 };
00744 
00745 
00746 /************************************************/
00748 template<class Rep, class ErrChecker> EXMAT_INLINE2 static
00749 const Mat<ExpMat<SubExp<ScalarCon<typename Rep::value_type>, Rep> >, ErrChecker>
00750 operator-(const Mat<Rep, ErrChecker>& mat) {
00751     typedef typename Rep::value_type value_type;
00752     // --! Only simply return 0 - mat, which is not efficient
00753     return Mat<ExpMat<SubExp<ScalarCon<value_type>, Rep> >, ErrChecker>(ScalarCon<value_type>(0), mat);
00754 }
00755 
00756 
00758 
00761 template<class Rep, class ErrChecker_=DefaultErrorChecker>
00762 class Vec : public Mat<Rep, ErrChecker_> {
00763 public:
00764     typedef Mat<Rep, ErrChecker_>           super_type;
00765     typedef Vec<Rep, ErrChecker_>           self_type;
00766     typedef typename Rep::row_type          row_type;
00767     typedef typename Rep::const_row_type    const_row_type;
00768     typedef typename Rep::col_type          col_type;
00769     typedef typename Rep::value_type        value_type;
00770     typedef typename Rep::index_type        index_type;
00771     typedef typename Rep::reference         reference;
00772     typedef typename Rep::const_reference   const_reference;
00773     typedef typename Rep::param_type        param_type;
00774     typedef typename Rep::const_param_type  const_param_type;
00775     typedef ErrChecker_                     ErrChecker;
00776     typedef typename Rep::rep_type          rep_type;
00777 
00778     enum {
00780         IsRowVec = (Rep::ROWS == 1),
00782         IsColVec = (Rep::COLS == 1)
00783     };
00784 
00785 public:
00786     /************************************************/
00787     // Constructors
00789     EXMAT_INLINE2 Vec() {}
00790 
00792 
00793 #if defined( EXMAT_VC6 ) || defined( EXMAT_VC7 )
00794     //  VC6 have problems on distinguishing const and non-const template function
00795     //  therefore extra functions are need for single parameter
00796     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00797     Vec(Vec<Rep2, ErrChk2>& vec) : super_type(vec) {}
00798     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00799     Vec(const Vec<Rep2, ErrChk2>& vec) : super_type(vec) {}
00800     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00801     Vec(Mat<Rep2, ErrChk2>& vec) : super_type(vec) {}
00802     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00803     Vec(const Mat<Rep2, ErrChk2>& vec) : super_type(vec) {}
00804     template<class Rep2> EXMAT_INLINE2
00805     Vec(ExpMat<Rep2>& A) : super_type(A) {}
00806     template<class Rep2> EXMAT_INLINE2
00807     Vec(const ExpMat<Rep2>& A) : super_type(A) {}
00808     EXMAT_INLINE2 Vec(const std::string& s) : super_type(s) {}
00810     EXMAT_INLINE2 Vec(const Dim& d) : super_type(d) {}
00811 #else
00812     template<typename T1> EXMAT_INLINE2
00813     Vec(T1& t1) : super_type(t1) {}
00814     template<typename T1> EXMAT_INLINE2
00815     Vec(const T1& t1) : super_type(t1) {}
00816 //  template<typename T1, typename T2, typename T3> EXMAT_INLINE2
00817 //  Vec(T1 t1, T2 t2, T3 t3) : super_type(t1, t2, t3) {}
00818 //  template<typename T1, typename T2, typename T3, typename T4> EXMAT_INLINE2
00819 //  Vec(T1 t1, T2 t2, T3 t3, T4 t4) : super_type(t1, t2, t3, t4) {}
00820 #endif
00821     template<typename T1, typename T2> EXMAT_INLINE2
00822     Vec(const T1& t1, const T2& t2) : super_type(t1, t2) {}
00823     template<typename T1, typename T2, typename T3> EXMAT_INLINE2
00824     Vec(T1& t1, T2& t2, T3& t3) : super_type(t1, t2, t3) {}
00825     template<typename T1, typename T2, typename T3, typename T4> EXMAT_INLINE2
00826     Vec(T1& t1, T2& t2, T3& t3, T4& t4) : super_type(t1, t2, t3, t4) {}
00828 
00830     EXMAT_INLINE2 Vec(const_param_type s) : super_type(s) {}
00831 
00832     /************************************************/
00836 
00837     EXMAT_INLINE2 CommaInitializer<self_type> operator=(const_param_type v_) {
00838         return CommaInitializer<self_type>(*this, v_);
00839     }
00841     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00842     Vec& operator=(const Vec<Rep2, ErrChk2>& A) {
00843         ((super_type*)(this))->operator=(A);
00844         return *this;
00845     }
00847     template<class Rep2, class ErrChk2> EXMAT_INLINE2
00848     Vec& operator=(const Mat<Rep2, ErrChk2>& A) {
00849         ((super_type*)(this))->operator=(A);
00850         return *this;
00851     }
00853     EXMAT_INLINE2 Vec& operator=(const self_type& A) {
00854         // Forward the assignment operation to the rep_type
00855         ((super_type*)(this))->operator=(A);
00856         return *this;
00857     }
00859 
00860     /************************************************/
00870     EXMAT_INLINE2 reference operator() (index_type i) {
00871         ErrChecker::AssertBounds(index_type(0), index_type(this->size()-1), i);
00872         return setAt(i);
00873     }
00874     EXMAT_INLINE2 const_reference operator() (index_type i) const {
00875         ErrChecker::AssertBounds(index_type(0), index_type(this->size()-1), i);
00876         return getAt(i);
00877     }
00878     EXMAT_INLINE2 reference operator[] (index_type i) {
00879         ErrChecker::AssertBounds(index_type(0), index_type(this->size()-1), i);
00880         return setAt(i);
00881     }
00882     EXMAT_INLINE2 const_reference operator[] (index_type i) const {
00883         ErrChecker::AssertBounds(index_type(0), index_type(this->size()-1), i);
00884         return getAt(i);
00885     }
00887 
00888 };
00889 
00890 /************************************************/
00892 template<class Rep, class ErrChecker> EXMAT_INLINE2 static
00893 const Vec<ExpMat<SubExp<ScalarCon<typename Rep::value_type>, typename Rep::rep_type> >, ErrChecker>
00894 operator-(const Vec<Rep, ErrChecker>& vec) {
00895     typedef typename Rep::value_type value_type;
00896     // --! Only simply return 0 - mat, which is not efficient
00897     return Vec<ExpMat<SubExp<ScalarCon<value_type>, TTYPENAME Rep::rep_type> >, ErrChecker>(ScalarCon<value_type>(0), vec);
00898 }
00899 
00900 }   // namespace exmat
00901 
00902 
00906 #define EXMAT_DERIVEDCLASS_IMP(NAME, MatOrVec)                  \
00907 public:                                                         \
00908 typedef typename super_type::rep_type   rep_type;               \
00909 typedef typename super_type::ErrChecker ErrChecker;             \
00910 typedef typename super_type::value_type value_type;             \
00911 EXMAT_INLINE2 NAME(value_type s) : super_type(s) {}             \
00912 EXMAT_INLINE2 NAME(const std::string& s) : super_type(s) {}     \
00913 template<class Rep2, class EC2> EXMAT_INLINE2                   \
00914 NAME(::exmat::MatOrVec<Rep2,EC2>& A) : super_type(A) {}         \
00915 template<class Rep2, class EC2> EXMAT_INLINE2                   \
00916 NAME(const ::exmat::MatOrVec<Rep2,EC2>& A) : super_type(A) {}   \
00917 template<class Rep2> EXMAT_INLINE2                              \
00918 NAME(::exmat::ExpMat<Rep2>& A) : super_type(A) {}               \
00919 template<class Rep2> EXMAT_INLINE2                              \
00920 NAME(const ::exmat::ExpMat<Rep2>& A) : super_type(A) {}         \
00921 template<class T1, class T2> EXMAT_INLINE2                      \
00922 NAME(const T1& t1, const T2& t2) : super_type(t1, t2) {}        \
00923 template<class T1, class T2, class T3> EXMAT_INLINE2            \
00924 NAME(const T1& t1, const T2& t2, const T3& t3)                  \
00925  : super_type(t1, t2, t3) {}                                    \
00926 template<class T1, class T2, class T3, class T4> EXMAT_INLINE2  \
00927 NAME(const T1& t1, const T2& t2, const T3& t3, const T4& t4)    \
00928  : super_type(t1, t2, t3, t4) {}                                \
00929 private:
00930 
00931 #define EXMAT_DERIVEDCLASS_ASSIGNOP(NAME, MatOrVec)             \
00932 public:                                                         \
00933 template<class Rep2, class EC> EXMAT_INLINE2                    \
00934 self_type& operator=(const ::exmat::MatOrVec<Rep2, EC>& v)      \
00935 {   super_type::operator=(v);   return *this;   }               \
00936 EXMAT_INLINE2 self_type& operator=(value_type s)                \
00937 {   super_type::operator=(s);   return *this;   }
00938 
00939 
00941 #define EXMAT_DERIVEDCLASS_Mak_Op(LT, RT, OT, op, OpName)   \
00942 template<class L, class R, class LC, class RC> EXMAT_INLINE2    \
00943     const OT< ::exmat::ExpMat<OpName<typename L::rep_type,typename R::rep_type> >, typename ::exmat::ResultantChecker<LC,RC>::RET> >    \
00944 op (const LT<L,LC> >& A, const RT<R,RC> >& B) { \
00945     typedef ::exmat::ExpMat<OpName<TTYPENAME L::rep_type,TTYPENAME R::rep_type> > RETType;  \
00946     return RETType(A, B);                                       \
00947 }
00948 #define EXMAT_DERIVEDCLASS_Mak_ScalarOp1(OT, op, OpName)    \
00949 template<class L, class ErrChk> EXMAT_INLINE2   \
00950     const OT< ::exmat::ExpMat<OpName<typename L::rep_type,::exmat::ScalarCon<typename L::value_type> > >, ErrChk> > \
00951 op (const OT<L,ErrChk> >& A, typename L::const_param_type scalar) { \
00952     typedef ::exmat::ExpMat<OpName<TTYPENAME L::rep_type,::exmat::ScalarCon<TTYPENAME L::value_type> > > RETType;   \
00953     return RETType(A, ::exmat::ScalarCon<TTYPENAME L::value_type>(scalar)); \
00954 }
00955 #define EXMAT_DERIVEDCLASS_Mak_ScalarOp2(OT, op, OpName)    \
00956 template<class L, class ErrChk> EXMAT_INLINE2   \
00957     const OT< ::exmat::ExpMat<OpName< ::exmat::ScalarCon<typename L::value_type>, typename L::rep_type> >, ErrChk> >    \
00958 op (typename L::const_param_type scalar, const OT<L,ErrChk> >& A) { \
00959     typedef ::exmat::ExpMat<OpName< ::exmat::ScalarCon<TTYPENAME L::value_type>, TTYPENAME L::rep_type> > RETType;  \
00960     return RETType(exmat::ScalarCon<TTYPENAME L::value_type>(scalar), A);   \
00961 }
00962 
00963 #define EXMAT_DERIVEDCLASS_DEFALUTOPS(ClassName, MatOrVec)  \
00964 EXMAT_DERIVEDCLASS_Mak_Op(ClassName< ::exmat::MatOrVec, ClassName< ::exmat::MatOrVec, ClassName< ::exmat::MatOrVec, operator+, ::exmat::AddExp);    \
00965 EXMAT_DERIVEDCLASS_Mak_ScalarOp1(ClassName< ::exmat::MatOrVec, operator+, ::exmat::AddExp);         \
00966 EXMAT_DERIVEDCLASS_Mak_ScalarOp2(ClassName< ::exmat::MatOrVec, operator+, ::exmat::AddExp);         \
00967 EXMAT_DERIVEDCLASS_Mak_Op(ClassName< ::exmat::MatOrVec, ClassName< ::exmat::MatOrVec, ClassName< ::exmat::MatOrVec, operator-, ::exmat::SubExp);    \
00968 EXMAT_DERIVEDCLASS_Mak_ScalarOp1(ClassName< ::exmat::MatOrVec, operator-, ::exmat::SubExp);         \
00969 EXMAT_DERIVEDCLASS_Mak_ScalarOp2(ClassName< ::exmat::MatOrVec, operator-, ::exmat::SubExp);         \
00970 EXMAT_DERIVEDCLASS_Mak_ScalarOp1(ClassName< ::exmat::MatOrVec, operator*, ::exmat::ScalarMulExp);   \
00971 EXMAT_DERIVEDCLASS_Mak_ScalarOp2(ClassName< ::exmat::MatOrVec, operator*, ::exmat::ScalarMulExp);   \
00972 EXMAT_DERIVEDCLASS_Mak_ScalarOp1(ClassName< ::exmat::MatOrVec, operator/, ::exmat::ScalarDivExp);   \
00973 EXMAT_DERIVEDCLASS_Mak_ScalarOp2(ClassName< ::exmat::MatOrVec, operator/, ::exmat::ScalarDivExp);
00974 
00975 
00976 #ifdef _MSC_VER
00977 #   pragma warning( pop )
00978 #endif  // _MSC_VER
00979 
00980 
00981 #endif  // _EXMAT_MAT_H

Generated on Sat May 6 23:11:58 2006 for Exmat by  doxygen 1.4.6-NO