matrix_expr.h

Go to the documentation of this file.
00001 /* -*- C++ -*- ------------------------------------------------------------
00002  
00003 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
00004 
00005 The Configurable Math Library (CML) is distributed under the terms of the
00006 Boost Software License, v1.0 (see cml/LICENSE for details).
00007 
00008  *-----------------------------------------------------------------------*/
00016 #ifndef matrix_expr_h
00017 #define matrix_expr_h
00018 
00019 
00020 #include <cml/et/size_checking.h>
00021 #include <cml/matrix/matrix_traits.h>
00022 #include <cml/matrix/matrix_promotions.h>
00023 
00024 /* XXX Don't know which it should be just yet, since RVO seems to obviate the
00025  * need for a reference type.  However, copy by value copies the *entire
00026  * expression tree rooted at the MatrixXpr<>, so this choice is bound to affect
00027  * performance for some compiler or another:
00028  */
00029 #define MATXPR_ARG_TYPE               const et::MatrixXpr<XprT>&
00030 #define MATXPR_ARG_TYPE_N(_N_)        const et::MatrixXpr<XprT##_N_>&
00031 
00032 //#define MATXPR_ARG_TYPE               const et::MatrixXpr<XprT>
00033 //#define MATXPR_ARG_TYPE_N(_N_)        const et::MatrixXpr<XprT##_N_>
00034 
00035 namespace cml {
00036 namespace et {
00037 
00039 template<class ExprT>
00040 class MatrixXpr
00041 {
00042   public:
00043 
00044     typedef MatrixXpr<ExprT> expr_type;
00045 
00046     /* Copy the expression by value into higher-up expressions: */
00047     typedef expr_type expr_const_reference;
00048 
00049     typedef typename ExprT::value_type value_type;
00050     typedef matrix_result_tag result_tag;
00051     typedef typename ExprT::size_tag size_tag;  // Just inherit size type.
00052 
00053     /* Store the expression traits: */
00054     typedef ExprTraits<ExprT> expr_traits;
00055 
00056     /* Get the reference type: */
00057     typedef typename expr_traits::const_reference expr_reference;
00058 
00059     /* Get the result type: */
00060     typedef typename expr_traits::result_type result_type;
00061     
00062     /* Get the basis type: */
00063     typedef typename result_type::basis_orient basis_orient;
00064 
00065     /* Get the temporary type: */
00066     typedef typename result_type::temporary_type temporary_type;
00067 
00068     /* For matching by assignability: */
00069     typedef cml::et::not_assignable_tag assignable_tag;
00070 
00071 
00072   public:
00073 
00075     enum { array_rows = ExprT::array_rows, array_cols = ExprT::array_cols };
00076 
00077 
00078   public:
00079 
00081     matrix_size size() const {
00082         return matrix_size(this->rows(),this->cols());
00083     }
00084 
00086     size_t rows() const { 
00087         return expr_traits().rows(m_expr);
00088     }
00089 
00091     size_t cols() const {
00092         return expr_traits().cols(m_expr);
00093     }
00094 
00096     expr_reference expression() const { return m_expr; }
00097 
00099     value_type operator()(size_t i, size_t j) const {
00100         return expr_traits().get(m_expr,i,j);
00101     }
00102     
00104     value_type basis_element(size_t i, size_t j) const {
00105         return basis_element(i,j,basis_orient());
00106     }
00107 
00108 
00109   public:
00110 
00112     explicit MatrixXpr(expr_reference expr) : m_expr(expr) {}
00113 
00115     MatrixXpr(const expr_type& e) : m_expr(e.m_expr) {}
00116 
00117 
00118   protected:
00119 
00120     value_type basis_element(size_t i, size_t j, row_basis) const {
00121         return (*this)(i,j);
00122     }
00123 
00124     value_type basis_element(size_t i, size_t j, col_basis) const {
00125         return (*this)(j,i);
00126     }
00127 
00128 
00129   protected:
00130 
00131     expr_reference m_expr;
00132 
00133 
00134   private:
00135 
00136     /* Cannot be assigned to: */
00137     expr_type& operator=(const expr_type&);
00138 };
00139 
00141 template<class ExprT>
00142 struct ExprTraits< MatrixXpr<ExprT> >
00143 {
00144     typedef MatrixXpr<ExprT> expr_type;
00145     typedef ExprT arg_type;
00146 
00147     typedef typename expr_type::value_type value_type;
00148     typedef typename expr_type::expr_const_reference const_reference;
00149     typedef typename expr_type::result_tag result_tag;
00150     typedef typename expr_type::size_tag size_tag;
00151     typedef typename expr_type::result_type result_type;
00152     typedef typename expr_type::assignable_tag assignable_tag;
00153     typedef expr_node_tag node_tag;
00154 
00155     value_type get(const expr_type& e, size_t i, size_t j) const {
00156         return e(i,j);
00157     }
00158 
00159 
00160     matrix_size size(const expr_type& e) const { return e.size(); }
00161     size_t rows(const expr_type& e) const { return e.rows(); }
00162     size_t cols(const expr_type& e) const { return e.cols(); }
00163 };
00164 
00165 
00170 template<class ExprT, class OpT>
00171 class UnaryMatrixOp
00172 {
00173   public:
00174 
00175     typedef UnaryMatrixOp<ExprT,OpT> expr_type;
00176 
00177     /* Record ary-ness of the expression: */
00178     typedef unary_expression expr_ary;
00179 
00180     /* Copy the expression by value into higher-up expressions: */
00181     typedef expr_type expr_const_reference;
00182 
00183     typedef typename OpT::value_type value_type;
00184     typedef matrix_result_tag result_tag;
00185     typedef typename ExprT::size_tag size_tag;
00186 
00187     /* Store the expression traits for the subexpression: */
00188     typedef ExprTraits<ExprT> expr_traits;
00189 
00190     /* Reference type for the subexpression: */
00191     typedef typename expr_traits::const_reference expr_reference;
00192 
00193     /* Get the result type: */
00194     typedef typename expr_traits::result_type result_type;
00195 
00196     /* Get the temporary type: */
00197     typedef typename result_type::temporary_type temporary_type;
00198 
00199     /* For matching by assignability: */
00200     typedef cml::et::not_assignable_tag assignable_tag;
00201 
00202 
00203   public:
00204 
00206     enum { array_rows = ExprT::array_rows, array_cols = ExprT::array_cols };
00207 
00208 
00209   public:
00210 
00212     matrix_size size() const {
00213         return matrix_size(this->rows(),this->cols());
00214     }
00215 
00217     size_t rows() const {
00218         return expr_traits().rows(m_expr);
00219     }
00220 
00222     size_t cols() const {
00223         return expr_traits().cols(m_expr);
00224     }
00225 
00227     value_type operator()(size_t i, size_t j) const {
00228 
00229         /* This uses the expression traits to figure out how to access the
00230          * i,j'th element of the subexpression:
00231          */
00232         return OpT().apply(expr_traits().get(m_expr,i,j));
00233     }
00234 
00235 
00236   public:
00237 
00239     explicit UnaryMatrixOp(expr_reference expr) : m_expr(expr) {}
00240 
00242     UnaryMatrixOp(const expr_type& e) : m_expr(e.m_expr) {}
00243 
00244 
00245   protected:
00246 
00247     expr_reference m_expr;
00248 
00249 
00250   private:
00251 
00252     /* Cannot be assigned to: */
00253     expr_type& operator=(const expr_type&);
00254 };
00255 
00257 template<class ExprT, class OpT>
00258 struct ExprTraits< UnaryMatrixOp<ExprT,OpT> >
00259 {
00260     typedef UnaryMatrixOp<ExprT,OpT> expr_type;
00261     typedef ExprT arg_type;
00262 
00263     typedef typename expr_type::value_type value_type;
00264     typedef typename expr_type::expr_const_reference const_reference;
00265     typedef typename expr_type::result_tag result_tag;
00266     typedef typename expr_type::size_tag size_tag;
00267     typedef typename expr_type::result_type result_type;
00268     typedef typename expr_type::assignable_tag assignable_tag;
00269     typedef expr_node_tag node_tag;
00270 
00271     value_type get(const expr_type& e, size_t i, size_t j) const {
00272         return e(i,j);
00273     }
00274 
00275     matrix_size size(const expr_type& e) const { return e.size(); }
00276     size_t rows(const expr_type& e) const { return e.rows(); }
00277     size_t cols(const expr_type& e) const { return e.cols(); }
00278 };
00279 
00280 
00282 template<class LeftT, class RightT, class OpT>
00283 class BinaryMatrixOp
00284 {
00285   public:
00286 
00287     typedef BinaryMatrixOp<LeftT,RightT,OpT> expr_type;
00288 
00289     /* Copy the UnaryMatrixOp expression by value into parent
00290      * expression tree nodes:
00291      */
00292     typedef expr_type expr_const_reference;
00293 
00294     typedef typename OpT::value_type value_type;
00295     typedef matrix_result_tag result_tag;
00296 
00297     /* For matching by assignability: */
00298     typedef cml::et::not_assignable_tag assignable_tag;
00299 
00300     /* Record the expression traits for the two subexpressions: */
00301     typedef ExprTraits<LeftT> left_traits;
00302     typedef ExprTraits<RightT> right_traits;
00303 
00304     /* Reference types for the two subexpressions: */
00305     typedef typename left_traits::const_reference left_reference;
00306     typedef typename right_traits::const_reference right_reference;
00307 
00308     /* Figure out the expression's resulting (matrix) type: */
00309     typedef typename left_traits::result_type left_result;
00310     typedef typename right_traits::result_type right_result;
00311     typedef typename MatrixPromote<left_result,right_result>::type result_type;
00312     typedef typename result_type::size_tag size_tag;
00313 
00314     /* Get the temporary type: */
00315     typedef typename result_type::temporary_type temporary_type;
00316 
00317     /* Define a size checker: */
00318     typedef GetCheckedSize<LeftT,RightT,size_tag> checked_size;
00319 
00320 
00321   public:
00322 
00327     enum {
00328         array_rows = result_type::array_rows,
00329         array_cols = result_type::array_cols
00330     };
00331 
00332 
00333   public:
00334 
00336     matrix_size size() const {
00337         return CheckedSize(m_left,m_right,size_tag());
00338     }
00339 
00346     size_t rows() const {
00347 #if defined(CML_CHECK_MATRIX_EXPR_SIZES)
00348         return this->size().first;
00349 #else
00350         return left_traits().rows(m_left);
00351 #endif
00352     }
00353 
00360     size_t cols() const {
00361 #if defined(CML_CHECK_MATRIX_EXPR_SIZES)
00362         return this->size().second;
00363 #else
00364         return right_traits().cols(m_right);
00365 #endif
00366     }
00367 
00369     value_type operator()(size_t i, size_t j) const {
00370 
00371         /* This uses the expression traits to figure out how to access the
00372          * i'th index of the two subexpressions:
00373          */
00374         return OpT().apply(
00375                 left_traits().get(m_left,i,j),
00376                 right_traits().get(m_right,i,j));
00377     }
00378 
00379 
00380   public:
00381 
00387     explicit BinaryMatrixOp(left_reference left, right_reference right)
00388         : m_left(left), m_right(right) {}
00389 
00391     BinaryMatrixOp(const expr_type& e)
00392         : m_left(e.m_left), m_right(e.m_right) {}
00393 
00394 
00395   protected:
00396 
00397     left_reference m_left;
00398     right_reference m_right;
00399 
00400 
00401   private:
00402 
00403     /* This ensures that a compile-time size check is executed: */
00404     typename checked_size::check_type _dummy;
00405 
00406 
00407   private:
00408 
00409     /* Cannot be assigned to: */
00410     expr_type& operator=(const expr_type&);
00411 };
00412 
00414 template<class LeftT, class RightT, class OpT>
00415 struct ExprTraits< BinaryMatrixOp<LeftT,RightT,OpT> >
00416 {
00417     typedef BinaryMatrixOp<LeftT,RightT,OpT> expr_type;
00418     typedef LeftT left_type;
00419     typedef RightT right_type;
00420 
00421     typedef typename expr_type::value_type value_type;
00422     typedef typename expr_type::expr_const_reference const_reference;
00423     typedef typename expr_type::result_tag result_tag;
00424     typedef typename expr_type::size_tag size_tag;
00425     typedef typename expr_type::result_type result_type;
00426     typedef typename expr_type::assignable_tag assignable_tag;
00427     typedef expr_node_tag node_tag;
00428 
00429     value_type get(const expr_type& e, size_t i, size_t j) const {
00430         return e(i,j);
00431     }
00432 
00433     matrix_size size(const expr_type& e) const { return e.size(); }
00434     size_t rows(const expr_type& e) const { return e.rows(); }
00435     size_t cols(const expr_type& e) const { return e.cols(); }
00436 };
00437 
00438 /* Helper struct to verify that both arguments are matrix expressions: */
00439 template<typename LeftTraits, typename RightTraits>
00440 struct MatrixExpressions
00441 {
00442     /* Require that both arguments are matrix expressions: */
00443     typedef typename LeftTraits::result_tag left_result;
00444     typedef typename RightTraits::result_tag right_result;
00445     enum { is_true = (same_type<left_result,et::matrix_result_tag>::is_true
00446             && same_type<right_result,et::matrix_result_tag>::is_true) };
00447 };
00448 
00449 namespace detail {
00450 
00451 /* XXX These are temporary helpers until dynamic resizing is integrated more
00452  * naturally into mul() and matrix transpose():
00453  */
00454 template<typename MatT, typename MT> inline
00455 void Resize(MatT&, size_t, size_t, fixed_size_tag, MT) {}
00456 
00457 template<typename MatT> inline
00458 void Resize(MatT& m,
00459         size_t R, size_t C, dynamic_size_tag, dynamic_memory_tag)
00460 {
00461     m.resize(R,C);
00462 }
00463 
00464 template<typename MatT> inline
00465 void Resize(MatT& m, size_t R, size_t C) {
00466     Resize(m, R, C, typename MatT::size_tag(), typename MatT::memory_tag());
00467 }
00468 
00469 template<typename MatT> inline
00470 void Resize(MatT& m, matrix_size N) {
00471     Resize(m, N.first, N.second,
00472             typename MatT::size_tag(), typename MatT::memory_tag());
00473 }
00474 
00475 } // namespace detail
00476 
00477 } // namespace et
00478 } // namespace cml
00479 
00480 #endif
00481 
00482 // -------------------------------------------------------------------------
00483 // vim:ft=cpp

Generated on Sat Jul 18 19:35:24 2009 for CML 1.0 by  doxygen 1.5.9