// Copyright (C) 2006 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_MATRIx_EXP_h_ #define DLIB_MATRIx_EXP_h_ #include "../algs.h" #include "../is_kind.h" #include "matrix_fwd.h" #include "matrix_exp_abstract.h" #include namespace dlib { // ---------------------------------------------------------------------------------------- // We want to return the compile time constant if our NR and NC dimensions // aren't zero but if they are then we want to call ref_.nx() and return // the correct values. template < typename exp_type, long NR > struct get_nr_helper { static inline long get(const exp_type&) { return NR; } }; template < typename exp_type > struct get_nr_helper { static inline long get(const exp_type& m) { return m.nr(); } }; template < typename exp_type, long NC > struct get_nc_helper { static inline long get(const exp_type&) { return NC; } }; template < typename exp_type > struct get_nc_helper { static inline long get(const exp_type& m) { return m.nc(); } }; template struct matrix_traits { typedef typename EXP::type type; typedef typename EXP::const_ret_type const_ret_type; typedef typename EXP::mem_manager_type mem_manager_type; typedef typename EXP::layout_type layout_type; const static long NR = EXP::NR; const static long NC = EXP::NC; const static long cost = EXP::cost; }; // ---------------------------------------------------------------------------------------- template class matrix_exp; template class matrix_exp_iterator : public std::iterator::type> { friend class matrix_exp; matrix_exp_iterator(const EXP& m_, long r_, long c_) { r = r_; c = c_; nc = m_.nc(); m = &m_; } public: matrix_exp_iterator() : r(0), c(0), nc(0), m(0) {} typedef typename matrix_traits::type type; typedef type value_type; typedef typename matrix_traits::const_ret_type const_ret_type; bool operator == ( const matrix_exp_iterator& itr) const { return r == itr.r && c == itr.c; } bool operator != ( const matrix_exp_iterator& itr) const { return !(*this == itr); } matrix_exp_iterator& operator++() { ++c; if (c==nc) { c = 0; ++r; } return *this; } matrix_exp_iterator operator++(int) { matrix_exp_iterator temp(*this); ++(*this); return temp; } const_ret_type operator* () const { return (*m)(r,c); } private: long r, c; long nc; const EXP* m; }; // ---------------------------------------------------------------------------------------- template < typename EXP > class matrix_exp { /*! REQUIREMENTS ON EXP EXP should be something convertible to a matrix_exp. That is, it should inherit from matrix_exp !*/ public: typedef typename matrix_traits::type type; typedef type value_type; typedef typename matrix_traits::const_ret_type const_ret_type; typedef typename matrix_traits::mem_manager_type mem_manager_type; typedef typename matrix_traits::layout_type layout_type; const static long NR = matrix_traits::NR; const static long NC = matrix_traits::NC; const static long cost = matrix_traits::cost; typedef matrix matrix_type; typedef EXP exp_type; typedef matrix_exp_iterator iterator; typedef matrix_exp_iterator const_iterator; inline const_ret_type operator() ( long r, long c ) const { DLIB_ASSERT(r < nr() && c < nc() && r >= 0 && c >= 0, "\tconst type matrix_exp::operator(r,c)" << "\n\tYou must give a valid row and column" << "\n\tr: " << r << "\n\tc: " << c << "\n\tnr(): " << nr() << "\n\tnc(): " << nc() << "\n\tthis: " << this ); return ref()(r,c); } const_ret_type operator() ( long i ) const { COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0); DLIB_ASSERT(nc() == 1 || nr() == 1, "\tconst type matrix_exp::operator(i)" << "\n\tYou can only use this operator on column or row vectors" << "\n\ti: " << i << "\n\tnr(): " << nr() << "\n\tnc(): " << nc() << "\n\tthis: " << this ); DLIB_ASSERT( ((nc() == 1 && i < nr()) || (nr() == 1 && i < nc())) && i >= 0, "\tconst type matrix_exp::operator(i)" << "\n\tYou must give a valid row/column number" << "\n\ti: " << i << "\n\tnr(): " << nr() << "\n\tnc(): " << nc() << "\n\tthis: " << this ); if (nc() == 1) return ref()(i,0); else return ref()(0,i); } long size ( ) const { return nr()*nc(); } long nr ( ) const { return get_nr_helper::get(ref()); } long nc ( ) const { return get_nc_helper::get(ref()); } template bool aliases ( const matrix_exp& item ) const { return ref().aliases(item); } template bool destructively_aliases ( const matrix_exp& item ) const { return ref().destructively_aliases(item); } inline const exp_type& ref ( ) const { return *static_cast(this); } inline operator const type ( ) const { COMPILE_TIME_ASSERT(NC == 1 || NC == 0); COMPILE_TIME_ASSERT(NR == 1 || NR == 0); DLIB_ASSERT(nr() == 1 && nc() == 1, "\tmatrix_exp::operator const type() const" << "\n\tYou can only use this operator on a 1x1 matrix" << "\n\tnr(): " << nr() << "\n\tnc(): " << nc() << "\n\tthis: " << this ); // Put the expression contained in this matrix_exp into // a temporary 1x1 matrix so that the expression will encounter // all the overloads of matrix_assign() and have the chance to // go through any applicable optimizations. matrix temp(ref()); return temp(0); } const_iterator begin() const { return matrix_exp_iterator(ref(),0,0); } const_iterator end() const { return matrix_exp_iterator(ref(),nr(),0); } protected: matrix_exp() {} matrix_exp(const matrix_exp& ) {} private: matrix_exp& operator= (const matrix_exp&); }; // ---------------------------------------------------------------------------------------- // something is a matrix if it is convertible to a matrix_exp object template struct is_matrix& > >::type > { static const bool value = true; }; /* is_matrix::value == 1 if T is a matrix type else 0 */ // ---------------------------------------------------------------------------------------- template < typename EXP > class matrix_diag_exp : public matrix_exp { /*! This is a matrix expression type used to represent diagonal matrices. That is, square matrices with all off diagonal elements equal to 0. !*/ protected: matrix_diag_exp() {} matrix_diag_exp(const matrix_diag_exp& item ):matrix_exp(item) {} }; // ---------------------------------------------------------------------------------------- } #endif // DLIB_MATRIx_EXP_h_