// Copyright (C) 2006 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_MATRIx_MAT_Hh_ #define DLIB_MATRIx_MAT_Hh_ #include "matrix_mat_abstract.h" #include "../stl_checked.h" #include #include "matrix_op.h" #include "../array2d.h" #include "../array.h" #include "../image_processing/generic_image.h" namespace dlib { // ---------------------------------------------------------------------------------------- template < typename EXP > const matrix_exp& mat ( const matrix_exp& m ) { return m; } // ---------------------------------------------------------------------------------------- template struct op_image_to_mat : does_not_alias { op_image_to_mat( const image_type& img) : imgview(img){} const_image_view imgview; const static long cost = 1; const static long NR = 0; const static long NC = 0; typedef pixel_type type; typedef const pixel_type& const_ret_type; typedef default_memory_manager mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long c ) const { return imgview[r][c]; } long nr () const { return imgview.nr(); } long nc () const { return imgview.nc(); } }; // ---------------------------------------------------------------------------------------- template < typename image_type > // The reason we disable this if it is a matrix is because this matrix_op claims // to not alias any matrix. But obviously that would be a problem if we let it // take a matrix. const typename disable_if,matrix_op::pixel_type> > >::type mat ( const image_type& img ) { typedef op_image_to_mat::pixel_type> op; return matrix_op(op(img)); } // ---------------------------------------------------------------------------------------- template struct op_image_view_to_mat : does_not_alias { op_image_view_to_mat( const image_view& img) : imgview(img){} typedef typename image_traits::pixel_type pixel_type; const image_view& imgview; const static long cost = 1; const static long NR = 0; const static long NC = 0; typedef pixel_type type; typedef const pixel_type& const_ret_type; typedef default_memory_manager mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long c ) const { return imgview[r][c]; } long nr () const { return imgview.nr(); } long nc () const { return imgview.nc(); } }; template < typename image_type > const matrix_op > mat ( const image_view& img ) { typedef op_image_view_to_mat op; return matrix_op(op(img)); } // ---------------------------------------------------------------------------------------- template struct op_const_image_view_to_mat : does_not_alias { op_const_image_view_to_mat( const const_image_view& img) : imgview(img){} typedef typename image_traits::pixel_type pixel_type; const const_image_view& imgview; const static long cost = 1; const static long NR = 0; const static long NC = 0; typedef pixel_type type; typedef const pixel_type& const_ret_type; typedef default_memory_manager mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long c ) const { return imgview[r][c]; } long nr () const { return imgview.nr(); } long nc () const { return imgview.nc(); } }; template < typename image_type > const matrix_op > mat ( const const_image_view& img ) { typedef op_const_image_view_to_mat op; return matrix_op(op(img)); } // ---------------------------------------------------------------------------------------- template struct op_array_to_mat : does_not_alias { op_array_to_mat( const T& vect_) : vect(vect_){} const T& vect; const static long cost = 1; const static long NR = 0; const static long NC = 1; typedef typename T::type type; typedef const typename T::type& const_ret_type; typedef typename T::mem_manager_type mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long ) const { return vect[r]; } long nr () const { return vect.size(); } long nc () const { return 1; } }; // ---------------------------------------------------------------------------------------- template < typename T, typename MM > const matrix_op > > mat ( const array& m ) { typedef op_array_to_mat > op; return matrix_op(op(m)); } // ---------------------------------------------------------------------------------------- namespace impl { template struct not_bool { typedef U type; }; template <> struct not_bool { typedef bool type; }; } template struct op_std_vect_to_mat : does_not_alias { op_std_vect_to_mat( const T& vect_) : vect(vect_){} const T& vect; const static long cost = 1; const static long NR = 0; const static long NC = 1; typedef typename T::value_type type; // Since std::vector returns a proxy for bool types we need to make sure we don't // return an element by reference if it is a bool type. typedef typename impl::not_bool::type const_ret_type; typedef default_memory_manager mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long ) const { return vect[r]; } long nr () const { return vect.size(); } long nc () const { return 1; } }; // ---------------------------------------------------------------------------------------- template < typename value_type, typename alloc > const matrix_op > > mat ( const std::vector& vector ) { typedef op_std_vect_to_mat > op; return matrix_op(op(vector)); } // ---------------------------------------------------------------------------------------- template < typename value_type, typename alloc > const matrix_op > > mat ( const std_vector_c& vector ) { typedef op_std_vect_to_mat > op; return matrix_op(op(vector)); } // ---------------------------------------------------------------------------------------- template struct op_pointer_to_mat; template struct op_pointer_to_col_vect { op_pointer_to_col_vect( const T* ptr_, const long size_ ) : ptr(ptr_), size(size_){} const T* ptr; const long size; const static long cost = 1; const static long NR = 0; const static long NC = 1; typedef T type; typedef const T& const_ret_type; typedef default_memory_manager mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long ) const { return ptr[r]; } long nr () const { return size; } long nc () const { return 1; } template bool aliases ( const matrix_exp& ) const { return false; } template bool destructively_aliases ( const matrix_exp& ) const { return false; } template bool aliases ( const matrix_exp >& item ) const { if (item.size() == 0) return false; else return (ptr == &item(0,0)); } inline bool aliases ( const matrix_exp > >& item ) const; bool aliases ( const matrix_exp > >& item ) const { return item.ref().op.ptr == ptr; } }; // ---------------------------------------------------------------------------------------- template < typename T > const matrix_op > mat ( const T* ptr, long nr ) { DLIB_ASSERT(nr >= 0 , "\tconst matrix_exp mat(ptr, nr)" << "\n\t nr must be >= 0" << "\n\t nr: " << nr ); typedef op_pointer_to_col_vect op; return matrix_op(op(ptr, nr)); } // ---------------------------------------------------------------------------------------- template struct op_pointer_to_mat { op_pointer_to_mat( const T* ptr_, const long nr_, const long nc_ ) : ptr(ptr_), rows(nr_), cols(nc_){} const T* ptr; const long rows; const long cols; const static long cost = 1; const static long NR = 0; const static long NC = 0; typedef T type; typedef const T& const_ret_type; typedef default_memory_manager mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long c) const { return ptr[r*cols + c]; } long nr () const { return rows; } long nc () const { return cols; } template bool aliases ( const matrix_exp& ) const { return false; } template bool destructively_aliases ( const matrix_exp& ) const { return false; } template bool aliases ( const matrix_exp >& item ) const { if (item.size() == 0) return false; else return (ptr == &item(0,0)); } bool aliases ( const matrix_exp > >& item ) const { return item.ref().op.ptr == ptr; } bool aliases ( const matrix_exp > >& item ) const { return item.ref().op.ptr == ptr; } }; template bool op_pointer_to_col_vect:: aliases ( const matrix_exp > >& item ) const { return item.ref().op.ptr == ptr; } template bool matrix::aliases ( const matrix_exp > >& item ) const { if (size() != 0) return item.ref().op.ptr == &data(0,0); else return false; } template bool matrix::aliases ( const matrix_exp > >& item ) const { if (size() != 0) return item.ref().op.ptr == &data(0,0); else return false; } // ---------------------------------------------------------------------------------------- template < typename T > const matrix_op > mat ( const T* ptr, long nr, long nc ) { DLIB_ASSERT(nr >= 0 && nc >= 0 , "\tconst matrix_exp mat(ptr, nr, nc)" << "\n\t nr and nc must be >= 0" << "\n\t nr: " << nr << "\n\t nc: " << nc ); typedef op_pointer_to_mat op; return matrix_op(op(ptr,nr,nc)); } // ---------------------------------------------------------------------------------------- } namespace arma { template class Mat; } namespace dlib { template struct op_arma_Mat_to_mat : does_not_alias { op_arma_Mat_to_mat( const T& array_) : array(array_){} const T& array; const static long cost = 1; const static long NR = 0; const static long NC = 0; typedef typename T::elem_type type; typedef typename T::elem_type const_ret_type; typedef default_memory_manager mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long c ) const { return array(r,c); } long nr () const { return array.n_rows; } long nc () const { return array.n_cols; } }; // ---------------------------------------------------------------------------------------- template < typename T > const matrix_op > > mat ( const ::arma::Mat& array ) { typedef op_arma_Mat_to_mat< ::arma::Mat > op; return matrix_op(op(array)); } } namespace Eigen { template class Matrix; } namespace dlib { template struct op_eigen_Matrix_to_mat : does_not_alias { op_eigen_Matrix_to_mat( const T& array_) : m(array_){} const T& m; const static long cost = 1; const static long NR = (_Rows > 0) ? _Rows : 0; const static long NC = (_Cols > 0) ? _Cols : 0; typedef typename T::Scalar type; typedef typename T::Scalar const_ret_type; typedef default_memory_manager mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long c ) const { return m(r,c); } long nr () const { return m.rows(); } long nc () const { return m.cols(); } }; // ---------------------------------------------------------------------------------------- template < typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols > const matrix_op,_Rows,_Cols > > mat ( const ::Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>& m ) { typedef op_eigen_Matrix_to_mat< ::Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>,_Rows,_Cols > op; return matrix_op(op(m)); } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // DEPRECATED FUNCTIONS // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // vector_to_matrix(), array_to_matrix(), pointer_to_matrix(), and // pointer_to_column_vector() have been deprecated in favor of the more uniform mat() // function. But they are here for backwards compatibility. template < typename vector_type > const typename disable_if, matrix_op > >::type vector_to_matrix ( const vector_type& vector ) { typedef op_array_to_mat op; return matrix_op(op(vector)); } template < typename vector_type > const typename enable_if,vector_type>::type& vector_to_matrix ( const vector_type& vector ) /*! This overload catches the case where the argument to this function is already a matrix. !*/ { return vector; } template < typename value_type, typename alloc > const matrix_op > > vector_to_matrix ( const std::vector& vector ) { typedef op_std_vect_to_mat > op; return matrix_op(op(vector)); } template < typename value_type, typename alloc > const matrix_op > > vector_to_matrix ( const std_vector_c& vector ) { typedef op_std_vect_to_mat > op; return matrix_op(op(vector)); } // ---------------------------------------------------------------------------------------- template < typename array_type > const typename enable_if,array_type>::type& array_to_matrix ( const array_type& array ) { return array; } // ---------------------------------------------------------------------------------------- template struct op_array2d_to_mat : does_not_alias { op_array2d_to_mat( const T& array_) : array(array_){} const T& array; const static long cost = 1; const static long NR = 0; const static long NC = 0; typedef typename T::type type; typedef const typename T::type& const_ret_type; typedef typename T::mem_manager_type mem_manager_type; typedef row_major_layout layout_type; const_ret_type apply (long r, long c ) const { return array[r][c]; } long nr () const { return array.nr(); } long nc () const { return array.nc(); } }; // Note that we have this version of mat() because it's slightly faster executing // than the general one that handles any generic image. This is because it avoids // calling image_data() which for array2d involves a single if statement but this // version here has no if statement in its construction. template < typename T, typename MM > const matrix_op > > mat ( const array2d& array ) { typedef op_array2d_to_mat > op; return matrix_op(op(array)); } template < typename array_type > const typename disable_if,matrix_op > >::type array_to_matrix ( const array_type& array ) { typedef op_array2d_to_mat op; return matrix_op(op(array)); } // ---------------------------------------------------------------------------------------- template < typename T > const matrix_op > pointer_to_matrix ( const T* ptr, long nr, long nc ) { DLIB_ASSERT(nr > 0 && nc > 0 , "\tconst matrix_exp pointer_to_matrix(ptr, nr, nc)" << "\n\t nr and nc must be bigger than 0" << "\n\t nr: " << nr << "\n\t nc: " << nc ); typedef op_pointer_to_mat op; return matrix_op(op(ptr,nr,nc)); } template < typename T > const matrix_op > pointer_to_column_vector ( const T* ptr, long nr ) { DLIB_ASSERT(nr > 0 , "\tconst matrix_exp pointer_to_column_vector(ptr, nr)" << "\n\t nr must be bigger than 0" << "\n\t nr: " << nr ); typedef op_pointer_to_col_vect op; return matrix_op(op(ptr, nr)); } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- inline matrix mat ( double value ) { matrix temp; temp(0) = value; return temp; } inline matrix mat ( float value ) { matrix temp; temp(0) = value; return temp; } inline matrix mat ( long double value ) { matrix temp; temp(0) = value; return temp; } // ---------------------------------------------------------------------------------------- } #endif // DLIB_MATRIx_MAT_Hh_