Commit 2183d6fe authored by Davis King's avatar Davis King

- Fixed a bug in scale_columns. It said it didn't have any destructive aliasing when in fact it

   destructively aliased its second argument.
 - Moved matrix_exp into its own file
 - Removed all the operator templated matrix expression classes from matrix_expressions.h
   and replaced them with a single (much simpler) class called matrix_op.  This new
   class is located in matrix_op.h.   Virtually all the code changes in this commit are just
   the refactoring needed to support this change.  No functionality has been changed.  I just
   did this because it makes the code a lot simpler.
 - Simplified the code for the kernel_matrix() function.  I also made it a little more
   general.  So it should now support just about any possible combination of arguments
   that makes any kind of sense for creating a kernel matrix.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%403705
parent 31785ca3
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#ifndef DLIB_MATRIx_ #ifndef DLIB_MATRIx_
#define DLIB_MATRIx_ #define DLIB_MATRIx_
#include "matrix_fwd.h" #include "matrix_exp.h"
#include "matrix_abstract.h" #include "matrix_abstract.h"
#include "../algs.h" #include "../algs.h"
#include "../serialize.h" #include "../serialize.h"
...@@ -29,178 +29,6 @@ ...@@ -29,178 +29,6 @@
namespace dlib 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<exp_type,0>
{
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<exp_type,0>
{
static inline long get(const exp_type& m) { return m.nc(); }
};
template <typename EXP>
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 <
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<EXP>::type type;
typedef typename matrix_traits<EXP>::const_ret_type const_ret_type;
typedef typename matrix_traits<EXP>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<EXP>::layout_type layout_type;
const static long NR = matrix_traits<EXP>::NR;
const static long NC = matrix_traits<EXP>::NC;
const static long cost = matrix_traits<EXP>::cost;
typedef matrix<type,NR,NC,mem_manager_type,layout_type> matrix_type;
typedef EXP exp_type;
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<exp_type,NR>::get(ref()); }
long nc (
) const { return get_nc_helper<exp_type,NC>::get(ref()); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return ref().aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return ref().destructively_aliases(item); }
inline const exp_type& ref (
) const { return *static_cast<const exp_type*>(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<type,1,1,mem_manager_type,layout_type> temp(ref());
return temp(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 <typename T>
struct is_matrix<T, typename enable_if<is_convertible<T, const matrix_exp<typename T::exp_type>& > >::type >
{ static const bool value = true; };
/*
is_matrix<T>::value == 1 if T is a matrix type else 0
*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// This template will perform the needed loop for element multiplication using whichever // This template will perform the needed loop for element multiplication using whichever
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#undef DLIB_MATRIx_ABSTRACT_ #undef DLIB_MATRIx_ABSTRACT_
#ifdef DLIB_MATRIx_ABSTRACT_ #ifdef DLIB_MATRIx_ABSTRACT_
#include "matrix_exp_abstract.h"
#include "../serialize.h" #include "../serialize.h"
#include "../memory_manager.h" #include "../memory_manager.h"
#include "matrix_data_layout_abstract.h" #include "matrix_data_layout_abstract.h"
...@@ -10,186 +11,6 @@ ...@@ -10,186 +11,6 @@
namespace dlib namespace dlib
{ {
// ----------------------------------------------------------------------------------------
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager,
typename layout
>
class matrix;
// ----------------------------------------------------------------------------------------
template <
typename EXP
>
class matrix_exp
{
/*!
REQUIREMENTS ON EXP
- must be an object that inherits publicly from matrix_exp (this class).
WHAT THIS OBJECT REPRESENTS
This object represents an expression that evaluates to a matrix
of nr() rows and nc() columns.
The reason for having an object that represents an expression is that it
allows us to use the "expression templates" technique to eliminate the
temporary matrix objects that would normally be returned from expressions
such as M = A+B+C+D; Normally each invocation of the + operator would
construct and return a temporary matrix object but using this technique we
can avoid creating all of these temporary objects and receive a large
speed boost.
Note that every time you invoke operator() on this object it recomputes
its result which may not be what you want to do. For example, if you
are going to be accessing the same element over and over it might
be faster to assign the matrix_exp to a temporary matrix and then
use that temporary.
const_ret_type typedef (defined below)
The purpose of the const_ret_type typedef is to allow matrix expressions
to return their elements by reference when appropriate. So const_ret_type
should be one of the following types:
- const type
- const type&
!*/
public:
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 cost = EXP::cost;
const static long NR = EXP::NR;
const static long NC = EXP::NC;
typedef matrix<type,NR,NC, mem_manager_type,layout_type> matrix_type;
typedef EXP exp_type;
const_ret_type operator() (
long r,
long c
) const;
/*!
requires
- 0 <= r < nr()
- 0 <= c < nc()
ensures
- returns ref()(r,c)
(i.e. returns the value at the given row and column that would be in
the matrix represented by this matrix expression)
!*/
const_ret_type operator() (
long i
) const;
/*!
requires
- nc() == 1 || nr() == 1 (i.e. this must be a column or row vector)
- if (nc() == 1) then
- 0 <= i < nr()
- else
- 0 <= i < nc()
ensures
- if (nc() == 1) then
- returns (*this)(i,0)
- else
- returns (*this)(0,i)
!*/
operator const type (
) const;
/*!
requires
- nr() == 1
- nc() == 1
ensures
- returns (*this)(0,0)
!*/
long nr (
) const;
/*!
ensures
- returns the number of rows in this matrix expression.
!*/
long nc (
) const;
/*!
ensures
- returns the number of columns in this matrix expression.
!*/
long size (
) const;
/*!
ensures
- returns nr()*nc()
!*/
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const;
/*!
ensures
- if (A change to the state of item could cause a change to the state of *this
matrix_exp object. ) then
- returns true
- This happens when this matrix_exp contains item in some way.
- else
- returns false
!*/
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const;
/*!
ensures
- if (aliases(item)) then
- if (nr() != item.nr() || nc() != item.nc()
- returns true
(i.e. if this expression has different dimensions than item then
we have destructive aliasing)
- returns true if the following assignment would evaluate incorrectly:
for (long r = 0; r < nr(); ++r)
for (long c = 0; c < nc(); ++c)
item(r,c) = (*this)(r,c)
- That is, if this matrix expression aliases item in such a way that a modification
to element item(r,c) causes a change in the value of something other than
(*this)(r,c) then this function returns true.
- returns false if none of the above conditions say we should return true
- else
- returns false
!*/
inline const exp_type& ref (
) const;
/*!
ensures
- returns a reference to the expression contained in *this.
(i.e. returns *static_cast<const exp_type*>(this) )
!*/
protected:
// Only derived classes of matrix_exp may call the matrix_exp constructors.
matrix_exp(const matrix_exp&);
matrix_exp();
private:
// no one may ever use the assignment operator on a matrix_exp
matrix_exp& operator= (const matrix_exp&);
};
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
/* /*
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "../enable_if.h" #include "../enable_if.h"
#include "matrix_assign_fwd.h" #include "matrix_assign_fwd.h"
#include "matrix_default_mul.h" #include "matrix_default_mul.h"
#include "matrix_conj_trans.h"
namespace dlib namespace dlib
{ {
...@@ -70,8 +71,20 @@ namespace dlib ...@@ -70,8 +71,20 @@ namespace dlib
struct has_matrix_multiply<matrix_div_scal_exp<T> > struct has_matrix_multiply<matrix_div_scal_exp<T> >
{ const static bool value = has_matrix_multiply<T>::value; }; { const static bool value = has_matrix_multiply<T>::value; };
template <typename T, typename OP> template <typename T>
struct has_matrix_multiply<matrix_unary_exp<T,OP> > struct has_matrix_multiply<matrix_op<T> >
{ const static bool value = has_matrix_multiply<T>::value; };
template <typename T>
struct has_matrix_multiply<op_trans<T> >
{ const static bool value = has_matrix_multiply<T>::value; };
template <typename T>
struct has_matrix_multiply<op_conj_trans<T> >
{ const static bool value = has_matrix_multiply<T>::value; };
template <typename T>
struct has_matrix_multiply<op_conj<T> >
{ const static bool value = has_matrix_multiply<T>::value; }; { const static bool value = has_matrix_multiply<T>::value; };
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
...@@ -112,31 +125,31 @@ namespace dlib ...@@ -112,31 +125,31 @@ namespace dlib
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_scalar_binary_exp<matrix<T,NR,NC,MM,L>,long,op_colm> > struct matrix_type_id<matrix_op<op_colm<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = column_matrix; const static int value = column_matrix;
}; };
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_scalar_binary_exp<matrix<T,NR,NC,MM,L>,long,op_rowm> > struct matrix_type_id<matrix_op<op_rowm<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = row_matrix; const static int value = row_matrix;
}; };
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,L>,long,op_colm2> > struct matrix_type_id<matrix_op<op_colm2<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = column_matrix; const static int value = column_matrix;
}; };
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,L>,long,op_rowm2> > struct matrix_type_id<matrix_op<op_rowm2<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = row_matrix; const static int value = row_matrix;
}; };
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_sub_exp<matrix<T,NR,NC,MM,L> > > struct matrix_type_id<matrix_op<op_subm<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = general_matrix; const static int value = general_matrix;
}; };
...@@ -215,8 +228,16 @@ namespace dlib ...@@ -215,8 +228,16 @@ namespace dlib
struct same_exp<matrix_div_scal_exp<T>, matrix_div_scal_exp<U>, layout > struct same_exp<matrix_div_scal_exp<T>, matrix_div_scal_exp<U>, layout >
{ const static bool value = same_exp<T,U,layout>::value; }; { const static bool value = same_exp<T,U,layout>::value; };
template <typename T, typename U, typename OP, typename layout> template <typename T, typename U, typename layout>
struct same_exp<matrix_unary_exp<T,OP>, matrix_unary_exp<U,OP>, layout > struct same_exp<matrix_op<op_trans<T> >, matrix_op<op_trans<U> >, layout >
{ const static bool value = same_exp<T,U,layout>::value; };
template <typename T, typename U, typename layout>
struct same_exp<matrix_op<op_conj<T> >, matrix_op<op_conj<U> >, layout >
{ const static bool value = same_exp<T,U,layout>::value; };
template <typename T, typename U, typename layout>
struct same_exp<matrix_op<op_conj_trans<T> >, matrix_op<op_conj_trans<U> >, layout >
{ const static bool value = same_exp<T,U,layout>::value; }; { const static bool value = same_exp<T,U,layout>::value; };
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
...@@ -410,7 +431,7 @@ namespace dlib ...@@ -410,7 +431,7 @@ namespace dlib
> >
void matrix_assign_blas_proxy ( void matrix_assign_blas_proxy (
dest_exp& dest, dest_exp& dest,
const matrix_unary_exp<src_exp,op_trans>& src, const matrix_op<op_trans<src_exp> >& src,
typename src_exp::type alpha, typename src_exp::type alpha,
bool add_to, bool add_to,
bool transpose bool transpose
...@@ -574,13 +595,13 @@ namespace dlib ...@@ -574,13 +595,13 @@ namespace dlib
> >
void matrix_assign_blas_proxy ( void matrix_assign_blas_proxy (
dest_exp& dest, dest_exp& dest,
const matrix_unary_exp<src_exp,op_trans>& src, const matrix_op<op_trans<src_exp> >& src,
typename src_exp::type alpha, typename src_exp::type alpha,
bool add_to, bool add_to,
bool transpose bool transpose
) )
{ {
matrix_assign_blas_proxy(dest, src.m, alpha, add_to, !transpose); matrix_assign_blas_proxy(dest, src.op.m, alpha, add_to, !transpose);
} }
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
......
...@@ -323,10 +323,10 @@ namespace dlib ...@@ -323,10 +323,10 @@ namespace dlib
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_ld (const matrix_sub_exp<matrix<T,NR,NC,MM,row_major_layout> >& m) { return m.m.nc(); } int get_ld (const matrix_op<op_subm<matrix<T,NR,NC,MM,row_major_layout> > >& m) { return m.op.m.nc(); }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_ld (const matrix_sub_exp<matrix<T,NR,NC,MM,column_major_layout> >& m) { return m.m.nr(); } int get_ld (const matrix_op<op_subm<matrix<T,NR,NC,MM,column_major_layout> > >& m) { return m.op.m.nr(); }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_ld (const assignable_sub_matrix<T,NR,NC,MM,row_major_layout>& m) { return m.m.nc(); } int get_ld (const assignable_sub_matrix<T,NR,NC,MM,row_major_layout>& m) { return m.m.nc(); }
...@@ -340,25 +340,25 @@ namespace dlib ...@@ -340,25 +340,25 @@ namespace dlib
int get_inc (const matrix<T,NR,NC,MM,L>& ) { return 1; } int get_inc (const matrix<T,NR,NC,MM,L>& ) { return 1; }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_inc(const matrix_scalar_binary_exp<matrix<T,NR,NC,MM,row_major_layout>,long,op_colm>& m) int get_inc(const matrix_op<op_colm<matrix<T,NR,NC,MM,row_major_layout> > >& m)
{ {
return m.m.nc(); return m.op.m.nc();
} }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_inc(const matrix_scalar_binary_exp<matrix<T,NR,NC,MM,row_major_layout>,long,op_rowm>& ) int get_inc(const matrix_op<op_rowm<matrix<T,NR,NC,MM,row_major_layout> > >& )
{ {
return 1; return 1;
} }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_inc(const matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,row_major_layout>,long,op_colm2>& m) int get_inc(const matrix_op<op_colm2<matrix<T,NR,NC,MM,row_major_layout> > >& m)
{ {
return m.m.nc(); return m.op.m.nc();
} }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_inc(const matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,row_major_layout>,long,op_rowm2>& ) int get_inc(const matrix_op<op_rowm2<matrix<T,NR,NC,MM,row_major_layout> > >& )
{ {
return 1; return 1;
} }
...@@ -366,27 +366,27 @@ namespace dlib ...@@ -366,27 +366,27 @@ namespace dlib
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_inc(const matrix_scalar_binary_exp<matrix<T,NR,NC,MM,column_major_layout>,long,op_colm>& ) int get_inc(const matrix_op<op_colm<matrix<T,NR,NC,MM,column_major_layout> > >& )
{ {
return 1; return 1;
} }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_inc(const matrix_scalar_binary_exp<matrix<T,NR,NC,MM,column_major_layout>,long,op_rowm>& m) int get_inc(const matrix_op<op_rowm<matrix<T,NR,NC,MM,column_major_layout> > >& m)
{ {
return m.m.nr(); return m.op.m.nr();
} }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_inc(const matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,column_major_layout>,long,op_colm2>& ) int get_inc(const matrix_op<op_colm2<matrix<T,NR,NC,MM,column_major_layout> > >& )
{ {
return 1; return 1;
} }
template <typename T, long NR, long NC, typename MM> template <typename T, long NR, long NC, typename MM>
int get_inc(const matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,column_major_layout>,long,op_rowm2>& m) int get_inc(const matrix_op<op_rowm2<matrix<T,NR,NC,MM,column_major_layout> > >& m)
{ {
return m.m.nr(); return m.op.m.nr();
} }
...@@ -424,19 +424,19 @@ namespace dlib ...@@ -424,19 +424,19 @@ namespace dlib
T* get_ptr (matrix<T,NR,NC,MM,L>& m) { return &m(0,0); } T* get_ptr (matrix<T,NR,NC,MM,L>& m) { return &m(0,0); }
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
const T* get_ptr (const matrix_sub_exp<matrix<T,NR,NC,MM,L> >& m) { return &m.m(m.r_,m.c_); } const T* get_ptr (const matrix_op<op_subm<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(m.r_,m.c_); }
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
const T* get_ptr (const matrix_scalar_binary_exp<matrix<T,NR,NC,MM,L>,long,op_colm>& m) { return &m.m(0,m.s); } const T* get_ptr (const matrix_op<op_colm<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(0,m.op.col); }
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
const T* get_ptr (const matrix_scalar_binary_exp<matrix<T,NR,NC,MM,L>,long,op_rowm>& m) { return &m.m(m.s,0); } const T* get_ptr (const matrix_op<op_rowm<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(m.op.row,0); }
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
const T* get_ptr (const matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,L>,long,op_colm2>& m) { return &m.m(0,m.s1); } const T* get_ptr (const matrix_op<op_colm2<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(0,m.op.col); }
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
const T* get_ptr (const matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,L>,long,op_rowm2>& m) { return &m.m(m.s1,0); } const T* get_ptr (const matrix_op<op_rowm2<matrix<T,NR,NC,MM,L> > >& m) { return &m.op.m(m.op.row,0); }
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
...@@ -504,8 +504,8 @@ namespace dlib ...@@ -504,8 +504,8 @@ namespace dlib
const int M = static_cast<int>(src.nr()); const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc()); const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc()); const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs); const T* B = get_ptr(src.rhs);
const int ldb = get_ld(src.rhs); const int ldb = get_ld(src.rhs);
...@@ -534,8 +534,8 @@ namespace dlib ...@@ -534,8 +534,8 @@ namespace dlib
const int K = static_cast<int>(src.lhs.nc()); const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs); const T* A = get_ptr(src.lhs);
const int lda = get_ld(src.lhs); const int lda = get_ld(src.lhs);
const T* B = get_ptr(src.rhs.m); const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.m); const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest); T* C = get_ptr(dest);
...@@ -558,10 +558,10 @@ namespace dlib ...@@ -558,10 +558,10 @@ namespace dlib
const int M = static_cast<int>(src.nr()); const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc()); const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc()); const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs.m); const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.m); const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest); T* C = get_ptr(dest);
...@@ -587,8 +587,8 @@ namespace dlib ...@@ -587,8 +587,8 @@ namespace dlib
const int M = static_cast<int>(src.nr()); const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc()); const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc()); const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs); const T* B = get_ptr(src.rhs);
const int ldb = get_ld(src.rhs); const int ldb = get_ld(src.rhs);
...@@ -615,10 +615,10 @@ namespace dlib ...@@ -615,10 +615,10 @@ namespace dlib
const int M = static_cast<int>(src.nr()); const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc()); const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc()); const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs.m); const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.m); const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest); T* C = get_ptr(dest);
...@@ -645,8 +645,8 @@ namespace dlib ...@@ -645,8 +645,8 @@ namespace dlib
const int K = static_cast<int>(src.lhs.nc()); const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs); const T* A = get_ptr(src.lhs);
const int lda = get_ld(src.lhs); const int lda = get_ld(src.lhs);
const T* B = get_ptr(src.rhs.m); const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.m); const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest); T* C = get_ptr(dest);
...@@ -669,10 +669,10 @@ namespace dlib ...@@ -669,10 +669,10 @@ namespace dlib
const int M = static_cast<int>(src.nr()); const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc()); const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc()); const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs.m); const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.m); const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest); T* C = get_ptr(dest);
...@@ -696,10 +696,10 @@ namespace dlib ...@@ -696,10 +696,10 @@ namespace dlib
const int M = static_cast<int>(src.nr()); const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc()); const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc()); const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs.m); const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.m); const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest); T* C = get_ptr(dest);
...@@ -775,8 +775,8 @@ namespace dlib ...@@ -775,8 +775,8 @@ namespace dlib
const int N = static_cast<int>(src.rhs.nc()); const int N = static_cast<int>(src.rhs.nc());
const T* A = get_ptr(src.rhs); const T* A = get_ptr(src.rhs);
const int lda = get_ld(src.rhs); const int lda = get_ld(src.rhs);
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest); T* Y = get_ptr(dest);
...@@ -797,8 +797,8 @@ namespace dlib ...@@ -797,8 +797,8 @@ namespace dlib
const int N = static_cast<int>(src.lhs.nc()); const int N = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs); const T* A = get_ptr(src.lhs);
const int lda = get_ld(src.lhs); const int lda = get_ld(src.lhs);
const T* X = get_ptr(src.rhs.m); const T* X = get_ptr(src.rhs.op.m);
const int incX = get_inc(src.rhs.m); const int incX = get_inc(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest); T* Y = get_ptr(dest);
...@@ -817,10 +817,10 @@ namespace dlib ...@@ -817,10 +817,10 @@ namespace dlib
const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value;
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasTrans; const CBLAS_TRANSPOSE TransA = CblasTrans;
const int M = static_cast<int>(src.lhs.m.nr()); const int M = static_cast<int>(src.lhs.op.m.nr());
const int N = static_cast<int>(src.lhs.m.nc()); const int N = static_cast<int>(src.lhs.op.m.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* X = get_ptr(src.rhs); const T* X = get_ptr(src.rhs);
const int incX = get_inc(src.rhs); const int incX = get_inc(src.rhs);
...@@ -841,10 +841,10 @@ namespace dlib ...@@ -841,10 +841,10 @@ namespace dlib
const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value;
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasNoTrans; const CBLAS_TRANSPOSE TransA = CblasNoTrans;
const int M = static_cast<int>(src.rhs.m.nr()); const int M = static_cast<int>(src.rhs.op.m.nr());
const int N = static_cast<int>(src.rhs.m.nc()); const int N = static_cast<int>(src.rhs.op.m.nc());
const T* A = get_ptr(src.rhs.m); const T* A = get_ptr(src.rhs.op.m);
const int lda = get_ld(src.rhs.m); const int lda = get_ld(src.rhs.op.m);
const T* X = get_ptr(src.lhs); const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs); const int incX = get_inc(src.lhs);
...@@ -865,12 +865,12 @@ namespace dlib ...@@ -865,12 +865,12 @@ namespace dlib
const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value;
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasNoTrans; const CBLAS_TRANSPOSE TransA = CblasNoTrans;
const int M = static_cast<int>(src.rhs.m.nr()); const int M = static_cast<int>(src.rhs.op.m.nr());
const int N = static_cast<int>(src.rhs.m.nc()); const int N = static_cast<int>(src.rhs.op.m.nc());
const T* A = get_ptr(src.rhs.m); const T* A = get_ptr(src.rhs.op.m);
const int lda = get_ld(src.rhs.m); const int lda = get_ld(src.rhs.op.m);
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest); T* Y = get_ptr(dest);
...@@ -887,12 +887,12 @@ namespace dlib ...@@ -887,12 +887,12 @@ namespace dlib
const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value;
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasTrans; const CBLAS_TRANSPOSE TransA = CblasTrans;
const int M = static_cast<int>(src.lhs.m.nr()); const int M = static_cast<int>(src.lhs.op.m.nr());
const int N = static_cast<int>(src.lhs.m.nc()); const int N = static_cast<int>(src.lhs.op.m.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* X = get_ptr(src.rhs.m); const T* X = get_ptr(src.rhs.op.m);
const int incX = get_inc(src.rhs.m); const int incX = get_inc(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest); T* Y = get_ptr(dest);
...@@ -912,12 +912,12 @@ namespace dlib ...@@ -912,12 +912,12 @@ namespace dlib
const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value;
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasConjTrans; const CBLAS_TRANSPOSE TransA = CblasConjTrans;
const int M = static_cast<int>(src.rhs.m.nr()); const int M = static_cast<int>(src.rhs.op.m.nr());
const int N = static_cast<int>(src.rhs.m.nc()); const int N = static_cast<int>(src.rhs.op.m.nc());
const T* A = get_ptr(src.rhs.m); const T* A = get_ptr(src.rhs.op.m);
const int lda = get_ld(src.rhs.m); const int lda = get_ld(src.rhs.op.m);
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest); T* Y = get_ptr(dest);
...@@ -935,10 +935,10 @@ namespace dlib ...@@ -935,10 +935,10 @@ namespace dlib
const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value;
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasConjTrans; const CBLAS_TRANSPOSE TransA = CblasConjTrans;
const int M = static_cast<int>(src.rhs.m.nr()); const int M = static_cast<int>(src.rhs.op.m.nr());
const int N = static_cast<int>(src.rhs.m.nc()); const int N = static_cast<int>(src.rhs.op.m.nc());
const T* A = get_ptr(src.rhs.m); const T* A = get_ptr(src.rhs.op.m);
const int lda = get_ld(src.rhs.m); const int lda = get_ld(src.rhs.op.m);
const T* X = get_ptr(src.lhs); const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs); const int incX = get_inc(src.lhs);
...@@ -957,10 +957,10 @@ namespace dlib ...@@ -957,10 +957,10 @@ namespace dlib
const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value;
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasConjTrans; const CBLAS_TRANSPOSE TransA = CblasConjTrans;
const int M = static_cast<int>(src.lhs.m.nr()); const int M = static_cast<int>(src.lhs.op.m.nr());
const int N = static_cast<int>(src.lhs.m.nc()); const int N = static_cast<int>(src.lhs.op.m.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* X = get_ptr(src.rhs); const T* X = get_ptr(src.rhs);
const int incX = get_inc(src.rhs); const int incX = get_inc(src.rhs);
...@@ -979,12 +979,12 @@ namespace dlib ...@@ -979,12 +979,12 @@ namespace dlib
const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value; const bool is_row_major_order = is_same_type<typename dest_exp::layout_type,row_major_layout>::value;
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasConjTrans; const CBLAS_TRANSPOSE TransA = CblasConjTrans;
const int M = static_cast<int>(src.lhs.m.nr()); const int M = static_cast<int>(src.lhs.op.m.nr());
const int N = static_cast<int>(src.lhs.m.nc()); const int N = static_cast<int>(src.lhs.op.m.nc());
const T* A = get_ptr(src.lhs.m); const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.m); const int lda = get_ld(src.lhs.op.m);
const T* X = get_ptr(src.rhs.m); const T* X = get_ptr(src.rhs.op.m);
const int incX = get_inc(src.rhs.m); const int incX = get_inc(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0); const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest); T* Y = get_ptr(dest);
...@@ -1033,8 +1033,8 @@ namespace dlib ...@@ -1033,8 +1033,8 @@ namespace dlib
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const int M = static_cast<int>(dest.nr()); const int M = static_cast<int>(dest.nr());
const int N = static_cast<int>(dest.nc()); const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs); const T* Y = get_ptr(src.rhs);
const int incY = get_inc(src.rhs); const int incY = get_inc(src.rhs);
...@@ -1061,8 +1061,8 @@ namespace dlib ...@@ -1061,8 +1061,8 @@ namespace dlib
const int N = static_cast<int>(dest.nc()); const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs); const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs); const int incX = get_inc(src.lhs);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (add_to == false) if (add_to == false)
zero_matrix(dest); zero_matrix(dest);
...@@ -1085,10 +1085,10 @@ namespace dlib ...@@ -1085,10 +1085,10 @@ namespace dlib
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const int M = static_cast<int>(dest.nr()); const int M = static_cast<int>(dest.nr());
const int N = static_cast<int>(dest.nc()); const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (add_to == false) if (add_to == false)
zero_matrix(dest); zero_matrix(dest);
...@@ -1118,8 +1118,8 @@ namespace dlib ...@@ -1118,8 +1118,8 @@ namespace dlib
const int N = static_cast<int>(dest.nc()); const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs); const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs); const int incX = get_inc(src.lhs);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (add_to == false) if (add_to == false)
zero_matrix(dest); zero_matrix(dest);
...@@ -1145,8 +1145,8 @@ namespace dlib ...@@ -1145,8 +1145,8 @@ namespace dlib
const int N = static_cast<int>(dest.nc()); const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs); const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs); const int incX = get_inc(src.lhs);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (transpose == false) if (transpose == false)
...@@ -1175,10 +1175,10 @@ namespace dlib ...@@ -1175,10 +1175,10 @@ namespace dlib
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const int M = static_cast<int>(dest.nr()); const int M = static_cast<int>(dest.nr());
const int N = static_cast<int>(dest.nc()); const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (transpose == false) if (transpose == false)
...@@ -1208,10 +1208,10 @@ namespace dlib ...@@ -1208,10 +1208,10 @@ namespace dlib
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const int M = static_cast<int>(dest.nr()); const int M = static_cast<int>(dest.nr());
const int N = static_cast<int>(dest.nc()); const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (add_to == false) if (add_to == false)
zero_matrix(dest); zero_matrix(dest);
...@@ -1254,8 +1254,8 @@ namespace dlib ...@@ -1254,8 +1254,8 @@ namespace dlib
{ {
//cout << "BLAS DOT: trans(cv)*cv" << endl; //cout << "BLAS DOT: trans(cv)*cv" << endl;
const int N = static_cast<int>(src.lhs.size()); const int N = static_cast<int>(src.lhs.size());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs); const T* Y = get_ptr(src.rhs);
const int incY = get_inc(src.rhs); const int incY = get_inc(src.rhs);
...@@ -1274,8 +1274,8 @@ namespace dlib ...@@ -1274,8 +1274,8 @@ namespace dlib
const int N = static_cast<int>(src.lhs.size()); const int N = static_cast<int>(src.lhs.size());
const T* X = get_ptr(src.lhs); const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs); const int incX = get_inc(src.lhs);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (add_to == false) if (add_to == false)
dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); dest(0) = alpha*cblas_dot(N, X, incX, Y, incY);
...@@ -1289,11 +1289,11 @@ namespace dlib ...@@ -1289,11 +1289,11 @@ namespace dlib
DLIB_ADD_BLAS_BINDING(trans(cv)*trans(rv)) DLIB_ADD_BLAS_BINDING(trans(cv)*trans(rv))
{ {
//cout << "BLAS DOT: trans(cv)*trans(rv)" << endl; //cout << "BLAS DOT: trans(cv)*trans(rv)" << endl;
const int N = static_cast<int>(src.lhs.m.size()); const int N = static_cast<int>(src.lhs.op.m.size());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (add_to == false) if (add_to == false)
dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); dest(0) = alpha*cblas_dot(N, X, incX, Y, incY);
...@@ -1311,9 +1311,9 @@ namespace dlib ...@@ -1311,9 +1311,9 @@ namespace dlib
DLIB_ADD_BLAS_BINDING(conj(rv)*cv) DLIB_ADD_BLAS_BINDING(conj(rv)*cv)
{ {
//cout << "BLAS DOTC: conj(rv)*cv" << endl; //cout << "BLAS DOTC: conj(rv)*cv" << endl;
const int N = static_cast<int>(src.lhs.m.size()); const int N = static_cast<int>(src.lhs.op.m.size());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs); const T* Y = get_ptr(src.rhs);
const int incY = get_inc(src.rhs); const int incY = get_inc(src.rhs);
...@@ -1329,9 +1329,9 @@ namespace dlib ...@@ -1329,9 +1329,9 @@ namespace dlib
DLIB_ADD_BLAS_BINDING(conj(trans(cv))*cv) DLIB_ADD_BLAS_BINDING(conj(trans(cv))*cv)
{ {
//cout << "BLAS DOTC: conj(trans(cv))*cv" << endl; //cout << "BLAS DOTC: conj(trans(cv))*cv" << endl;
const int N = static_cast<int>(src.lhs.m.size()); const int N = static_cast<int>(src.lhs.op.m.size());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs); const T* Y = get_ptr(src.rhs);
const int incY = get_inc(src.rhs); const int incY = get_inc(src.rhs);
...@@ -1347,11 +1347,11 @@ namespace dlib ...@@ -1347,11 +1347,11 @@ namespace dlib
DLIB_ADD_BLAS_BINDING(trans(conj(cv))*trans(rv)) DLIB_ADD_BLAS_BINDING(trans(conj(cv))*trans(rv))
{ {
//cout << "BLAS DOTC: trans(conj(cv))*trans(rv)" << endl; //cout << "BLAS DOTC: trans(conj(cv))*trans(rv)" << endl;
const int N = static_cast<int>(src.lhs.m.size()); const int N = static_cast<int>(src.lhs.op.m.size());
const T* X = get_ptr(src.lhs.m); const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.m); const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.m); const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.m); const int incY = get_inc(src.rhs.op.m);
if (add_to == false) if (add_to == false)
dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY); dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY);
......
...@@ -22,44 +22,44 @@ namespace dlib ...@@ -22,44 +22,44 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_conj_trans struct op_conj_trans
{ {
template <typename EXP> op_conj_trans( const M& m_) : m(m_){}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost;
const static long NR = EXP::NC;
const static long NC = EXP::NR;
typedef typename EXP::type type;
typedef typename EXP::type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type;
template <typename M>
static const const_ret_type apply ( const M& m, long r, long c)
{ return std::conj(m(c,r)); }
template <typename M> const static long cost = M::cost;
static long nr (const M& m) { return m.nc(); } const static long NR = M::NC;
template <typename M> const static long NC = M::NR;
static long nc (const M& m) { return m.nr(); } typedef typename M::type type;
}; typedef typename M::type const_ret_type;
typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
const_ret_type apply (long r, long c) const { return std::conj(m(c,r)); }
long nr () const { return m.nc(); }
long nc () const { return m.nr(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template <typename EXP> template <typename EXP>
const matrix_unary_exp<EXP,op_conj_trans> trans ( const matrix_op<op_conj_trans<EXP> > trans (
const matrix_unary_exp<EXP,op_conj>& m const matrix_op<op_conj<EXP> >& m
) )
{ {
typedef matrix_unary_exp<EXP,op_conj_trans> exp; typedef op_conj_trans<EXP> op;
return exp(m.m); return matrix_op<op>(op(m.op.m));
} }
template <typename EXP> template <typename EXP>
const matrix_unary_exp<EXP,op_conj_trans> conj ( const matrix_op<op_conj_trans<EXP> > conj (
const matrix_unary_exp<EXP,op_trans>& m const matrix_op<op_trans<EXP> >& m
) )
{ {
typedef matrix_unary_exp<EXP,op_conj_trans> exp; typedef op_conj_trans<EXP> op;
return exp(m.m); return matrix_op<op>(op(m.op.m));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
// 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"
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<exp_type,0>
{
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<exp_type,0>
{
static inline long get(const exp_type& m) { return m.nc(); }
};
template <typename EXP>
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 <
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<EXP>::type type;
typedef typename matrix_traits<EXP>::const_ret_type const_ret_type;
typedef typename matrix_traits<EXP>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<EXP>::layout_type layout_type;
const static long NR = matrix_traits<EXP>::NR;
const static long NC = matrix_traits<EXP>::NC;
const static long cost = matrix_traits<EXP>::cost;
typedef matrix<type,NR,NC,mem_manager_type,layout_type> matrix_type;
typedef EXP exp_type;
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<exp_type,NR>::get(ref()); }
long nc (
) const { return get_nc_helper<exp_type,NC>::get(ref()); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return ref().aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return ref().destructively_aliases(item); }
inline const exp_type& ref (
) const { return *static_cast<const exp_type*>(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<type,1,1,mem_manager_type,layout_type> temp(ref());
return temp(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 <typename T>
struct is_matrix<T, typename enable_if<is_convertible<T, const matrix_exp<typename T::exp_type>& > >::type >
{ static const bool value = true; };
/*
is_matrix<T>::value == 1 if T is a matrix type else 0
*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_EXP_h_
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MATRIx_EXP_ABSTRACT_
#ifdef DLIB_MATRIx_EXP_ABSTRACT_
#include "matrix_fwd.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename EXP
>
class matrix_exp
{
/*!
REQUIREMENTS ON EXP
- must be an object that inherits publicly from matrix_exp (this class).
WHAT THIS OBJECT REPRESENTS
This object represents an expression that evaluates to a matrix
of nr() rows and nc() columns.
The reason for having an object that represents an expression is that it
allows us to use the "expression templates" technique to eliminate the
temporary matrix objects that would normally be returned from expressions
such as M = A+B+C+D; Normally each invocation of the + operator would
construct and return a temporary matrix object but using this technique we
can avoid creating all of these temporary objects and receive a large
speed boost.
Note that every time you invoke operator() on this object it recomputes
its result which may not be what you want to do. For example, if you
are going to be accessing the same element over and over it might
be faster to assign the matrix_exp to a temporary matrix and then
use that temporary.
const_ret_type typedef (defined below)
The purpose of the const_ret_type typedef is to allow matrix expressions
to return their elements by reference when appropriate. So const_ret_type
should be one of the following types:
- const type
- const type&
!*/
public:
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 cost = EXP::cost;
const static long NR = EXP::NR;
const static long NC = EXP::NC;
typedef matrix<type,NR,NC, mem_manager_type,layout_type> matrix_type;
typedef EXP exp_type;
const_ret_type operator() (
long r,
long c
) const;
/*!
requires
- 0 <= r < nr()
- 0 <= c < nc()
ensures
- returns ref()(r,c)
(i.e. returns the value at the given row and column that would be in
the matrix represented by this matrix expression)
!*/
const_ret_type operator() (
long i
) const;
/*!
requires
- nc() == 1 || nr() == 1 (i.e. this must be a column or row vector)
- if (nc() == 1) then
- 0 <= i < nr()
- else
- 0 <= i < nc()
ensures
- if (nc() == 1) then
- returns (*this)(i,0)
- else
- returns (*this)(0,i)
!*/
operator const type (
) const;
/*!
requires
- nr() == 1
- nc() == 1
ensures
- returns (*this)(0,0)
!*/
long nr (
) const;
/*!
ensures
- returns the number of rows in this matrix expression.
!*/
long nc (
) const;
/*!
ensures
- returns the number of columns in this matrix expression.
!*/
long size (
) const;
/*!
ensures
- returns nr()*nc()
!*/
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const;
/*!
ensures
- if (A change to the state of item could cause a change to the state of *this
matrix_exp object. ) then
- returns true
- This happens when this matrix_exp contains item in some way.
- else
- returns false
!*/
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const;
/*!
ensures
- if (aliases(item)) then
- if (nr() != item.nr() || nc() != item.nc()
- returns true
(i.e. if this expression has different dimensions than item then
we have destructive aliasing)
- returns true if the following assignment would evaluate incorrectly:
for (long r = 0; r < nr(); ++r)
for (long c = 0; c < nc(); ++c)
item(r,c) = (*this)(r,c)
- That is, if this matrix expression aliases item in such a way that a modification
to element item(r,c) causes a change in the value of something other than
(*this)(r,c) then this function returns true.
- returns false if none of the above conditions say we should return true
- else
- returns false
!*/
inline const exp_type& ref (
) const;
/*!
ensures
- returns a reference to the expression contained in *this.
(i.e. returns *static_cast<const exp_type*>(this) )
!*/
protected:
// Only derived classes of matrix_exp may call the matrix_exp constructors.
matrix_exp(const matrix_exp&);
matrix_exp();
private:
// no one may ever use the assignment operator on a matrix_exp
matrix_exp& operator= (const matrix_exp&);
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_EXP_ABSTRACT_
...@@ -23,1339 +23,6 @@ namespace dlib ...@@ -23,1339 +23,6 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// Helper templates for making operators used by expression objects // Helper templates for making operators used by expression objects
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
/*
templates for finding the max of two matrix expressions' dimensions
*/
template <typename EXP1, typename EXP2 = void, typename EXP3 = void, typename EXP4 = void>
struct max_nr;
template <typename EXP1>
struct max_nr<EXP1,void,void,void>
{
const static long val = EXP1::NR;
};
template <typename EXP1, typename EXP2>
struct max_nr<EXP1,EXP2,void,void>
{
const static long val = (EXP1::NR > EXP2::NR) ? (EXP1::NR) : (EXP2::NR);
};
template <typename EXP1, typename EXP2, typename EXP3>
struct max_nr<EXP1,EXP2,EXP3,void>
{
private:
const static long max12 = (EXP1::NR > EXP2::NR) ? (EXP1::NR) : (EXP2::NR);
public:
const static long val = (max12 > EXP3::NR) ? (max12) : (EXP3::NR);
};
template <typename EXP1, typename EXP2, typename EXP3, typename EXP4>
struct max_nr
{
private:
const static long max12 = (EXP1::NR > EXP2::NR) ? (EXP1::NR) : (EXP2::NR);
const static long max34 = (EXP3::NR > EXP4::NR) ? (EXP3::NR) : (EXP4::NR);
public:
const static long val = (max12 > max34) ? (max12) : (max34);
};
template <typename EXP1, typename EXP2 = void, typename EXP3 = void, typename EXP4 = void>
struct max_nc;
template <typename EXP1>
struct max_nc<EXP1,void,void,void>
{
const static long val = EXP1::NC;
};
template <typename EXP1, typename EXP2>
struct max_nc<EXP1,EXP2,void,void>
{
const static long val = (EXP1::NC > EXP2::NC) ? (EXP1::NC) : (EXP2::NC);
};
template <typename EXP1, typename EXP2, typename EXP3>
struct max_nc<EXP1,EXP2,EXP3,void>
{
private:
const static long max12 = (EXP1::NC > EXP2::NC) ? (EXP1::NC) : (EXP2::NC);
public:
const static long val = (max12 > EXP3::NC) ? (max12) : (EXP3::NC);
};
template <typename EXP1, typename EXP2, typename EXP3, typename EXP4>
struct max_nc
{
private:
const static long max12 = (EXP1::NC > EXP2::NC) ? (EXP1::NC) : (EXP2::NC);
const static long max34 = (EXP3::NC > EXP4::NC) ? (EXP3::NC) : (EXP4::NC);
public:
const static long val = (max12 > max34) ? (max12) : (max34);
};
// ----------------------------------------------------------------------------------------
struct has_destructive_aliasing
{
template <typename M, typename U>
static bool destructively_aliases (
const M& m,
const matrix_exp<U>& item
) { return m.aliases(item); }
template <typename M1, typename M2, typename U>
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const matrix_exp<U>& item
) { return m1.aliases(item) || m2.aliases(item) ; }
template <typename M1, typename M2, typename M3, typename U>
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const M3& m3,
const matrix_exp<U>& item
) { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item); }
template <typename M1, typename M2, typename M3, typename M4, typename U>
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const M3& m3,
const M4& m4,
const matrix_exp<U>& item
) { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) || m4.aliases(item); }
};
// ----------------------------------------------------------------------------------------
struct has_nondestructive_aliasing
{
template <typename M, typename U>
static bool destructively_aliases (
const M& m,
const matrix_exp<U>& item
) { return m.destructively_aliases(item); }
template <typename M1, typename M2, typename U>
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const matrix_exp<U>& item
) { return m1.destructively_aliases(item) || m2.destructively_aliases(item) ; }
template <typename M1, typename M2, typename M3, typename U>
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const M3& m3,
const matrix_exp<U>& item
) { return m1.destructively_aliases(item) || m2.destructively_aliases(item) || m3.destructively_aliases(item) ; }
template <typename M1, typename M2, typename M3, typename M4, typename U>
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const M3& m3,
const M4& m4,
const matrix<U>& item
) { return m1.destructively_aliases(item) ||
m2.destructively_aliases(item) ||
m3.destructively_aliases(item) ||
m4.destructively_aliases(item) ; }
};
// ----------------------------------------------------------------------------------------
template <typename EXP1, typename EXP2 = void, typename EXP3 = void, typename EXP4 = void>
struct preserves_dimensions
{
const static long NR = max_nr<EXP1,EXP2,EXP3,EXP4>::val;
const static long NC = max_nc<EXP1,EXP2,EXP3,EXP4>::val;
typedef typename EXP1::mem_manager_type mem_manager_type;
template <typename M>
static long nr (const M& m) { return m.nr(); }
template <typename M>
static long nc (const M& m) { return m.nc(); }
template <typename M1, typename M2>
static long nr (const M1& m1, const M2& ) { return m1.nr(); }
template <typename M1, typename M2>
static long nc (const M1& m1, const M2& ) { return m1.nc(); }
template <typename M1, typename M2, typename M3>
static long nr (const M1& m1, const M2&, const M3& ) { return m1.nr(); }
template <typename M1, typename M2, typename M3>
static long nc (const M1& m1, const M2&, const M3& ) { return m1.nc(); }
template <typename M1, typename M2, typename M3, typename M4>
static long nr (const M1& m1, const M2&, const M3&, const M4& ) { return m1.nr(); }
template <typename M1, typename M2, typename M3, typename M4>
static long nc (const M1& m1, const M2&, const M3&, const M4& ) { return m1.nc(); }
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// General matrix expressions that take operator structs
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template < typename M, typename OP_ >
class matrix_unary_exp;
template < typename M, typename OP_ >
struct matrix_traits<matrix_unary_exp<M,OP_> >
{
typedef typename OP_::template op<M> OP;
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
template <
typename M,
typename OP_
>
class matrix_unary_exp : public matrix_exp<matrix_unary_exp<M,OP_> >
{
/*!
REQUIREMENTS ON M
- must be an object that inherits from matrix_exp
!*/
typedef typename OP_::template op<M> OP;
public:
typedef typename matrix_traits<matrix_unary_exp>::type type;
typedef typename matrix_traits<matrix_unary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_unary_exp>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<matrix_unary_exp>::layout_type layout_type;
const static long NR = matrix_traits<matrix_unary_exp>::NR;
const static long NC = matrix_traits<matrix_unary_exp>::NC;
const static long cost = matrix_traits<matrix_unary_exp>::cost;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1>
matrix_unary_exp (T1);
public:
matrix_unary_exp (
const M& m_
) :
m(m_)
{}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(m,r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_unary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return m.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return OP::destructively_aliases(m,item); }
long nr (
) const { return OP::nr(m); }
long nc (
) const { return OP::nc(m); }
const M& m;
};
// ----------------------------------------------------------------------------------------
template < typename M, typename S, typename OP_ >
class matrix_scalar_binary_exp;
template < typename M, typename S, typename OP_ >
struct matrix_traits<matrix_scalar_binary_exp<M,S,OP_> >
{
typedef typename OP_::template op<M> OP;
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
typedef typename M::layout_type layout_type;
};
template <
typename M,
typename S,
typename OP_
>
class matrix_scalar_binary_exp : public matrix_exp<matrix_scalar_binary_exp<M,S,OP_> >
{
/*!
REQUIREMENTS ON M
- must be an object that inherits from matrix_exp
!*/
typedef typename OP_::template op<M> OP;
public:
typedef typename matrix_traits<matrix_scalar_binary_exp>::type type;
typedef typename matrix_traits<matrix_scalar_binary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_scalar_binary_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_scalar_binary_exp>::NR;
const static long NC = matrix_traits<matrix_scalar_binary_exp>::NC;
const static long cost = matrix_traits<matrix_scalar_binary_exp>::cost;
typedef typename matrix_traits<matrix_scalar_binary_exp>::layout_type layout_type;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1>
matrix_scalar_binary_exp (T1,const S&);
public:
matrix_scalar_binary_exp (
const M& m_,
const S& s_
) :
m(m_),
s(s_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(m,s,r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_scalar_binary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return m.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return OP::destructively_aliases(m,item); }
long nr (
) const { return OP::nr(m); }
long nc (
) const { return OP::nc(m); }
const M& m;
const S s;
};
// ----------------------------------------------------------------------------------------
template < typename M, typename S, typename OP_ >
class matrix_scalar_ternary_exp;
template < typename M, typename S, typename OP_ >
struct matrix_traits<matrix_scalar_ternary_exp<M,S,OP_> >
{
typedef typename OP_::template op<M> OP;
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
typedef typename M::layout_type layout_type;
};
template <
typename M,
typename S,
typename OP_
>
class matrix_scalar_ternary_exp : public matrix_exp<matrix_scalar_ternary_exp<M,S,OP_> >
{
/*!
REQUIREMENTS ON M
- must be an object that inherits from matrix_exp
!*/
typedef typename OP_::template op<M> OP;
public:
typedef typename matrix_traits<matrix_scalar_ternary_exp>::type type;
typedef typename matrix_traits<matrix_scalar_ternary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_scalar_ternary_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_scalar_ternary_exp>::NR;
const static long NC = matrix_traits<matrix_scalar_ternary_exp>::NC;
const static long cost = matrix_traits<matrix_scalar_ternary_exp>::cost;
typedef typename matrix_traits<matrix_scalar_ternary_exp>::layout_type layout_type;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1>
matrix_scalar_ternary_exp (T1, const S&, const S&);
public:
matrix_scalar_ternary_exp (
const M& m_,
const S& s1_,
const S& s2_
) :
m(m_),
s1(s1_),
s2(s2_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(m,s1,s2,r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_scalar_ternary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return m.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return OP::destructively_aliases(m,item); }
long nr (
) const { return OP::nr(m,s1,s2); }
long nc (
) const { return OP::nc(m,s1,s2); }
const M& m;
const S s1;
const S s2;
};
// ----------------------------------------------------------------------------------------
template < typename M1, typename M2, typename OP_ >
class matrix_binary_exp;
template < typename M1, typename M2, typename OP_ >
struct matrix_traits<matrix_binary_exp<M1,M2,OP_> >
{
typedef typename OP_::template op<M1,M2> OP;
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
typedef typename M1::layout_type layout_type;
};
template <
typename M1,
typename M2,
typename OP_
>
class matrix_binary_exp : public matrix_exp<matrix_binary_exp<M1,M2,OP_> >
{
/*!
REQUIREMENTS ON M1 AND M2
- must be objects that inherit from matrix_exp
!*/
typedef typename OP_::template op<M1,M2> OP;
public:
typedef typename matrix_traits<matrix_binary_exp>::type type;
typedef typename matrix_traits<matrix_binary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_binary_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_binary_exp>::NR;
const static long NC = matrix_traits<matrix_binary_exp>::NC;
const static long cost = matrix_traits<matrix_binary_exp>::cost;
typedef typename matrix_traits<matrix_binary_exp>::layout_type layout_type;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1, typename T2>
matrix_binary_exp (T1,T2);
public:
matrix_binary_exp (
const M1& m1_,
const M2& m2_
) :
m1(m1_),
m2(m2_)
{}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(m1,m2,r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_binary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return m1.aliases(item) || m2.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return OP::destructively_aliases(m1,m2,item); }
long nr (
) const { return OP::nr(m1,m2); }
long nc (
) const { return OP::nc(m1,m2); }
private:
const M1& m1;
const M2& m2;
};
// ----------------------------------------------------------------------------------------
template < typename M1, typename M2, typename M3, typename OP_ >
class matrix_ternary_exp;
template < typename M1, typename M2, typename M3, typename OP_ >
struct matrix_traits<matrix_ternary_exp<M1,M2,M3,OP_> >
{
typedef typename OP_::template op<M1,M2,M3> OP;
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
typedef typename M1::layout_type layout_type;
};
template <
typename M1,
typename M2,
typename M3,
typename OP_
>
class matrix_ternary_exp : public matrix_exp<matrix_ternary_exp<M1,M2,M3,OP_> >
{
/*!
REQUIREMENTS ON M1, M2 AND M3
- must be objects that inherit from matrix_exp
!*/
typedef typename OP_::template op<M1,M2,M3> OP;
public:
typedef typename matrix_traits<matrix_ternary_exp>::type type;
typedef typename matrix_traits<matrix_ternary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_ternary_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_ternary_exp>::NR;
const static long NC = matrix_traits<matrix_ternary_exp>::NC;
const static long cost = matrix_traits<matrix_ternary_exp>::cost;
typedef typename matrix_traits<matrix_ternary_exp>::layout_type layout_type;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1, typename T2, typename T3>
matrix_ternary_exp ( T1, T2, T3 );
public:
matrix_ternary_exp (
const M1& m1_,
const M2& m2_,
const M3& m3_
) :
m1(m1_),
m2(m2_),
m3(m3_)
{}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(m1,m2,m3,r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_ternary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return OP::destructively_aliases(m1,m2,m3,item); }
long nr (
) const { return OP::nr(m1,m2,m3); }
long nc (
) const { return OP::nc(m1,m2,m3); }
private:
const M1& m1;
const M2& m2;
const M3& m3;
};
// ----------------------------------------------------------------------------------------
template < typename M1, typename M2, typename M3, typename M4, typename OP_ >
class matrix_fourary_exp;
template < typename M1, typename M2, typename M3, typename M4, typename OP_ >
struct matrix_traits<matrix_fourary_exp<M1,M2,M3,M4,OP_> >
{
typedef typename OP_::template op<M1,M2,M3,M4> OP;
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
typedef typename M1::layout_type layout_type;
};
template <
typename M1,
typename M2,
typename M3,
typename M4,
typename OP_
>
class matrix_fourary_exp : public matrix_exp<matrix_fourary_exp<M1,M2,M3,M4,OP_> >
{
/*!
REQUIREMENTS ON M1, M2, M3 AND M4
- must be objects that inherit from matrix_exp
!*/
typedef typename OP_::template op<M1,M2,M3,M4> OP;
public:
typedef typename matrix_traits<matrix_fourary_exp>::type type;
typedef typename matrix_traits<matrix_fourary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_fourary_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_fourary_exp>::NR;
const static long NC = matrix_traits<matrix_fourary_exp>::NC;
const static long cost = matrix_traits<matrix_fourary_exp>::cost;
typedef typename matrix_traits<matrix_fourary_exp>::layout_type layout_type;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1, typename T2, typename T3, typename T4>
matrix_fourary_exp (T1,T2,T3,T4);
public:
matrix_fourary_exp (
const M1& m1_,
const M2& m2_,
const M3& m3_,
const M4& m4_
) :
m1(m1_),
m2(m2_),
m3(m3_),
m4(m4_)
{}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(m1,m2,m3,m4,r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_fourary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) || m4.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return OP::destructively_aliases(m1,m2,m3,m4,item); }
long nr (
) const { return OP::nr(m1,m2,m3,m4); }
long nc (
) const { return OP::nc(m1,m2,m3,m4); }
private:
const M1& m1;
const M2& m2;
const M3& m3;
const M4& m4;
};
// ----------------------------------------------------------------------------------------
template < typename S, typename OP >
class dynamic_matrix_scalar_unary_exp;
template < typename S, typename OP >
struct matrix_traits<dynamic_matrix_scalar_unary_exp<S,OP> >
{
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
typedef row_major_layout layout_type;
};
template <
typename S,
typename OP
>
class dynamic_matrix_scalar_unary_exp : public matrix_exp<dynamic_matrix_scalar_unary_exp<S,OP> >
{
/*!
REQUIREMENTS ON S
should be some scalar type
!*/
public:
typedef typename matrix_traits<dynamic_matrix_scalar_unary_exp>::type type;
typedef typename matrix_traits<dynamic_matrix_scalar_unary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<dynamic_matrix_scalar_unary_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<dynamic_matrix_scalar_unary_exp>::NR;
const static long NC = matrix_traits<dynamic_matrix_scalar_unary_exp>::NC;
const static long cost = matrix_traits<dynamic_matrix_scalar_unary_exp>::cost;
typedef typename matrix_traits<dynamic_matrix_scalar_unary_exp>::layout_type layout_type;
dynamic_matrix_scalar_unary_exp (
long nr__,
long nc__,
const S& s_
) :
nr_(nr__),
nc_(nc__),
s(s_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(s,r,c, nr_, nc_); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<dynamic_matrix_scalar_unary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return nr_; }
long nc (
) const { return nc_; }
private:
const long nr_;
const long nc_;
const S s;
};
// ----------------------------------------------------------------------------------------
template <typename S, typename OP>
class matrix_scalar_unary_exp;
template <typename S, typename OP>
struct matrix_traits<matrix_scalar_unary_exp<S,OP> >
{
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
typedef row_major_layout layout_type;
};
template <
typename S,
typename OP
>
class matrix_scalar_unary_exp : public matrix_exp<matrix_scalar_unary_exp<S,OP> >
{
/*!
REQUIREMENTS ON S
should be some scalar type
!*/
public:
typedef typename matrix_traits<matrix_scalar_unary_exp>::type type;
typedef typename matrix_traits<matrix_scalar_unary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_scalar_unary_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_scalar_unary_exp>::NR;
const static long NC = matrix_traits<matrix_scalar_unary_exp>::NC;
const static long cost = matrix_traits<matrix_scalar_unary_exp>::cost;
typedef typename matrix_traits<matrix_scalar_unary_exp>::layout_type layout_type;
matrix_scalar_unary_exp (
const S& s_
) :
s(s_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(s,r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_scalar_unary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return NR; }
long nc (
) const { return NC; }
private:
const S s;
};
// ----------------------------------------------------------------------------------------
template <typename OP>
class matrix_zeroary_exp;
template <typename OP>
struct matrix_traits<matrix_zeroary_exp<OP> >
{
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
typedef row_major_layout layout_type;
};
template <
typename OP
>
class matrix_zeroary_exp : public matrix_exp<matrix_zeroary_exp<OP> >
{
public:
typedef typename matrix_traits<matrix_zeroary_exp>::type type;
typedef typename matrix_traits<matrix_zeroary_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_zeroary_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_zeroary_exp>::NR;
const static long NC = matrix_traits<matrix_zeroary_exp>::NC;
const static long cost = matrix_traits<matrix_zeroary_exp>::cost;
typedef typename matrix_traits<matrix_zeroary_exp>::layout_type layout_type;
matrix_zeroary_exp (
) {}
const_ret_type operator() (
long r,
long c
) const { return OP::apply(r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_zeroary_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return false; }
long nr (
) const { return NR; }
long nc (
) const { return NC; }
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Specialized matrix expressions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template < typename M, typename EXPr, typename EXPc >
class matrix_sub_range_exp;
template < typename M, typename EXPr, typename EXPc >
struct matrix_traits<matrix_sub_range_exp<M,EXPr,EXPc> >
{
typedef typename M::type type;
typedef typename M::const_ret_type const_ret_type;
typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
const static long NR = EXPr::NR*EXPr::NC;
const static long NC = EXPc::NR*EXPc::NC;
const static long cost = EXPr::cost+EXPc::cost+M::cost;
};
template <
typename M,
typename EXPr,
typename EXPc
>
class matrix_sub_range_exp : public matrix_exp<matrix_sub_range_exp<M,EXPr,EXPc> >
{
/*!
REQUIREMENTS ON M, EXPr and EXPc
- must be objects that inherit from matrix_exp
!*/
public:
typedef typename matrix_traits<matrix_sub_range_exp>::type type;
typedef typename matrix_traits<matrix_sub_range_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_sub_range_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_sub_range_exp>::NR;
const static long NC = matrix_traits<matrix_sub_range_exp>::NC;
const static long cost = matrix_traits<matrix_sub_range_exp>::cost;
typedef typename matrix_traits<matrix_sub_range_exp>::layout_type layout_type;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1, typename T2, typename T3>
matrix_sub_range_exp (T1,T2,T3);
public:
matrix_sub_range_exp (
const M& m_,
const EXPr& rows_,
const EXPc& cols_
) :
m(m_),
rows(rows_),
cols(cols_)
{
}
const_ret_type operator() (
long r,
long c
) const { return m(rows(r),cols(c)); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_sub_range_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return m.aliases(item) || rows.aliases(item) || cols.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return m.aliases(item) || rows.aliases(item) || cols.aliases(item); }
long nr (
) const { return rows.size(); }
long nc (
) const { return cols.size(); }
private:
const M& m;
const EXPr& rows;
const EXPc& cols;
};
// ----------------------------------------------------------------------------------------
template <typename M>
class matrix_std_vector_exp;
template <typename M>
struct matrix_traits<matrix_std_vector_exp<M> >
{
typedef typename M::value_type type;
typedef const typename M::value_type& const_ret_type;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
const static long NR = 0;
const static long NC = 1;
const static long cost = 1;
typedef row_major_layout layout_type;
};
template <
typename M
>
class matrix_std_vector_exp : public matrix_exp<matrix_std_vector_exp<M> >
{
/*!
REQUIREMENTS ON M
- must be a std::vector object (or
an object with a compatible interface).
!*/
public:
typedef typename matrix_traits<matrix_std_vector_exp>::type type;
typedef typename matrix_traits<matrix_std_vector_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_std_vector_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_std_vector_exp>::NR;
const static long NC = matrix_traits<matrix_std_vector_exp>::NC;
const static long cost = matrix_traits<matrix_std_vector_exp>::cost;
typedef typename matrix_traits<matrix_std_vector_exp>::layout_type layout_type;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1>
matrix_std_vector_exp (T1);
public:
matrix_std_vector_exp (
const M& m_
) :
m(m_)
{
}
const_ret_type operator() (
long r,
long
) const { return m[r]; }
const_ret_type operator() ( long i ) const
{ return m[i]; }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return m.size(); }
long nc (
) const { return 1; }
private:
const M& m;
};
// ----------------------------------------------------------------------------------------
template <typename M>
class matrix_array_exp;
template <typename M>
struct matrix_traits<matrix_array_exp<M> >
{
typedef typename M::type type;
typedef const typename M::type& const_ret_type;
typedef typename M::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type;
const static long NR = 0;
const static long NC = 1;
const static long cost = 1;
};
template <
typename M
>
class matrix_array_exp : public matrix_exp<matrix_array_exp<M> >
{
/*!
REQUIREMENTS ON M
- must be a dlib::array object (or
an object with a compatible interface).
!*/
public:
typedef typename matrix_traits<matrix_array_exp>::type type;
typedef typename matrix_traits<matrix_array_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_array_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_array_exp>::NR;
const static long NC = matrix_traits<matrix_array_exp>::NC;
const static long cost = matrix_traits<matrix_array_exp>::cost;
typedef typename matrix_traits<matrix_array_exp>::layout_type layout_type;
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1>
matrix_array_exp (T1);
matrix_array_exp (
const M& m_
) :
m(m_)
{
}
const_ret_type operator() (
long r,
long
) const { return m[r]; }
const_ret_type operator() ( long i ) const
{ return m[i]; }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return m.size(); }
long nc (
) const { return 1; }
private:
const M& m;
};
// ----------------------------------------------------------------------------------------
template <typename M>
class matrix_array2d_exp;
template <typename M>
struct matrix_traits<matrix_array2d_exp<M> >
{
typedef typename M::type type;
typedef const typename M::type& const_ret_type;
typedef typename M::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type;
const static long NR = 0;
const static long NC = 0;
const static long cost = 1;
};
template <
typename M
>
class matrix_array2d_exp : public matrix_exp<matrix_array2d_exp<M> >
{
/*!
REQUIREMENTS ON M
- must be a dlib::array2d object (or
an object with a compatible interface).
!*/
public:
typedef typename matrix_traits<matrix_array2d_exp>::type type;
typedef typename matrix_traits<matrix_array2d_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_array2d_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_array2d_exp>::NR;
const static long NC = matrix_traits<matrix_array2d_exp>::NC;
const static long cost = matrix_traits<matrix_array2d_exp>::cost;
typedef typename matrix_traits<matrix_array2d_exp>::layout_type layout_type;
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1>
matrix_array2d_exp (T1);
matrix_array2d_exp (
const M& m_
) :
m(m_)
{
}
const_ret_type operator() (
long r,
long c
) const { return m[r][c]; }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_array2d_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return m.nr(); }
long nc (
) const { return m.nc(); }
private:
const M& m;
};
// ----------------------------------------------------------------------------------------
template <typename M>
class matrix_sub_exp;
template <typename M>
struct matrix_traits<matrix_sub_exp<M> >
{
typedef typename M::type type;
typedef typename M::const_ret_type const_ret_type;
typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
const static long NR = 0;
const static long NC = 0;
const static long cost = M::cost+1;
};
template <
typename M
>
class matrix_sub_exp : public matrix_exp<matrix_sub_exp<M> >
{
/*!
REQUIREMENTS ON M
- must be an object that inherits from matrix_exp
!*/
public:
typedef typename matrix_traits<matrix_sub_exp>::type type;
typedef typename matrix_traits<matrix_sub_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_sub_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_sub_exp>::NR;
const static long NC = matrix_traits<matrix_sub_exp>::NC;
const static long cost = matrix_traits<matrix_sub_exp>::cost;
typedef typename matrix_traits<matrix_sub_exp>::layout_type layout_type;
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1>
matrix_sub_exp (T1, long, long, long, long);
matrix_sub_exp (
const M& m_,
const long& r__,
const long& c__,
const long& nr__,
const long& nc__
) :
m(m_),
r_(r__),
c_(c__),
nr_(nr__),
nc_(nc__)
{
}
const_ret_type operator() (
long r,
long c
) const { return m(r+r_,c+c_); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_sub_exp>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return m.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return m.aliases(item); }
long nr (
) const { return nr_; }
long nc (
) const { return nc_; }
const M& m;
const long r_, c_, nr_, nc_;
};
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename T> template <typename T>
...@@ -1520,7 +187,7 @@ namespace dlib ...@@ -1520,7 +187,7 @@ namespace dlib
const_ret_type operator() ( const_ret_type operator() (
long c long c
) const { return std::pow(10,start + c*inc); } ) const { return std::pow((T)10,start + c*inc); }
template <typename U> template <typename U>
bool aliases ( bool aliases (
...@@ -1609,5 +276,5 @@ namespace dlib ...@@ -1609,5 +276,5 @@ namespace dlib
} }
#endif // DLIB_MATRIx_UTILITIES_ #endif // DLIB_MATRIx_EXPRESSIONS_H_
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define DLIB_MATRIx_MATH_FUNCTIONS #define DLIB_MATRIx_MATH_FUNCTIONS
#include "matrix_math_functions_abstract.h" #include "matrix_math_functions_abstract.h"
#include "matrix_op.h"
#include "matrix_utilities.h" #include "matrix_utilities.h"
#include "matrix.h" #include "matrix.h"
#include "../algs.h" #include "../algs.h"
...@@ -17,349 +18,214 @@ namespace dlib ...@@ -17,349 +18,214 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
#define DLIB_MATRIX_SIMPLE_STD_FUNCTION(name,extra_cost) struct op_##name { \ DLIB_DEFINE_FUNCTION_M(op_sqrt, sqrt, std::sqrt ,7);
template <typename EXP> \ DLIB_DEFINE_FUNCTION_M(op_log, log, std::log ,7);
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP> \ DLIB_DEFINE_FUNCTION_M(op_log10, log10, std::log10 ,7);
{ \ DLIB_DEFINE_FUNCTION_M(op_exp, exp, std::exp ,7);
const static long cost = EXP::cost+(extra_cost); \
typedef typename EXP::type type; \
typedef const typename EXP::type const_ret_type; \
template <typename M> \
static const_ret_type apply ( const M& m, long r, long c) \
{ return static_cast<type>(std::name(m(r,c))); } \
};}; \
template < typename EXP > \
const matrix_unary_exp<EXP,op_##name> name ( \
const matrix_exp<EXP>& m) \
{ \
return matrix_unary_exp<EXP,op_##name>(m.ref()); \
}
// ----------------------------------------------------------------------------------------
DLIB_MATRIX_SIMPLE_STD_FUNCTION(sqrt,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(log,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(log10,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(exp,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(conj,1) DLIB_DEFINE_FUNCTION_M(op_conj, conj, std::conj ,1);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(ceil,7) DLIB_DEFINE_FUNCTION_M(op_ceil, ceil, std::ceil ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(floor,7) DLIB_DEFINE_FUNCTION_M(op_floor, floor, std::floor ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(sin,7) DLIB_DEFINE_FUNCTION_M(op_sin, sin, std::sin ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(cos,7) DLIB_DEFINE_FUNCTION_M(op_cos, cos, std::cos ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(tan,7) DLIB_DEFINE_FUNCTION_M(op_tan, tan, std::tan ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(sinh,7) DLIB_DEFINE_FUNCTION_M(op_sinh, sinh, std::sinh ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(cosh,7) DLIB_DEFINE_FUNCTION_M(op_cosh, cosh, std::cosh ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(tanh,7) DLIB_DEFINE_FUNCTION_M(op_tanh, tanh, std::tanh ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(asin,7) DLIB_DEFINE_FUNCTION_M(op_asin, asin, std::asin ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(acos,7) DLIB_DEFINE_FUNCTION_M(op_acos, acos, std::acos ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan,7) DLIB_DEFINE_FUNCTION_M(op_atan, atan, std::atan ,7);
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_sigmoid namespace impl
{ {
template <typename EXP> template <typename type>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP> inline type sigmoid (const type& val)
{ {
const static long cost = EXP::cost+7; return static_cast<type>(1/(1 + std::exp(-val)));
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{
return static_cast<type>(1/(1 + std::exp(-m(r,c))));
} }
};
};
template < template <typename type, typename S>
typename EXP inline type round_zeros_eps (const type& val, const S& eps)
>
const matrix_unary_exp<EXP,op_sigmoid> sigmoid (
const matrix_exp<EXP>& m
)
{ {
return matrix_unary_exp<EXP,op_sigmoid>(m.ref()); // you can only round matrices that contain built in scalar types like double, long, float, etc.
} COMPILE_TIME_ASSERT(is_built_in_scalar_type<type>::value);
// ----------------------------------------------------------------------------------------
struct op_round_zeros if (val >= eps || val <= -eps)
{ return val;
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M, typename T>
static const_ret_type apply ( const M& m, const T& eps, long r, long c)
{
const type temp = m(r,c);
if (temp >= eps || temp <= -eps)
return temp;
else else
return 0; return 0;
} }
};
};
template < template <typename type>
typename EXP inline type round_zeros (const type& val)
>
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_round_zeros> round_zeros (
const matrix_exp<EXP>& m
)
{ {
// you can only round matrices that contain built in scalar types like double, long, float, etc. // you can only round matrices that contain built in scalar types like double, long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<type>::value);
typedef matrix_scalar_binary_exp<EXP,typename EXP::type, op_round_zeros> exp;
return exp(m.ref(),10*std::numeric_limits<typename EXP::type>::epsilon());
}
template < const type eps = 10*std::numeric_limits<type>::epsilon();
typename EXP if (val >= eps || val <= -eps)
> return val;
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_round_zeros> round_zeros ( else
const matrix_exp<EXP>& m, return 0;
typename EXP::type eps
)
{
// you can only round matrices that contain built in scalar types like double, long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,typename EXP::type, op_round_zeros>(m.ref(),eps);
} }
// ---------------------------------------------------------------------------------------- template <typename type>
inline type squared (const type& val)
struct op_cubed
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{ {
const static long cost = EXP::cost+7; return val*val;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{
const type temp = m(r,c);
return temp*temp*temp;
} }
};
};
template < template <typename type>
typename EXP type cubed (const type& val)
>
const matrix_unary_exp<EXP,op_cubed> cubed (
const matrix_exp<EXP>& m
)
{ {
return matrix_unary_exp<EXP,op_cubed>(m.ref()); return val*val*val;
} }
// ---------------------------------------------------------------------------------------- template <typename type, typename S>
inline type pow1 (const type& val, const S& s)
struct op_squared
{ {
template <typename EXP> // you can only call pow() on matrices that contain floats, doubles or long doubles.
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP> COMPILE_TIME_ASSERT((
{ is_same_type<type,float>::value == true ||
const static long cost = EXP::cost+6; is_same_type<type,double>::value == true ||
typedef typename EXP::type type; is_same_type<type,long double>::value == true
typedef const typename EXP::type const_ret_type; ));
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{
const type temp = m(r,c);
return temp*temp;
}
};
};
template < return std::pow(val,s);
typename EXP
>
const matrix_unary_exp<EXP,op_squared> squared (
const matrix_exp<EXP>& m
)
{
return matrix_unary_exp<EXP,op_squared>(m.ref());
} }
// ---------------------------------------------------------------------------------------- template <typename type, typename S>
inline type pow2 (const S& s, const type& val)
struct op_pow
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
{ return static_cast<type>(std::pow(m(r,c),s)); }
};
};
template <
typename EXP,
typename S
>
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_pow> pow (
const matrix_exp<EXP>& m,
const S& s
)
{ {
// you can only round matrices that contain floats, doubles or long doubles. // you can only call pow() on matrices that contain floats, doubles or long doubles.
COMPILE_TIME_ASSERT(( COMPILE_TIME_ASSERT((
is_same_type<typename EXP::type,float>::value == true || is_same_type<type,float>::value == true ||
is_same_type<typename EXP::type,double>::value == true || is_same_type<type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true is_same_type<type,long double>::value == true
)); ));
return matrix_scalar_binary_exp<EXP,typename EXP::type,op_pow>(m.ref(),s);
}
// ---------------------------------------------------------------------------------------- return std::pow(s,val);
}
struct op_pow2 template <typename type>
inline type reciprocal (const type& val)
{ {
template <typename EXP> // you can only compute reciprocal matrices that contain floats, doubles or long doubles.
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
{ return static_cast<type>(std::pow(s,m(r,c))); }
};
};
template <
typename EXP,
typename S
>
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_pow2> pow (
const S& s,
const matrix_exp<EXP>& m
)
{
// you can only round matrices that contain floats, doubles or long doubles.
COMPILE_TIME_ASSERT(( COMPILE_TIME_ASSERT((
is_same_type<typename EXP::type,float>::value == true || is_same_type<type,float>::value == true ||
is_same_type<typename EXP::type,double>::value == true || is_same_type<type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true is_same_type<type,long double>::value == true ||
is_same_type<type,std::complex<float> >::value == true ||
is_same_type<type,std::complex<double> >::value == true ||
is_same_type<type,std::complex<long double> >::value == true
)); ));
return matrix_scalar_binary_exp<EXP,typename EXP::type,op_pow2>(m.ref(),s);
}
// ----------------------------------------------------------------------------------------
struct op_reciprocal if (val != static_cast<type>(0))
{ return static_cast<type>((type)1.0/val);
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+6;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{
const type temp = m(r,c);
if (temp != static_cast<type>(0))
return static_cast<type>((type)1.0/temp);
else else
return 0; return 0;
} }
};
};
template < template <typename type>
typename EXP inline type reciprocal_max (const type& val)
>
const matrix_unary_exp<EXP,op_reciprocal> reciprocal (
const matrix_exp<EXP>& m
)
{ {
// you can only compute reciprocal matrices that contain floats, doubles or long doubles. // you can only compute reciprocal_max matrices that contain floats, doubles or long doubles.
COMPILE_TIME_ASSERT(( COMPILE_TIME_ASSERT((
is_same_type<typename EXP::type,float>::value == true || is_same_type<type,float>::value == true ||
is_same_type<typename EXP::type,double>::value == true || is_same_type<type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true || is_same_type<type,long double>::value == true
is_same_type<typename EXP::type,std::complex<float> >::value == true ||
is_same_type<typename EXP::type,std::complex<double> >::value == true ||
is_same_type<typename EXP::type,std::complex<long double> >::value == true
)); ));
return matrix_unary_exp<EXP,op_reciprocal>(m.ref());
if (val != static_cast<type>(0))
return static_cast<type>((type)1.0/val);
else
return std::numeric_limits<type>::max();
} }
}
DLIB_DEFINE_FUNCTION_M(op_sigmoid, sigmoid, impl::sigmoid, 7);
DLIB_DEFINE_FUNCTION_MS(op_round_zeros, round_zeros, impl::round_zeros_eps, 7);
DLIB_DEFINE_FUNCTION_M(op_round_zeros2, round_zeros, impl::round_zeros, 7);
DLIB_DEFINE_FUNCTION_M(op_cubed, cubed, impl::cubed, 7);
DLIB_DEFINE_FUNCTION_M(op_squared, squared, impl::squared, 6);
DLIB_DEFINE_FUNCTION_MS(op_pow1, pow, impl::pow1, 7);
DLIB_DEFINE_FUNCTION_SM(op_pow2, pow, impl::pow2, 7);
DLIB_DEFINE_FUNCTION_M(op_reciprocal, reciprocal, impl::reciprocal, 6);
DLIB_DEFINE_FUNCTION_M(op_reciprocal_max, reciprocal_max, impl::reciprocal_max, 6);
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_reciprocal_max template <typename M, typename enabled = void>
struct op_round : basic_op_m<M>
{ {
template <typename EXP> op_round( const M& m_) : basic_op_m<M>(m_){}
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
const static long cost = M::cost+7;
typedef typename M::type type;
typedef const typename M::type const_ret_type;
const_ret_type apply (long r, long c) const
{ {
const static long cost = EXP::cost+6; return static_cast<type>(std::floor(this->m(r,c)+0.5));
typedef typename EXP::type type; }
typedef const typename EXP::type const_ret_type; };
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, long r, long c) struct op_round<M,typename enable_if_c<std::numeric_limits<typename M::type>::is_integer>::type >
: basic_op_m<M>
{ {
const type temp = m(r,c); op_round( const M& m_) : basic_op_m<M>(m_){}
if (temp != static_cast<type>(0))
return static_cast<type>((type)1.0/temp); const static long cost = M::cost;
else typedef typename M::type type;
return std::numeric_limits<type>::max(); typedef typename M::const_ret_type const_ret_type;
const_ret_type apply (long r, long c) const
{
return this->m(r,c);
} }
}; };
};
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_reciprocal_max> reciprocal_max ( const matrix_op<op_round<EXP> > round (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
// you can only compute reciprocal_max matrices that contain floats, doubles or long doubles. // you can only round matrices that contain built in scalar types like double, long, float, etc.
COMPILE_TIME_ASSERT(( COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
is_same_type<typename EXP::type,float>::value == true ||
is_same_type<typename EXP::type,double>::value == true || typedef op_round<EXP> op;
is_same_type<typename EXP::type,long double>::value == true return matrix_op<op>(op(m.ref()));
));
return matrix_unary_exp<EXP,op_reciprocal_max>(m.ref());
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_normalize
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+5;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, const type& s, long r, long c) struct op_normalize : basic_op_m<M>
{
typedef typename M::type type;
op_normalize( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){}
const type s;
const static long cost = M::cost+5;
typedef const typename M::type const_ret_type;
const_ret_type apply (long r, long c) const
{ {
return m(r,c)*s; return this->m(r,c)*s;
} }
}; };
};
template < template <
typename EXP typename EXP
> >
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_normalize> normalize ( const matrix_op<op_normalize<EXP> > normalize (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
...@@ -369,152 +235,104 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan,7) ...@@ -369,152 +235,104 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan,7)
is_same_type<typename EXP::type,double>::value == true || is_same_type<typename EXP::type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true is_same_type<typename EXP::type,long double>::value == true
)); ));
typedef matrix_scalar_binary_exp<EXP,typename EXP::type, op_normalize> exp;
typedef op_normalize<EXP> op;
typename EXP::type temp = std::sqrt(sum(squared(m))); typename EXP::type temp = std::sqrt(sum(squared(m)));
if (temp != 0.0) if (temp != 0.0)
temp = 1.0/temp; temp = 1.0/temp;
return exp(m.ref(),temp); return matrix_op<op>(op(m.ref(),temp));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_round template <typename M, typename return_type = typename M::type>
{ struct op_abs : basic_op_m<M>
template <typename EXP, typename enabled = void>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{ {
return static_cast<type>(std::floor(m(r,c)+0.5)); op_abs( const M& m_) : basic_op_m<M>(m_){}
}
};
template <typename EXP> const static long cost = M::cost+7;
struct op<EXP,typename enable_if_c<std::numeric_limits<typename EXP::type>::is_integer>::type > typedef typename M::type type;
: has_nondestructive_aliasing, preserves_dimensions<EXP> typedef const typename M::type const_ret_type;
const_ret_type apply ( long r, long c) const
{ {
const static long cost = EXP::cost; return static_cast<type>(std::abs(this->m(r,c)));
typedef typename EXP::type type;
typedef typename EXP::const_ret_type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{
return m(r,c);
} }
}; };
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_round> round (
const matrix_exp<EXP>& m
)
{
// you can only round matrices that contain built in scalar types like double, long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
typedef matrix_unary_exp<EXP,op_round> exp;
return exp(m.ref());
}
// ---------------------------------------------------------------------------------------- template <typename M, typename T>
struct op_abs<M, std::complex<T> > : basic_op_m<M>
struct op_abs
{
template <typename EXP, typename return_type = typename EXP::type>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{ {
return static_cast<type>(std::abs(m(r,c))); op_abs( const M& m_) : basic_op_m<M>(m_){}
}
};
template <typename EXP, typename T> const static long cost = M::cost;
struct op<EXP, std::complex<T> > : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost;
typedef T type; typedef T type;
typedef const T const_ret_type; typedef const T const_ret_type;
template <typename M> const_ret_type apply ( long r, long c) const
static const_ret_type apply ( const M& m, long r, long c)
{ {
return static_cast<type>(std::abs(m(r,c))); return static_cast<type>(std::abs(this->m(r,c)));
} }
}; };
};
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_abs> abs ( const matrix_op<op_abs<EXP> > abs (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_abs> exp; typedef op_abs<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_complex_matrix
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+1;
typedef std::complex<typename EXP::type> type;
typedef const std::complex<typename EXP::type> const_ret_type;
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, long r, long c) struct op_complex_matrix : basic_op_m<M>
{
op_complex_matrix( const M& m_) : basic_op_m<M>(m_){}
const static long cost = M::cost+1;
typedef std::complex<typename M::type> type;
typedef const std::complex<typename M::type> const_ret_type;
const_ret_type apply ( long r, long c) const
{ {
return type(m(r,c)); return type(this->m(r,c));
} }
}; };
};
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_complex_matrix> complex_matrix ( const matrix_op<op_complex_matrix<EXP> > complex_matrix (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
return matrix_unary_exp<EXP,op_complex_matrix>(m.ref()); typedef op_complex_matrix<EXP> op;
return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_complex_matrix2 template <typename M1, typename M2>
{ struct op_complex_matrix2 : basic_op_mm<M1,M2>
template <typename EXP1, typename EXP2>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP1,EXP2>
{ {
const static long cost = EXP1::cost+EXP2::cost+1; op_complex_matrix2( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){}
typedef std::complex<typename EXP1::type> type;
typedef const std::complex<typename EXP1::type> const_ret_type;
template <typename M1, typename M2> const static long cost = M1::cost+M2::cost+1;
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c) typedef std::complex<typename M1::type> type;
{ return type(m1(r,c),m2(r,c)); } typedef const std::complex<typename M1::type> const_ret_type;
};
const_ret_type apply ( long r, long c) const
{ return type(this->m1(r,c), this->m2(r,c)); }
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
const matrix_binary_exp<EXP1,EXP2,op_complex_matrix2> complex_matrix ( const matrix_op<op_complex_matrix2<EXP1,EXP2> > complex_matrix (
const matrix_exp<EXP1>& real_part, const matrix_exp<EXP1>& real_part,
const matrix_exp<EXP2>& imag_part const matrix_exp<EXP2>& imag_part
) )
...@@ -532,89 +350,84 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan,7) ...@@ -532,89 +350,84 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan,7)
<< "\n\timag_part.nr(): " << imag_part.nr() << "\n\timag_part.nr(): " << imag_part.nr()
<< "\n\timag_part.nc(): " << imag_part.nc() << "\n\timag_part.nc(): " << imag_part.nc()
); );
typedef matrix_binary_exp<EXP1,EXP2,op_complex_matrix2> exp;
return exp(real_part.ref(),imag_part.ref()); typedef op_complex_matrix2<EXP1,EXP2> op;
return matrix_op<op>(op(real_part.ref(),imag_part.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_norm
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+6;
typedef typename EXP::type::value_type type;
typedef const typename EXP::type::value_type const_ret_type;
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, long r, long c) struct op_norm : basic_op_m<M>
{ return std::norm(m(r,c)); } {
}; op_norm( const M& m_) : basic_op_m<M>(m_){}
const static long cost = M::cost+6;
typedef typename M::type::value_type type;
typedef const typename M::type::value_type const_ret_type;
const_ret_type apply ( long r, long c) const
{ return std::norm(this->m(r,c)); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_norm> norm ( const matrix_op<op_norm<EXP> > norm (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_norm> exp; typedef op_norm<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_real
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost;
typedef typename EXP::type::value_type type;
typedef const typename EXP::type::value_type const_ret_type;
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, long r, long c) struct op_real : basic_op_m<M>
{ return std::real(m(r,c)); } {
}; op_real( const M& m_) : basic_op_m<M>(m_){}
const static long cost = M::cost;
typedef typename M::type::value_type type;
typedef const typename M::type::value_type const_ret_type;
const_ret_type apply ( long r, long c) const
{ return std::real(this->m(r,c)); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_real> real ( const matrix_op<op_real<EXP> > real (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_real> exp; typedef op_real<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_imag
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost;
typedef typename EXP::type::value_type type;
typedef const typename EXP::type::value_type const_ret_type;
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, long r, long c) struct op_imag : basic_op_m<M>
{ return std::imag(m(r,c)); } {
}; op_imag( const M& m_) : basic_op_m<M>(m_){}
const static long cost = M::cost;
typedef typename M::type::value_type type;
typedef const typename M::type::value_type const_ret_type;
const_ret_type apply (long r, long c) const
{ return std::imag(this->m(r,c)); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_imag> imag ( const matrix_op<op_imag<EXP> > imag (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_imag> exp; typedef op_imag<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATRIx_OP_H_
#define DLIB_MATRIx_OP_H_
#include "matrix_exp.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <typename OP >
class matrix_op;
template < typename OP >
struct matrix_traits<matrix_op<OP> >
{
typedef typename OP::type type;
typedef typename OP::const_ret_type const_ret_type;
typedef typename OP::mem_manager_type mem_manager_type;
typedef typename OP::layout_type layout_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
template <
typename OP
>
class matrix_op : public matrix_exp<matrix_op<OP> >
{
/*!
!*/
public:
typedef typename matrix_traits<matrix_op>::type type;
typedef typename matrix_traits<matrix_op>::const_ret_type const_ret_type;
typedef typename matrix_traits<matrix_op>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<matrix_op>::layout_type layout_type;
const static long NR = matrix_traits<matrix_op>::NR;
const static long NC = matrix_traits<matrix_op>::NC;
const static long cost = matrix_traits<matrix_op>::cost;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of object.
template <typename T1>
matrix_op (T1);
public:
matrix_op (
const OP& op_
) :
op(op_)
{}
const_ret_type operator() (
long r,
long c
) const { return op.apply(r,c); }
const_ret_type operator() ( long i ) const
{ return matrix_exp<matrix_op>::operator()(i); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return op.aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return op.destructively_aliases(item); }
long nr (
) const { return op.nr(); }
long nc (
) const { return op.nc(); }
const OP op;
};
// ----------------------------------------------------------------------------------------
struct does_not_alias
{
/*!
This is a partial implementation of a matrix operator that never aliases
another expression.
!*/
template <typename U> bool aliases ( const U& ) const { return false; }
template <typename U> bool destructively_aliases ( const U& ) const { return false; }
};
// ----------------------------------------------------------------------------------------
template <typename M>
struct basic_op_m
{
/*!
This is a partial implementation of a matrix operator that preserves
the dimensions of its argument and doesn't have destructive aliasing.
!*/
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of object.
template <typename T1>
basic_op_m (T1);
public:
basic_op_m(
const M& m_
) : m(m_){}
const M& m;
const static long NR = M::NR;
const static long NC = M::NC;
typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
long nr () const { return m.nr(); }
long nc () const { return m.nc(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const
{ return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m.destructively_aliases(item); }
};
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct basic_op_mm
{
/*!
This is a partial implementation of a matrix operator that preserves
the dimensions of its arguments and doesn't have destructive aliasing.
!*/
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of object.
template <typename T1, typename T2>
basic_op_mm (T1, T2);
public:
basic_op_mm(
const M1& m1_,
const M2& m2_
) : m1(m1_), m2(m2_){}
const M1& m1;
const M2& m2;
const static long NR = M1::NR;
const static long NC = M1::NC;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
long nr () const { return m1.nr(); }
long nc () const { return m1.nc(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || m2.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.destructively_aliases(item) || m2.destructively_aliases(item); }
};
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2, typename M3>
struct basic_op_mmm
{
/*!
This is a partial implementation of a matrix operator that preserves
the dimensions of its arguments and doesn't have destructive aliasing.
!*/
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of object.
template <typename T1, typename T2, typename T3>
basic_op_mmm (T1, T2, T3);
public:
basic_op_mmm(
const M1& m1_,
const M2& m2_,
const M3& m3_
) : m1(m1_), m2(m2_), m3(m3_){}
const M1& m1;
const M2& m2;
const M3& m3;
const static long NR = M1::NR;
const static long NC = M1::NC;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
long nr () const { return m1.nr(); }
long nc () const { return m1.nc(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || m2.aliases(item) || m3.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.destructively_aliases(item) || m2.destructively_aliases(item) ||
m3.destructively_aliases(item);}
};
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2, typename M3, typename M4>
struct basic_op_mmmm
{
/*!
This is a partial implementation of a matrix operator that preserves
the dimensions of its arguments and doesn't have destructive aliasing.
!*/
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of object.
template <typename T1, typename T2, typename T3, typename T4>
basic_op_mmmm (T1, T2, T3, T4);
public:
basic_op_mmmm(
const M1& m1_,
const M2& m2_,
const M3& m3_,
const M4& m4_
) : m1(m1_), m2(m2_), m3(m3_), m4(m4_){}
const M1& m1;
const M2& m2;
const M3& m3;
const M4& m4;
const static long NR = M1::NR;
const static long NC = M1::NC;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
long nr () const { return m1.nr(); }
long nc () const { return m1.nc(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) || m4.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.destructively_aliases(item) || m2.destructively_aliases(item) ||
m3.destructively_aliases(item) || m4.destructively_aliases(item);}
};
// ----------------------------------------------------------------------------------------
#define DLIB_DEFINE_OP_M(op_name, function, extra_cost) \
template <typename M> \
struct op_name \
{ \
op_name( \
const M& m_ \
) : m(m_){} \
\
const M& m; \
\
const static long cost = M::cost+(extra_cost); \
const static long NR = M::NR; \
const static long NC = M::NC; \
typedef typename M::type type; \
typedef const typename M::type const_ret_type; \
typedef typename M::mem_manager_type mem_manager_type; \
typedef typename M::layout_type layout_type; \
\
const_ret_type apply (long r, long c) const { return function(m(r,c)); } \
\
long nr () const { return m.nr(); } \
long nc () const { return m.nc(); } \
\
template <typename U> bool aliases ( const matrix_exp<U>& item) const \
{ return m.aliases(item); } \
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const \
{ return m.destructively_aliases(item); } \
\
};
#define DLIB_DEFINE_FUNCTION_M(op_name, name, function, extra_cost) \
DLIB_DEFINE_OP_M(op_name, function, extra_cost) \
template < typename M > \
const matrix_op<op_name<M> > name ( const matrix_exp<M>& m) \
{ \
typedef op_name<M> op; \
return matrix_op<op>(op(m.ref())); \
}
// ----------------------------------------------------------------------------------------
#define DLIB_DEFINE_OP_MS(op_name, function, extra_cost) \
template <typename M, typename S> \
struct op_name \
{ \
op_name( \
const M& m_, \
const S& s_ \
) : m(m_), s(s_){} \
\
const M& m; \
const S s; \
\
const static long cost = M::cost+(extra_cost); \
const static long NR = M::NR; \
const static long NC = M::NC; \
typedef typename M::type type; \
typedef const typename M::type const_ret_type; \
typedef typename M::mem_manager_type mem_manager_type; \
typedef typename M::layout_type layout_type; \
\
const_ret_type apply (long r, long c) const { return function(m(r,c), s); } \
\
long nr () const { return m.nr(); } \
long nc () const { return m.nc(); } \
\
template <typename U> bool aliases ( const matrix_exp<U>& item) const \
{ return m.aliases(item); } \
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const \
{ return m.destructively_aliases(item); } \
\
};
#define DLIB_DEFINE_FUNCTION_MS(op_name, name, function, extra_cost) \
DLIB_DEFINE_OP_MS(op_name, function, extra_cost) \
template < typename M, typename S > \
const matrix_op<op_name<M, S> > name ( const matrix_exp<M>& m, const S& s) \
{ \
typedef op_name<M, S> op; \
return matrix_op<op>(op(m.ref(), s)); \
}
// ----------------------------------------------------------------------------------------
#define DLIB_DEFINE_OP_SM(op_name, function, extra_cost) \
template <typename S, typename M> \
struct op_name \
{ \
op_name( \
const S& s_, \
const M& m_ \
) : m(m_), s(s_){} \
\
const M& m; \
const S s; \
\
const static long cost = M::cost+(extra_cost); \
const static long NR = M::NR; \
const static long NC = M::NC; \
typedef typename M::type type; \
typedef const typename M::type const_ret_type; \
typedef typename M::mem_manager_type mem_manager_type; \
typedef typename M::layout_type layout_type; \
\
const_ret_type apply (long r, long c) const { return function(s, m(r,c)); } \
\
long nr () const { return m.nr(); } \
long nc () const { return m.nc(); } \
\
template <typename U> bool aliases ( const matrix_exp<U>& item) const \
{ return m.aliases(item); } \
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const \
{ return m.destructively_aliases(item); } \
\
};
#define DLIB_DEFINE_FUNCTION_SM(op_name, name, function, extra_cost) \
DLIB_DEFINE_OP_SM(op_name, function, extra_cost) \
template < typename S, typename M > \
const matrix_op<op_name<S, M> > name (const S& s, const matrix_exp<M>& m) \
{ \
typedef op_name<S, M> op; \
return matrix_op<op>(op(s, m.ref())); \
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_OP_H_
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define DLIB_MATRIx_SUBEXP_ #define DLIB_MATRIx_SUBEXP_
#include "matrix_subexp_abstract.h" #include "matrix_subexp_abstract.h"
#include "matrix_op.h"
#include "matrix.h" #include "matrix.h"
#include "../geometry/rectangle.h" #include "../geometry/rectangle.h"
#include "matrix_expressions.h" #include "matrix_expressions.h"
...@@ -59,10 +60,44 @@ namespace dlib ...@@ -59,10 +60,44 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_subm
{
op_subm (
const M& m_,
const long& r__,
const long& c__,
const long& nr__,
const long& nc__
) : m(m_), r_(r__), c_(c__), nr_(nr__), nc_(nc__) { }
const M& m;
const long r_;
const long c_;
const long nr_;
const long nc_;
const static long cost = M::cost+1;
typedef typename M::type type;
typedef typename M::const_ret_type const_ret_type;
typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
const static long NR = 0;
const static long NC = 0;
const_ret_type apply ( long r, long c) const { return m(r+r_,c+c_); }
long nr () const { return nr_; }
long nc () const { return nc_; }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
};
template < template <
typename EXP typename EXP
> >
const matrix_sub_exp<EXP> subm ( const matrix_op<op_subm<EXP> > subm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
long r, long r,
long c, long c,
...@@ -81,8 +116,8 @@ namespace dlib ...@@ -81,8 +116,8 @@ namespace dlib
<< "\n\tnc: " << nc << "\n\tnc: " << nc
); );
typedef matrix_sub_exp<EXP> exp; typedef op_subm<EXP> op;
return exp(m.ref(),r,c,nr,nc); return matrix_op<op>(op(m.ref(),r,c,nr,nc));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -90,7 +125,7 @@ namespace dlib ...@@ -90,7 +125,7 @@ namespace dlib
template < template <
typename EXP typename EXP
> >
const matrix_sub_exp<EXP> subm ( const matrix_op<op_subm<EXP> > subm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const rectangle& rect const rectangle& rect
) )
...@@ -106,18 +141,46 @@ namespace dlib ...@@ -106,18 +141,46 @@ namespace dlib
<< "\n\trect.bottom(): " << rect.bottom() << "\n\trect.bottom(): " << rect.bottom()
); );
typedef matrix_sub_exp<EXP> exp; typedef op_subm<EXP> op;
return exp(m.ref(),rect.top(),rect.left(),rect.height(),rect.width()); return matrix_op<op>(op(m.ref(),rect.top(),rect.left(),rect.height(),rect.width()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M1, typename M2, typename M3>
struct op_subm_range
{
op_subm_range( const M1& m1_, const M2& rows_, const M3& cols_) :
m1(m1_), rows(rows_), cols(cols_) {}
const M1& m1;
const M2& rows;
const M3& cols;
const static long cost = M1::cost+M2::cost+M3::cost;
typedef typename M1::type type;
typedef typename M1::const_ret_type const_ret_type;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
const static long NR = M2::NC*M2::NR;
const static long NC = M3::NC*M3::NR;
const_ret_type apply ( long r, long c) const { return m1(rows(r),cols(c)); }
long nr () const { return rows.size(); }
long nc () const { return cols.size(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || rows.aliases(item) || cols.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || rows.aliases(item) || cols.aliases(item); }
};
template < template <
typename EXP, typename EXP,
typename EXPr, typename EXPr,
typename EXPc typename EXPc
> >
const matrix_sub_range_exp<EXP,EXPr,EXPc> subm ( const matrix_op<op_subm_range<EXP,EXPr,EXPc> > subm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const matrix_exp<EXPr>& rows, const matrix_exp<EXPr>& rows,
const matrix_exp<EXPc>& cols const matrix_exp<EXPc>& cols
...@@ -143,38 +206,39 @@ namespace dlib ...@@ -143,38 +206,39 @@ namespace dlib
<< "\n\tcols.nc(): " << cols.nc() << "\n\tcols.nc(): " << cols.nc()
); );
typedef matrix_sub_range_exp<EXP,EXPr,EXPc> exp; typedef op_subm_range<EXP,EXPr,EXPc> op;
return exp(m.ref(),rows.ref(),cols.ref()); return matrix_op<op>(op(m.ref(),rows.ref(),cols.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_rowm struct op_rowm
{ {
template <typename EXP> op_rowm(const M& m_, const long& row_) : m(m_), row(row_) {}
struct op : has_destructive_aliasing const M& m;
{ const long row;
const static long cost = EXP::cost;
const static long NR = 1;
const static long NC = EXP::NC;
typedef typename EXP::type type;
typedef typename EXP::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type;
template <typename M>
static const_ret_type apply ( const M& m, long row, long, long c)
{ return m(row,c); }
template <typename M> const static long cost = M::cost;
static long nr (const M& ) { return 1; } const static long NR = 1;
template <typename M> const static long NC = M::NC;
static long nc (const M& m) { return m.nc(); } typedef typename M::type type;
}; typedef typename M::const_ret_type const_ret_type;
typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
const_ret_type apply ( long, long c) const { return m(row,c); }
long nr () const { return 1; }
long nc () const { return m.nc(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_scalar_binary_exp<EXP,long,op_rowm> rowm ( const matrix_op<op_rowm<EXP> > rowm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
long row long row
) )
...@@ -187,38 +251,40 @@ namespace dlib ...@@ -187,38 +251,40 @@ namespace dlib
<< "\n\trow: " << row << "\n\trow: " << row
); );
typedef matrix_scalar_binary_exp<EXP,long,op_rowm> exp; typedef op_rowm<EXP> op;
return exp(m.ref(),row); return matrix_op<op>(op(m.ref(),row));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_rowm2 struct op_rowm2
{ {
template <typename EXP> op_rowm2(const M& m_, const long& row_, const long& len) : m(m_), row(row_), length(len) {}
struct op : has_destructive_aliasing const M& m;
{ const long row;
const static long cost = EXP::cost; const long length;
const static long cost = M::cost;
const static long NR = 1; const static long NR = 1;
const static long NC = 0; const static long NC = 0;
typedef typename EXP::type type; typedef typename M::type type;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long row, long , long , long c) const_ret_type apply ( long , long c) const { return m(row,c); }
{ return m(row,c); }
template <typename M> long nr () const { return 1; }
static long nr (const M& , long, long) { return 1; } long nc () const { return length; }
template <typename M>
static long nc (const M& , long, long length) { return length; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_scalar_ternary_exp<EXP,long,op_rowm2> rowm ( const matrix_op<op_rowm2<EXP> > rowm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
long row, long row,
long length long length
...@@ -234,40 +300,43 @@ namespace dlib ...@@ -234,40 +300,43 @@ namespace dlib
<< "\n\tlength: " << length << "\n\tlength: " << length
); );
typedef matrix_scalar_ternary_exp<EXP,long,op_rowm2> exp; typedef op_rowm2<EXP> op;
return exp(m.ref(),row, length); return matrix_op<op>(op(m.ref(), row, length));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_rowm_range struct op_rowm_range
{ {
template <typename EXP1, typename EXP2> op_rowm_range( const M1& m1_, const M2& rows_) : m1(m1_), rows(rows_) {}
struct op : has_destructive_aliasing const M1& m1;
{ const M2& rows;
const static long cost = EXP1::cost+EXP2::cost;
typedef typename EXP1::type type;
typedef typename EXP1::const_ret_type const_ret_type;
typedef typename EXP1::mem_manager_type mem_manager_type;
const static long NR = EXP2::NC*EXP2::NR;
const static long NC = EXP1::NC;
template <typename M1, typename M2> const static long cost = M1::cost+M2::cost;
static const_ret_type apply ( const M1& m1, const M2& rows , long r, long c) typedef typename M1::type type;
{ return m1(rows(r),c); } typedef typename M1::const_ret_type const_ret_type;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
const static long NR = M2::NC*M2::NR;
const static long NC = M1::NC;
template <typename M1, typename M2> const_ret_type apply ( long r, long c) const { return m1(rows(r),c); }
static long nr (const M1& , const M2& rows ) { return rows.size(); }
template <typename M1, typename M2> long nr () const { return rows.size(); }
static long nc (const M1& m1, const M2& ) { return m1.nc(); } long nc () const { return m1.nc(); }
};
template <typename U> bool aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || rows.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || rows.aliases(item); }
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
const matrix_binary_exp<EXP1,EXP2,op_rowm_range> rowm ( const matrix_op<op_rowm_range<EXP1,EXP2> > rowm (
const matrix_exp<EXP1>& m, const matrix_exp<EXP1>& m,
const matrix_exp<EXP2>& rows const matrix_exp<EXP2>& rows
) )
...@@ -286,38 +355,39 @@ namespace dlib ...@@ -286,38 +355,39 @@ namespace dlib
<< "\n\trows.nc(): " << rows.nc() << "\n\trows.nc(): " << rows.nc()
); );
typedef matrix_binary_exp<EXP1,EXP2,op_rowm_range> exp; typedef op_rowm_range<EXP1,EXP2> op;
return exp(m.ref(),rows.ref()); return matrix_op<op>(op(m.ref(),rows.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_colm struct op_colm
{ {
template <typename EXP> op_colm(const M& m_, const long& col_) : m(m_), col(col_) {}
struct op : has_destructive_aliasing const M& m;
{ const long col;
const static long cost = EXP::cost;
const static long NR = EXP::NR; const static long cost = M::cost;
const static long NR = M::NR;
const static long NC = 1; const static long NC = 1;
typedef typename EXP::type type; typedef typename M::type type;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long col, long r, long) const_ret_type apply ( long r, long) const { return m(r,col); }
{ return m(r,col); }
template <typename M> long nr () const { return m.nr(); }
static long nr (const M& m) { return m.nr(); } long nc () const { return 1; }
template <typename M>
static long nc (const M& ) { return 1; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_scalar_binary_exp<EXP,long,op_colm> colm ( const matrix_op<op_colm<EXP> > colm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
long col long col
) )
...@@ -330,38 +400,40 @@ namespace dlib ...@@ -330,38 +400,40 @@ namespace dlib
<< "\n\tcol: " << col << "\n\tcol: " << col
); );
typedef matrix_scalar_binary_exp<EXP,long,op_colm> exp; typedef op_colm<EXP> op;
return exp(m.ref(),col); return matrix_op<op>(op(m.ref(),col));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_colm2 struct op_colm2
{ {
template <typename EXP> op_colm2(const M& m_, const long& col_, const long& len) : m(m_), col(col_), length(len) {}
struct op : has_destructive_aliasing const M& m;
{ const long col;
const static long cost = EXP::cost; const long length;
const static long cost = M::cost;
const static long NR = 0; const static long NR = 0;
const static long NC = 1; const static long NC = 1;
typedef typename EXP::type type; typedef typename M::type type;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long col, long , long r, long ) const_ret_type apply ( long r, long ) const { return m(r,col); }
{ return m(r,col); }
template <typename M> long nr () const { return length; }
static long nr (const M&, long, long length) { return length; } long nc () const { return 1; }
template <typename M>
static long nc (const M&, long, long) { return 1; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_scalar_ternary_exp<EXP,long,op_colm2> colm ( const matrix_op<op_colm2<EXP> > colm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
long col, long col,
long length long length
...@@ -377,40 +449,43 @@ namespace dlib ...@@ -377,40 +449,43 @@ namespace dlib
<< "\n\tlength: " << length << "\n\tlength: " << length
); );
typedef matrix_scalar_ternary_exp<EXP,long,op_colm2> exp; typedef op_colm2<EXP> op;
return exp(m.ref(),col, length); return matrix_op<op>(op(m.ref(),col, length));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_colm_range struct op_colm_range
{ {
template <typename EXP1, typename EXP2> op_colm_range( const M1& m1_, const M2& cols_) : m1(m1_), cols(cols_) {}
struct op : has_destructive_aliasing const M1& m1;
{ const M2& cols;
typedef typename EXP1::type type;
typedef typename EXP1::const_ret_type const_ret_type;
typedef typename EXP1::mem_manager_type mem_manager_type;
const static long NR = EXP1::NR;
const static long NC = EXP2::NC*EXP2::NR;
const static long cost = EXP1::cost+EXP2::cost;
template <typename M1, typename M2> typedef typename M1::type type;
static const_ret_type apply ( const M1& m1, const M2& cols , long r, long c) typedef typename M1::const_ret_type const_ret_type;
{ return m1(r,cols(c)); } typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
const static long NR = M1::NR;
const static long NC = M2::NC*M2::NR;
const static long cost = M1::cost+M2::cost;
template <typename M1, typename M2> const_ret_type apply (long r, long c) const { return m1(r,cols(c)); }
static long nr (const M1& m1, const M2& ) { return m1.nr(); }
template <typename M1, typename M2> long nr () const { return m1.nr(); }
static long nc (const M1& , const M2& cols ) { return cols.size(); } long nc () const { return cols.size(); }
};
template <typename U> bool aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || cols.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || cols.aliases(item); }
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
const matrix_binary_exp<EXP1,EXP2,op_colm_range> colm ( const matrix_op<op_colm_range<EXP1,EXP2> > colm (
const matrix_exp<EXP1>& m, const matrix_exp<EXP1>& m,
const matrix_exp<EXP2>& cols const matrix_exp<EXP2>& cols
) )
...@@ -429,8 +504,8 @@ namespace dlib ...@@ -429,8 +504,8 @@ namespace dlib
<< "\n\tcols.nc(): " << cols.nc() << "\n\tcols.nc(): " << cols.nc()
); );
typedef matrix_binary_exp<EXP1,EXP2,op_colm_range> exp; typedef op_colm_range<EXP1,EXP2> op;
return exp(m.ref(),cols.ref()); return matrix_op<op>(op(m.ref(),cols.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "../std_allocator.h" #include "../std_allocator.h"
#include "matrix_expressions.h" #include "matrix_expressions.h"
#include "matrix_math_functions.h" #include "matrix_math_functions.h"
#include "matrix_op.h"
namespace dlib namespace dlib
...@@ -268,29 +269,72 @@ namespace dlib ...@@ -268,29 +269,72 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename T>
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(); }
};
template < template <
typename array_type typename array_type
> >
const typename disable_if<is_matrix<array_type>,matrix_array2d_exp<array_type> >::type const typename disable_if<is_matrix<array_type>,matrix_op<op_array2d_to_mat<array_type> > >::type
array_to_matrix ( array_to_matrix (
const array_type& array const array_type& array
) )
{ {
return matrix_array2d_exp<array_type>(array); typedef op_array2d_to_mat<array_type> op;
return matrix_op<op>(op(array));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename T>
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 < template <
typename vector_type typename vector_type
> >
const typename disable_if<is_matrix<vector_type>,matrix_array_exp<vector_type> >::type const typename disable_if<is_matrix<vector_type>, matrix_op<op_array_to_mat<vector_type> > >::type
vector_to_matrix ( vector_to_matrix (
const vector_type& vector const vector_type& vector
) )
{ {
typedef matrix_array_exp<vector_type> exp; typedef op_array_to_mat<vector_type> op;
return exp(vector); return matrix_op<op>(op(vector));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -311,16 +355,37 @@ namespace dlib ...@@ -311,16 +355,37 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename T>
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;
typedef const typename T::value_type& const_ret_type;
typedef memory_manager<char>::kernel_1a 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 < template <
typename value_type, typename value_type,
typename alloc typename alloc
> >
const matrix_std_vector_exp<std::vector<value_type,alloc> > vector_to_matrix ( const matrix_op<op_std_vect_to_mat<std::vector<value_type,alloc> > > vector_to_matrix (
const std::vector<value_type,alloc>& vector const std::vector<value_type,alloc>& vector
) )
{ {
typedef matrix_std_vector_exp<std::vector<value_type,alloc> > exp; typedef op_std_vect_to_mat<std::vector<value_type,alloc> > op;
return exp(vector); return matrix_op<op>(op(vector));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -329,35 +394,45 @@ namespace dlib ...@@ -329,35 +394,45 @@ namespace dlib
typename value_type, typename value_type,
typename alloc typename alloc
> >
const matrix_std_vector_exp<std_vector_c<value_type,alloc> > vector_to_matrix ( const matrix_op<op_std_vect_to_mat<std_vector_c<value_type,alloc> > > vector_to_matrix (
const std_vector_c<value_type,alloc>& vector const std_vector_c<value_type,alloc>& vector
) )
{ {
typedef matrix_std_vector_exp<std_vector_c<value_type,alloc> > exp; typedef op_std_vect_to_mat<std_vector_c<value_type,alloc> > op;
return exp(vector); return matrix_op<op>(op(vector));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <typename T>
typename T struct op_pointer_to_col_vect : does_not_alias
>
struct op_pointer_to_col_vect : has_nondestructive_aliasing
{ {
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 cost = 1;
const static long NR = 0; const static long NR = 0;
const static long NC = 1; const static long NC = 1;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
typedef T type; typedef T type;
typedef const T& const_ret_type; typedef const T& const_ret_type;
static const_ret_type apply (const T* val, long r, long, long, long ) typedef memory_manager<char>::kernel_1a mem_manager_type;
{ return val[r]; } 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 < template <
typename T typename T
> >
const dynamic_matrix_scalar_unary_exp<const T*,op_pointer_to_col_vect<T> > pointer_to_column_vector ( const matrix_op<op_pointer_to_col_vect<T> > pointer_to_column_vector (
const T* ptr, const T* ptr,
long nr long nr
) )
...@@ -367,31 +442,43 @@ namespace dlib ...@@ -367,31 +442,43 @@ namespace dlib
<< "\n\t nr must be bigger than 0" << "\n\t nr must be bigger than 0"
<< "\n\t nr: " << nr << "\n\t nr: " << nr
); );
typedef dynamic_matrix_scalar_unary_exp<const T*,op_pointer_to_col_vect<T> > exp; typedef op_pointer_to_col_vect<T> op;
return exp(nr,1,ptr); return matrix_op<op>(op(ptr, nr));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <typename T>
typename T struct op_pointer_to_mat : does_not_alias
>
struct op_pointer_to_mat : has_nondestructive_aliasing
{ {
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 cost = 1;
const static long NR = 0; const static long NR = 0;
const static long NC = 0; const static long NC = 0;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
typedef T type; typedef T type;
typedef const T& const_ret_type; typedef const T& const_ret_type;
static const_ret_type apply (const T* val, long r, long c, long , long nc ) typedef memory_manager<char>::kernel_1a mem_manager_type;
{ return val[r*nc + c]; } 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 < template <
typename T typename T
> >
const dynamic_matrix_scalar_unary_exp<const T*,op_pointer_to_mat<T> > pointer_to_matrix ( const matrix_op<op_pointer_to_mat<T> > pointer_to_matrix (
const T* ptr, const T* ptr,
long nr, long nr,
long nc long nc
...@@ -403,45 +490,47 @@ namespace dlib ...@@ -403,45 +490,47 @@ namespace dlib
<< "\n\t nr: " << nr << "\n\t nr: " << nr
<< "\n\t nc: " << nc << "\n\t nc: " << nc
); );
typedef dynamic_matrix_scalar_unary_exp<const T*,op_pointer_to_mat<T> > exp; typedef op_pointer_to_mat<T> op;
return exp(nr,nc,ptr); return matrix_op<op>(op(ptr,nr,nc));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_trans struct op_trans
{ {
template <typename EXP> op_trans( const M& m_) : m(m_){}
struct op : has_destructive_aliasing
{ const M& m;
const static long cost = EXP::cost;
const static long NR = EXP::NC; const static long cost = M::cost;
const static long NC = EXP::NR; const static long NR = M::NC;
typedef typename EXP::type type; const static long NC = M::NR;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::type type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::const_ret_type const_ret_type;
template <typename M> typedef typename M::mem_manager_type mem_manager_type;
static const_ret_type apply ( const M& m, long r, long c) typedef typename M::layout_type layout_type;
{ return m(c,r); }
const_ret_type apply (long r, long c) const { return m(c,r); }
long nr () const { return m.nc(); }
long nc () const { return m.nr(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename M>
static long nr (const M& m) { return m.nc(); }
template <typename M>
static long nc (const M& m) { return m.nr(); }
};
}; };
template < template <
typename EXP typename M
> >
const matrix_unary_exp<EXP,op_trans> trans ( const matrix_op<op_trans<M> > trans (
const matrix_exp<EXP>& m const matrix_exp<M>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_trans> exp; typedef op_trans<M> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// I introduced this struct because it avoids an inane compiler warning from gcc // I introduced this struct because it avoids an inane compiler warning from gcc
...@@ -540,20 +629,21 @@ namespace dlib ...@@ -540,20 +629,21 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <long R, long C> template <typename M, long R, long C>
struct op_removerc struct op_removerc
{ {
template <typename EXP> op_removerc( const M& m_) : m(m_){}
struct op : has_destructive_aliasing
{ const M& m;
const static long cost = EXP::cost+2;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1); const static long cost = M::cost+2;
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1); const static long NR = (M::NR==0) ? 0 : (M::NR - 1);
typedef typename EXP::type type; const static long NC = (M::NC==0) ? 0 : (M::NC - 1);
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::type type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::const_ret_type const_ret_type;
template <typename M> typedef typename M::mem_manager_type mem_manager_type;
static const_ret_type apply ( const M& m, long r, long c) typedef typename M::layout_type layout_type;
const_ret_type apply (long r, long c) const
{ {
if (r < R) if (r < R)
{ {
...@@ -571,26 +661,29 @@ namespace dlib ...@@ -571,26 +661,29 @@ namespace dlib
} }
} }
template <typename M> long nr () const { return m.nr() - 1; }
static long nr (const M& m) { return m.nr() - 1; } long nc () const { return m.nc() - 1; }
template <typename M>
static long nc (const M& m) { return m.nc() - 1; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template <typename M>
struct op_removerc2 struct op_removerc2
{ {
template <typename EXP> op_removerc2( const M& m_, const long R_, const long C_) : m(m_), R(R_), C(C_){}
struct op : has_destructive_aliasing const M& m;
{ const long R;
const static long cost = EXP::cost+2; const long C;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1);
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1); const static long cost = M::cost+2;
typedef typename EXP::type type; const static long NR = (M::NR==0) ? 0 : (M::NR - 1);
typedef typename EXP::const_ret_type const_ret_type; const static long NC = (M::NC==0) ? 0 : (M::NC - 1);
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::type type;
template <typename M> typedef typename M::const_ret_type const_ret_type;
static const_ret_type apply ( const M& m, long R, long C, long r, long c) typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
const_ret_type apply (long r, long c) const
{ {
if (r < R) if (r < R)
{ {
...@@ -608,11 +701,11 @@ namespace dlib ...@@ -608,11 +701,11 @@ namespace dlib
} }
} }
template <typename M, typename S> long nr () const { return m.nr() - 1; }
static long nr (const M& m, S&, S&) { return m.nr() - 1; } long nc () const { return m.nc() - 1; }
template <typename M, typename S>
static long nc (const M& m, S&, S&) { return m.nc() - 1; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
...@@ -620,7 +713,7 @@ namespace dlib ...@@ -620,7 +713,7 @@ namespace dlib
long C, long C,
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_removerc<R,C> > removerc ( const matrix_op<op_removerc<EXP,R,C> > removerc (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
...@@ -636,14 +729,14 @@ namespace dlib ...@@ -636,14 +729,14 @@ namespace dlib
<< "\n\tR: " << R << "\n\tR: " << R
<< "\n\tC: " << C << "\n\tC: " << C
); );
typedef matrix_unary_exp<EXP,op_removerc<R,C> > exp; typedef op_removerc<EXP,R,C> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
template < template <
typename EXP typename EXP
> >
const matrix_scalar_ternary_exp<EXP,long,op_removerc2> removerc ( const matrix_op<op_removerc2<EXP> > removerc (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
long R, long R,
long C long C
...@@ -657,26 +750,26 @@ namespace dlib ...@@ -657,26 +750,26 @@ namespace dlib
<< "\n\tR: " << R << "\n\tR: " << R
<< "\n\tC: " << C << "\n\tC: " << C
); );
typedef matrix_scalar_ternary_exp<EXP,long,op_removerc2 > exp; typedef op_removerc2<EXP> op;
return exp(m.ref(),R,C); return matrix_op<op>(op(m.ref(),R,C));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <long C> template <typename M, long C>
struct op_remove_col struct op_remove_col
{ {
template <typename EXP> op_remove_col( const M& m_) : m(m_){}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost+1; const static long cost = M::cost+1;
const static long NR = EXP::NR; const static long NR = M::NR;
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1); const static long NC = (M::NC==0) ? 0 : (M::NC - 1);
typedef typename EXP::type type; typedef typename M::type type;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long r, long c) const_ret_type apply ( long r, long c) const
{ {
if (c < C) if (c < C)
{ {
...@@ -688,26 +781,28 @@ namespace dlib ...@@ -688,26 +781,28 @@ namespace dlib
} }
} }
template <typename M> long nr () const { return m.nr(); }
static long nr (const M& m) { return m.nr(); } long nc () const { return m.nc() - 1; }
template <typename M>
static long nc (const M& m) { return m.nc() - 1; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template <typename M>
struct op_remove_col2 struct op_remove_col2
{ {
template <typename EXP> op_remove_col2( const M& m_, const long C_) : m(m_), C(C_){}
struct op : has_destructive_aliasing const M& m;
{ const long C;
const static long cost = EXP::cost+1;
const static long NR = EXP::NR; const static long cost = M::cost+1;
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1); const static long NR = M::NR;
typedef typename EXP::type type; const static long NC = (M::NC==0) ? 0 : (M::NC - 1);
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::type type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::const_ret_type const_ret_type;
template <typename M> typedef typename M::mem_manager_type mem_manager_type;
static const_ret_type apply ( const M& m, long C, long r, long c) typedef typename M::layout_type layout_type;
const_ret_type apply ( long r, long c) const
{ {
if (c < C) if (c < C)
{ {
...@@ -719,18 +814,18 @@ namespace dlib ...@@ -719,18 +814,18 @@ namespace dlib
} }
} }
template <typename M> long nr () const { return m.nr(); }
static long nr (const M& m) { return m.nr(); } long nc () const { return m.nc() - 1; }
template <typename M>
static long nc (const M& m) { return m.nc() - 1; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
long C, long C,
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_remove_col<C> > remove_col ( const matrix_op<op_remove_col<EXP, C> > remove_col (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
...@@ -744,14 +839,14 @@ namespace dlib ...@@ -744,14 +839,14 @@ namespace dlib
<< "\n\tm.nc(): " << m.nc() << "\n\tm.nc(): " << m.nc()
<< "\n\tC: " << C << "\n\tC: " << C
); );
typedef matrix_unary_exp<EXP,op_remove_col<C> > exp; typedef op_remove_col<EXP,C> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
template < template <
typename EXP typename EXP
> >
const matrix_scalar_binary_exp<EXP,long,op_remove_col2> remove_col ( const matrix_op<op_remove_col2<EXP> > remove_col (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
long C long C
) )
...@@ -763,26 +858,26 @@ namespace dlib ...@@ -763,26 +858,26 @@ namespace dlib
<< "\n\tm.nc(): " << m.nc() << "\n\tm.nc(): " << m.nc()
<< "\n\tC: " << C << "\n\tC: " << C
); );
typedef matrix_scalar_binary_exp<EXP,long,op_remove_col2> exp; typedef op_remove_col2<EXP> op;
return exp(m.ref(),C); return matrix_op<op>(op(m.ref(),C));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <long R> template <typename M, long R>
struct op_remove_row struct op_remove_row
{ {
template <typename EXP> op_remove_row( const M& m_) : m(m_){}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost+1; const static long cost = M::cost+1;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1); const static long NR = (M::NR==0) ? 0 : (M::NR - 1);
const static long NC = EXP::NC; const static long NC = M::NC;
typedef typename EXP::type type; typedef typename M::type type;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long r, long c) const_ret_type apply ( long r, long c) const
{ {
if (r < R) if (r < R)
{ {
...@@ -794,26 +889,28 @@ namespace dlib ...@@ -794,26 +889,28 @@ namespace dlib
} }
} }
template <typename M> long nr () const { return m.nr() - 1; }
static long nr (const M& m) { return m.nr() - 1; } long nc () const { return m.nc(); }
template <typename M>
static long nc (const M& m) { return m.nc(); } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template <typename M>
struct op_remove_row2 struct op_remove_row2
{ {
template <typename EXP> op_remove_row2( const M& m_, const long R_) : m(m_), R(R_){}
struct op : has_destructive_aliasing const M& m;
{ const long R;
const static long cost = EXP::cost+1;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1); const static long cost = M::cost+1;
const static long NC = EXP::NC; const static long NR = (M::NR==0) ? 0 : (M::NR - 1);
typedef typename EXP::type type; const static long NC = M::NC;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::type type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::const_ret_type const_ret_type;
template <typename M> typedef typename M::mem_manager_type mem_manager_type;
static const_ret_type apply ( const M& m, long R, long r, long c) typedef typename M::layout_type layout_type;
const_ret_type apply ( long r, long c) const
{ {
if (r < R) if (r < R)
{ {
...@@ -825,18 +922,18 @@ namespace dlib ...@@ -825,18 +922,18 @@ namespace dlib
} }
} }
template <typename M> long nr () const { return m.nr() - 1; }
static long nr (const M& m) { return m.nr() - 1; } long nc () const { return m.nc(); }
template <typename M>
static long nc (const M& m) { return m.nc(); } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
long R, long R,
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_remove_row<R> > remove_row ( const matrix_op<op_remove_row<EXP,R> > remove_row (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
...@@ -850,14 +947,14 @@ namespace dlib ...@@ -850,14 +947,14 @@ namespace dlib
<< "\n\tm.nc(): " << m.nc() << "\n\tm.nc(): " << m.nc()
<< "\n\tR: " << R << "\n\tR: " << R
); );
typedef matrix_unary_exp<EXP,op_remove_row<R> > exp; typedef op_remove_row<EXP,R> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
template < template <
typename EXP typename EXP
> >
const matrix_scalar_binary_exp<EXP,long,op_remove_row2> remove_row ( const matrix_op<op_remove_row2<EXP> > remove_row (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
long R long R
) )
...@@ -869,26 +966,27 @@ namespace dlib ...@@ -869,26 +966,27 @@ namespace dlib
<< "\n\tm.nc(): " << m.nc() << "\n\tm.nc(): " << m.nc()
<< "\n\tR: " << R << "\n\tR: " << R
); );
typedef matrix_scalar_binary_exp<EXP,long,op_remove_row2 > exp; typedef op_remove_row2<EXP> op;
return exp(m.ref(),R); return matrix_op<op>(op(m.ref(),R));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_diagm struct op_diagm
{ {
template <typename EXP> op_diagm( const M& m_) : m(m_){}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost+1; const static long cost = M::cost+1;
const static long N = EXP::NC*EXP::NR; const static long N = M::NC*M::NR;
const static long NR = N; const static long NR = N;
const static long NC = N; const static long NC = N;
typedef typename EXP::type type; typedef typename M::type type;
typedef const typename EXP::type const_ret_type; typedef const typename M::type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long r, long c) const_ret_type apply ( long r, long c) const
{ {
if (r==c) if (r==c)
return m(r); return m(r);
...@@ -896,17 +994,17 @@ namespace dlib ...@@ -896,17 +994,17 @@ namespace dlib
return 0; return 0;
} }
template <typename M> long nr () const { return (m.nr()>m.nc())? m.nr():m.nc(); }
static long nr (const M& m) { return (m.nr()>m.nc())? m.nr():m.nc(); } long nc () const { return (m.nr()>m.nc())? m.nr():m.nc(); }
template <typename M>
static long nc (const M& m) { return (m.nr()>m.nc())? m.nr():m.nc(); } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_diagm> diagm ( const matrix_op<op_diagm<EXP> > diagm (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
...@@ -918,102 +1016,104 @@ namespace dlib ...@@ -918,102 +1016,104 @@ namespace dlib
<< "\n\tm.nr(): " << m.nr() << "\n\tm.nr(): " << m.nr()
<< "\n\tm.nc(): " << m.nc() << "\n\tm.nc(): " << m.nc()
); );
typedef matrix_unary_exp<EXP,op_diagm> exp; typedef op_diagm<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_diag struct op_diag
{ {
template <typename EXP> op_diag( const M& m_) : m(m_){}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost; const static long cost = M::cost;
const static long NR = (EXP::NC&&EXP::NR)? (tmin<EXP::NR,EXP::NC>::value) : (0); const static long NR = (M::NC&&M::NR)? (tmin<M::NR,M::NC>::value) : (0);
const static long NC = 1; const static long NC = 1;
typedef typename EXP::type type; typedef typename M::type type;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long r, long ) const_ret_type apply ( long r, long ) const { return m(r,r); }
{ return m(r,r); }
template <typename M> long nr () const { return std::min(m.nc(),m.nr()); }
static long nr (const M& m) { return std::min(m.nc(),m.nr()); } long nc () const { return 1; }
template <typename M>
static long nc (const M& ) { return 1; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_diag> diag ( const matrix_op<op_diag<EXP> > diag (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_diag> exp; typedef op_diag<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename target_type> template <typename M, typename target_type>
struct op_cast struct op_cast
{ {
template <typename EXP> op_cast( const M& m_) : m(m_){}
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP> const M& m;
{
const static long cost = EXP::cost; const static long cost = M::cost;
const static long NR = M::NR;
const static long NC = M::NC;
typedef target_type type; typedef target_type type;
typedef const target_type const_ret_type; typedef const target_type const_ret_type;
template <typename M> typedef typename M::mem_manager_type mem_manager_type;
static const_ret_type apply ( const M& m, long r, long c) typedef typename M::layout_type layout_type;
{ return static_cast<target_type>(m(r,c)); } const_ret_type apply ( long r, long c) const { return static_cast<target_type>(m(r,c)); }
};
long nr () const { return m.nr(); }
long nc () const { return m.nc(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.destructively_aliases(item); }
}; };
template < template <
typename target_type, typename target_type,
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_cast<target_type> > matrix_cast ( const matrix_op<op_cast<EXP, target_type> > matrix_cast (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_cast<target_type> > exp; typedef op_cast<EXP, target_type> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_lessthan namespace impl
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{ {
const static long cost = EXP::cost+1; template <typename type, typename S>
typedef typename EXP::type type; inline type lessthan(const type& val, const S& s)
typedef const typename EXP::type const_ret_type;
template <typename M, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
{ {
if (m(r,c) < s) if (val < s)
return 1; return 1;
else else
return 0; return 0;
} }
};
}; }
DLIB_DEFINE_OP_MS(op_lessthan, impl::lessthan, 1);
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_lessthan> >::type operator< ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_lessthan<EXP,S> > >::type operator< (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const S& s const S& s
) )
...@@ -1022,14 +1122,15 @@ namespace dlib ...@@ -1022,14 +1122,15 @@ namespace dlib
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_lessthan>(m.ref(),s); typedef op_lessthan<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_lessthan> >::type operator> ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_lessthan<EXP,S> > >::type operator> (
const S& s, const S& s,
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
...@@ -1038,88 +1139,81 @@ namespace dlib ...@@ -1038,88 +1139,81 @@ namespace dlib
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_lessthan>(m.ref(),s); typedef op_lessthan<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_lessthan_eq namespace impl
{ {
template <typename EXP> template <typename type, typename S>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP> inline type lessthan_eq(const type& val, const S& s)
{
const static long cost = EXP::cost+1;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
{ {
if (m(r,c) <= s) if (val <= s)
return 1; return 1;
else else
return 0; return 0;
} }
};
}; }
DLIB_DEFINE_OP_MS(op_lessthan_eq, impl::lessthan_eq, 1);
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_lessthan_eq> >::type operator<= ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_lessthan_eq<EXP,S> > >::type operator<= (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const S& s const S& s
) )
{ {
// you can only use this relational operator with the built in scalar types like // you can only use this relational operator with the built in scalar types like
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_lessthan_eq>(m.ref(),s); typedef op_lessthan_eq<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_lessthan_eq> >::type operator>= ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_lessthan_eq<EXP,S> > >::type operator>= (
const S& s, const S& s,
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
// you can only use this relational operator with the built in scalar types like // you can only use this relational operator with the built in scalar types like
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_lessthan_eq>(m.ref(),s); typedef op_lessthan_eq<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_greaterthan namespace impl
{ {
template <typename EXP> template <typename type, typename S>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP> inline type greaterthan(const type& val, const S& s)
{
const static long cost = EXP::cost+1;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
{ {
if (m(r,c) > s) if (val > s)
return 1; return 1;
else else
return 0; return 0;
} }
};
}; }
DLIB_DEFINE_OP_MS(op_greaterthan, impl::greaterthan, 1);
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_greaterthan> >::type operator> ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_greaterthan<EXP,S> > >::type operator> (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const S& s const S& s
) )
...@@ -1128,14 +1222,15 @@ namespace dlib ...@@ -1128,14 +1222,15 @@ namespace dlib
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_greaterthan>(m.ref(),s); typedef op_greaterthan<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_greaterthan> >::type operator< ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_greaterthan<EXP,S> > >::type operator< (
const S& s, const S& s,
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
...@@ -1144,88 +1239,81 @@ namespace dlib ...@@ -1144,88 +1239,81 @@ namespace dlib
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_greaterthan>(m.ref(),s); typedef op_greaterthan<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_greaterthan_eq namespace impl
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{ {
const static long cost = EXP::cost+1; template <typename type, typename S>
typedef typename EXP::type type; inline type greaterthan_eq(const type& val, const S& s)
typedef const typename EXP::type const_ret_type;
template <typename M, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
{ {
if (m(r,c) >= s) if (val >= s)
return 1; return 1;
else else
return 0; return 0;
} }
};
}; }
DLIB_DEFINE_OP_MS(op_greaterthan_eq, impl::greaterthan_eq, 1);
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_greaterthan_eq> >::type operator>= ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_greaterthan_eq<EXP,S> > >::type operator>= (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const S& s const S& s
) )
{ {
// you can only use this relational operator with the built in scalar types like // you can only use this relational operator with the built in scalar types like
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_greaterthan_eq>(m.ref(),s); typedef op_greaterthan_eq<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_greaterthan_eq> >::type operator<= ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_greaterthan_eq<EXP,S> > >::type operator<= (
const S& s, const S& s,
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
// you can only use this relational operator with the built in scalar types like // you can only use this relational operator with the built in scalar types like
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_greaterthan_eq>(m.ref(),s); typedef op_greaterthan_eq<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_equal_to namespace impl
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{ {
const static long cost = EXP::cost+1; template <typename type, typename S>
typedef typename EXP::type type; inline type equal_to(const type& val, const S& s)
typedef const typename EXP::type const_ret_type;
template <typename M, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
{ {
if (m(r,c) == s) if (val == s)
return 1; return 1;
else else
return 0; return 0;
} }
};
}; }
DLIB_DEFINE_OP_MS(op_equal_to, impl::equal_to, 1);
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_equal_to> >::type operator== ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_equal_to<EXP,S> > >::type operator== (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const S& s const S& s
) )
...@@ -1234,14 +1322,15 @@ namespace dlib ...@@ -1234,14 +1322,15 @@ namespace dlib
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_equal_to>(m.ref(),s); typedef op_equal_to<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_equal_to> >::type operator== ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_equal_to<EXP,S> > >::type operator== (
const S& s, const S& s,
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
...@@ -1250,35 +1339,32 @@ namespace dlib ...@@ -1250,35 +1339,32 @@ namespace dlib
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT( is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_equal_to>(m.ref(),s); typedef op_equal_to<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_not_equal_to namespace impl
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{ {
const static long cost = EXP::cost+1; template <typename type, typename S>
typedef typename EXP::type type; inline type not_equal_to(const type& val, const S& s)
typedef const typename EXP::type const_ret_type;
template <typename M, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
{ {
if (m(r,c) != s) if (val != s)
return 1; return 1;
else else
return 0; return 0;
} }
};
}; }
DLIB_DEFINE_OP_MS(op_not_equal_to, impl::not_equal_to, 1);
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_not_equal_to> >::type operator!= ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_not_equal_to<EXP,S> > >::type operator!= (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const S& s const S& s
) )
...@@ -1287,14 +1373,15 @@ namespace dlib ...@@ -1287,14 +1373,15 @@ namespace dlib
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_not_equal_to>(m.ref(),s); typedef op_not_equal_to<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
template < template <
typename EXP, typename EXP,
typename S typename S
> >
const typename enable_if<is_built_in_scalar_type<S>,matrix_scalar_binary_exp<EXP,S,op_not_equal_to> >::type operator!= ( const typename enable_if<is_built_in_scalar_type<S>, matrix_op<op_not_equal_to<EXP,S> > >::type operator!= (
const S& s, const S& s,
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
...@@ -1303,7 +1390,8 @@ namespace dlib ...@@ -1303,7 +1390,8 @@ namespace dlib
// long, float, etc. // long, float, etc.
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value); COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
return matrix_scalar_binary_exp<EXP,S, op_not_equal_to>(m.ref(),s); typedef op_not_equal_to<EXP,S> op;
return matrix_op<op>(op(m.ref(),s));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1420,19 +1508,20 @@ namespace dlib ...@@ -1420,19 +1508,20 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_sumr struct op_sumr
{ {
template <typename EXP> op_sumr(const M& m_) : m(m_) {}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost; const static long cost = M::cost;
const static long NR = 1; const static long NR = 1;
const static long NC = EXP::NC; const static long NC = M::NC;
typedef typename EXP::type type; typedef typename M::type type;
typedef const typename EXP::type const_ret_type; typedef const typename M::type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long , long c) const_ret_type apply ( long , long c) const
{ {
type temp = m(0,c); type temp = m(0,c);
for (long r = 1; r < m.nr(); ++r) for (long r = 1; r < m.nr(); ++r)
...@@ -1440,17 +1529,17 @@ namespace dlib ...@@ -1440,17 +1529,17 @@ namespace dlib
return temp; return temp;
} }
template <typename M> long nr () const { return 1; }
static long nr (const M& ) { return 1; } long nc () const { return m.nc(); }
template <typename M>
static long nc (const M& m) { return m.nc(); } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_sumr> sum_rows ( const matrix_op<op_sumr<EXP> > sum_rows (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
...@@ -1459,25 +1548,26 @@ namespace dlib ...@@ -1459,25 +1548,26 @@ namespace dlib
<< "\n\t The matrix can't be empty" << "\n\t The matrix can't be empty"
<< "\n\t m.size(): " << m.size() << "\n\t m.size(): " << m.size()
); );
typedef matrix_unary_exp<EXP,op_sumr> exp; typedef op_sumr<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_sumc struct op_sumc
{ {
template <typename EXP> op_sumc(const M& m_) : m(m_) {}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost; const static long cost = M::cost;
const static long NR = EXP::NR; const static long NR = M::NR;
const static long NC = 1; const static long NC = 1;
typedef typename EXP::type type; typedef typename M::type type;
typedef const typename EXP::type const_ret_type; typedef const typename M::type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long r, long ) const_ret_type apply ( long r, long ) const
{ {
type temp = m(r,0); type temp = m(r,0);
for (long c = 1; c < m.nc(); ++c) for (long c = 1; c < m.nc(); ++c)
...@@ -1485,17 +1575,17 @@ namespace dlib ...@@ -1485,17 +1575,17 @@ namespace dlib
return temp; return temp;
} }
template <typename M> long nr () const { return m.nr(); }
static long nr (const M& m) { return m.nr(); } long nc () const { return 1; }
template <typename M>
static long nc (const M& ) { return 1; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_sumc> sum_cols ( const matrix_op<op_sumc<EXP> > sum_cols (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
...@@ -1504,8 +1594,8 @@ namespace dlib ...@@ -1504,8 +1594,8 @@ namespace dlib
<< "\n\t The matrix can't be empty" << "\n\t The matrix can't be empty"
<< "\n\t m.size(): " << m.size() << "\n\t m.size(): " << m.size()
); );
typedef matrix_unary_exp<EXP,op_sumc> exp; typedef op_sumc<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1644,22 +1734,32 @@ namespace dlib ...@@ -1644,22 +1734,32 @@ namespace dlib
template < template <
typename T typename T
> >
struct op_uniform_matrix_3 : has_nondestructive_aliasing struct op_uniform_matrix_3 : does_not_alias
{ {
op_uniform_matrix_3(const long& rows_, const long& cols_, const T& val_ ) :
rows(rows_), cols(cols_), val(val_) {}
const long rows;
const long cols;
const T val;
const static long cost = 1; const static long cost = 1;
const static long NR = 0; const static long NR = 0;
const static long NC = 0; const static long NC = 0;
typedef typename memory_manager<char>::kernel_1a mem_manager_type; typedef memory_manager<char>::kernel_1a mem_manager_type;
typedef row_major_layout layout_type;
typedef T type; typedef T type;
typedef const T& const_ret_type; typedef const T& const_ret_type;
static const_ret_type apply (const T& val, long , long, long, long ) const_ret_type apply (long, long ) const { return val; }
{ return val; }
long nr() const { return rows; }
long nc() const { return cols; }
}; };
template < template <
typename T typename T
> >
const dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > uniform_matrix ( const matrix_op<op_uniform_matrix_3<T> > uniform_matrix (
long nr, long nr,
long nc, long nc,
const T& val const T& val
...@@ -1671,8 +1771,8 @@ namespace dlib ...@@ -1671,8 +1771,8 @@ namespace dlib
<< "\n\tnr: " << nr << "\n\tnr: " << nr
<< "\n\tnc: " << nc << "\n\tnc: " << nc
); );
typedef dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > exp; typedef op_uniform_matrix_3<T> op;
return exp(nr,nc,val); return matrix_op<op>(op(nr, nc, val));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1680,7 +1780,7 @@ namespace dlib ...@@ -1680,7 +1780,7 @@ namespace dlib
template < template <
typename T typename T
> >
const dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > zeros_matrix ( const matrix_op<op_uniform_matrix_3<T> > zeros_matrix (
long nr, long nr,
long nc long nc
) )
...@@ -1691,8 +1791,8 @@ namespace dlib ...@@ -1691,8 +1791,8 @@ namespace dlib
<< "\n\tnr: " << nr << "\n\tnr: " << nr
<< "\n\tnc: " << nc << "\n\tnc: " << nc
); );
typedef dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > exp; typedef op_uniform_matrix_3<T> op;
return exp(nr,nc,0); return matrix_op<op>(op(nr, nc, 0));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1700,7 +1800,7 @@ namespace dlib ...@@ -1700,7 +1800,7 @@ namespace dlib
template < template <
typename T typename T
> >
const dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > ones_matrix ( const matrix_op<op_uniform_matrix_3<T> > ones_matrix (
long nr, long nr,
long nc long nc
) )
...@@ -1711,8 +1811,8 @@ namespace dlib ...@@ -1711,8 +1811,8 @@ namespace dlib
<< "\n\tnr: " << nr << "\n\tnr: " << nr
<< "\n\tnc: " << nc << "\n\tnc: " << nc
); );
typedef dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > exp; typedef op_uniform_matrix_3<T> op;
return exp(nr,nc,1); return matrix_op<op>(op(nr, nc, 1));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1722,16 +1822,23 @@ namespace dlib ...@@ -1722,16 +1822,23 @@ namespace dlib
long NR_, long NR_,
long NC_ long NC_
> >
struct op_uniform_matrix_2 : has_nondestructive_aliasing struct op_uniform_matrix_2 : does_not_alias
{ {
op_uniform_matrix_2( const T& val_ ) : val(val_) {}
const T val;
const static long cost = 1; const static long cost = 1;
const static long NR = NR_; const static long NR = NR_;
const static long NC = NC_; const static long NC = NC_;
typedef typename memory_manager<char>::kernel_1a mem_manager_type; typedef memory_manager<char>::kernel_1a mem_manager_type;
typedef row_major_layout layout_type;
typedef T type; typedef T type;
typedef const T& const_ret_type; typedef const T& const_ret_type;
static const_ret_type apply (const T& val, long , long )
{ return val; } const_ret_type apply (long , long ) const { return val; }
long nr() const { return NR; }
long nc() const { return NC; }
}; };
template < template <
...@@ -1739,14 +1846,14 @@ namespace dlib ...@@ -1739,14 +1846,14 @@ namespace dlib
long NR, long NR,
long NC long NC
> >
const matrix_scalar_unary_exp<T,op_uniform_matrix_2<T,NR,NC> > uniform_matrix ( const matrix_op<op_uniform_matrix_2<T,NR,NC> > uniform_matrix (
const T& val const T& val
) )
{ {
COMPILE_TIME_ASSERT(NR > 0 && NC > 0); COMPILE_TIME_ASSERT(NR > 0 && NC > 0);
typedef matrix_scalar_unary_exp<T,op_uniform_matrix_2<T,NR,NC> > exp; typedef op_uniform_matrix_2<T,NR,NC> op;
return exp(val); return matrix_op<op>(op(val));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1757,16 +1864,19 @@ namespace dlib ...@@ -1757,16 +1864,19 @@ namespace dlib
long NC_, long NC_,
T val T val
> >
struct op_uniform_matrix : has_nondestructive_aliasing struct op_uniform_matrix : does_not_alias
{ {
const static long cost = 1; const static long cost = 1;
const static long NR = NR_; const static long NR = NR_;
const static long NC = NC_; const static long NC = NC_;
typedef typename memory_manager<char>::kernel_1a mem_manager_type; typedef memory_manager<char>::kernel_1a mem_manager_type;
typedef row_major_layout layout_type;
typedef T type; typedef T type;
typedef const T const_ret_type; typedef const T const_ret_type;
static const_ret_type apply ( long , long ) const_ret_type apply ( long , long ) const { return val; }
{ return val; }
long nr() const { return NR; }
long nc() const { return NC; }
}; };
template < template <
...@@ -1775,12 +1885,12 @@ namespace dlib ...@@ -1775,12 +1885,12 @@ namespace dlib
long NC, long NC,
T val T val
> >
const matrix_zeroary_exp<op_uniform_matrix<T,NR,NC,val> > uniform_matrix ( const matrix_op<op_uniform_matrix<T,NR,NC,val> > uniform_matrix (
) )
{ {
COMPILE_TIME_ASSERT(NR > 0 && NC > 0); COMPILE_TIME_ASSERT(NR > 0 && NC > 0);
typedef matrix_zeroary_exp<op_uniform_matrix<T,NR,NC,val> > exp; typedef op_uniform_matrix<T,NR,NC,val> op;
return exp(); return matrix_op<op>(op());
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1788,22 +1898,29 @@ namespace dlib ...@@ -1788,22 +1898,29 @@ namespace dlib
template < template <
typename T typename T
> >
struct op_identity_matrix_2 : has_nondestructive_aliasing struct op_identity_matrix_2 : does_not_alias
{ {
op_identity_matrix_2(const long& size_) : size(size_) {}
const long size;
const static long cost = 1; const static long cost = 1;
const static long NR = 0; const static long NR = 0;
const static long NC = 0; const static long NC = 0;
typedef typename memory_manager<char>::kernel_1a mem_manager_type; typedef memory_manager<char>::kernel_1a mem_manager_type;
typedef row_major_layout layout_type;
typedef T type; typedef T type;
typedef const T const_ret_type; typedef const T const_ret_type;
static const_ret_type apply (const T&, long r, long c, long, long) const_ret_type apply (long r, long c) const { return static_cast<type>(r == c); }
{ return static_cast<type>(r == c); }
long nr() const { return size; }
long nc() const { return size; }
}; };
template < template <
typename T typename T
> >
const dynamic_matrix_scalar_unary_exp<T,op_identity_matrix_2<T> > identity_matrix ( const matrix_op<op_identity_matrix_2<T> > identity_matrix (
const long& size const long& size
) )
{ {
...@@ -1812,10 +1929,8 @@ namespace dlib ...@@ -1812,10 +1929,8 @@ namespace dlib
<< "\n\tsize must be bigger than 0" << "\n\tsize must be bigger than 0"
<< "\n\tsize: " << size << "\n\tsize: " << size
); );
typedef dynamic_matrix_scalar_unary_exp<T,op_identity_matrix_2<T> > exp; typedef op_identity_matrix_2<T> op;
// the scalar value of the dynamic_matrix_scalar_unary_exp just isn't return matrix_op<op>(op(size));
// used by this operator
return exp(size,size,0);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1824,51 +1939,56 @@ namespace dlib ...@@ -1824,51 +1939,56 @@ namespace dlib
typename T, typename T,
long N long N
> >
struct op_identity_matrix : has_nondestructive_aliasing struct op_identity_matrix : does_not_alias
{ {
const static long cost = 1; const static long cost = 1;
const static long NR = N; const static long NR = N;
const static long NC = N; const static long NC = N;
typedef typename memory_manager<char>::kernel_1a mem_manager_type; typedef memory_manager<char>::kernel_1a mem_manager_type;
typedef row_major_layout layout_type;
typedef T type; typedef T type;
typedef const T const_ret_type; typedef const T const_ret_type;
static const_ret_type apply ( long r, long c) const_ret_type apply ( long r, long c) const { return static_cast<type>(r == c); }
{ return static_cast<type>(r == c); }
template <typename M> long nr () const { return NR; }
static long nr (const M&) { return NR; } long nc () const { return NC; }
template <typename M>
static long nc (const M&) { return NC; }
}; };
template < template <
typename T, typename T,
long N long N
> >
const matrix_zeroary_exp<op_identity_matrix<T,N> > identity_matrix ( const matrix_op<op_identity_matrix<T,N> > identity_matrix (
) )
{ {
COMPILE_TIME_ASSERT(N > 0); COMPILE_TIME_ASSERT(N > 0);
typedef matrix_zeroary_exp<op_identity_matrix<T,N> > exp; typedef op_identity_matrix<T,N> op;
return exp(); return matrix_op<op>(op());
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <long R, long C> template <typename M, long R, long C>
struct op_rotate struct op_rotate
{ {
template <typename EXP> op_rotate(const M& m_) : m(m_) {}
struct op : has_destructive_aliasing, preserves_dimensions<EXP> const M& m;
{
const static long cost = EXP::cost + 1; const static long cost = M::cost + 1;
typedef typename EXP::type type; const static long NR = M::NR;
typedef typename EXP::const_ret_type const_ret_type; const static long NC = M::NC;
template <typename M> typedef typename M::type type;
static const_ret_type apply ( const M& m, long r, long c) typedef typename M::const_ret_type const_ret_type;
{ return m((r+R)%m.nr(),(c+C)%m.nc()); } typedef typename M::mem_manager_type mem_manager_type;
}; typedef typename M::layout_type layout_type;
const_ret_type apply ( long r, long c) const { return m((r+R)%m.nr(),(c+C)%m.nc()); }
long nr () const { return m.nr(); }
long nc () const { return m.nc(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
...@@ -1876,18 +1996,17 @@ namespace dlib ...@@ -1876,18 +1996,17 @@ namespace dlib
long C, long C,
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_rotate<R,C> > rotate ( const matrix_op<op_rotate<EXP,R,C> > rotate (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_rotate<R,C> > exp; typedef op_rotate<EXP,R,C> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
namespace impl
struct op_pointwise_multiply
{ {
// A template to tell me if two types can be multiplied together in a sensible way. Here // A template to tell me if two types can be multiplied together in a sensible way. Here
// I'm saying it is ok if they are both the same type or one is the complex version of the other. // I'm saying it is ok if they are both the same type or one is the complex version of the other.
...@@ -1895,30 +2014,32 @@ namespace dlib ...@@ -1895,30 +2014,32 @@ namespace dlib
template <typename T> struct compatible<T,T> { static const bool value = true; typedef T type; }; template <typename T> struct compatible<T,T> { static const bool value = true; typedef T type; };
template <typename T> struct compatible<std::complex<T>,T> { static const bool value = true; typedef std::complex<T> type; }; template <typename T> struct compatible<std::complex<T>,T> { static const bool value = true; typedef std::complex<T> type; };
template <typename T> struct compatible<T,std::complex<T> > { static const bool value = true; typedef std::complex<T> type; }; template <typename T> struct compatible<T,std::complex<T> > { static const bool value = true; typedef std::complex<T> type; };
}
template <typename EXP1, typename EXP2> template <typename M1, typename M2>
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2> struct op_pointwise_multiply : basic_op_mm<M1,M2>
{ {
typedef typename compatible<typename EXP1::type, typename EXP2::type>::type type; op_pointwise_multiply( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){}
typedef typename impl::compatible<typename M1::type, typename M2::type>::type type;
typedef const type const_ret_type; typedef const type const_ret_type;
const static long cost = EXP1::cost + EXP2::cost + 1; const static long cost = M1::cost + M2::cost + 1;
template <typename M1, typename M2> const_ret_type apply ( long r, long c) const
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c) { return this->m1(r,c)*this->m2(r,c); }
{ return m1(r,c)*m2(r,c); }
};
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
inline const matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> pointwise_multiply ( inline const matrix_op<op_pointwise_multiply<EXP1,EXP2> > pointwise_multiply (
const matrix_exp<EXP1>& a, const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b const matrix_exp<EXP2>& b
) )
{ {
COMPILE_TIME_ASSERT((op_pointwise_multiply::compatible<typename EXP1::type,typename EXP2::type>::value == true)); COMPILE_TIME_ASSERT((impl::compatible<typename EXP1::type,typename EXP2::type>::value == true));
COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0);
COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0);
DLIB_ASSERT(a.nr() == b.nr() && DLIB_ASSERT(a.nr() == b.nr() &&
...@@ -1930,25 +2051,24 @@ namespace dlib ...@@ -1930,25 +2051,24 @@ namespace dlib
<< "\n\tb.nr(): " << b.nr() << "\n\tb.nr(): " << b.nr()
<< "\n\tb.nc(): " << b.nc() << "\n\tb.nc(): " << b.nc()
); );
typedef matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> exp; typedef op_pointwise_multiply<EXP1,EXP2> op;
return exp(a.ref(),b.ref()); return matrix_op<op>(op(a.ref(),b.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_pointwise_multiply3 template <typename M1, typename M2, typename M3>
{ struct op_pointwise_multiply3 : basic_op_mmm<M1,M2,M3>
template <typename EXP1, typename EXP2, typename EXP3>
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2,EXP3>
{ {
typedef typename EXP1::type type; op_pointwise_multiply3( const M1& m1_, const M2& m2_, const M3& m3_) :
typedef const typename EXP1::type const_ret_type; basic_op_mmm<M1,M2,M3>(m1_,m2_,m3_){}
const static long cost = EXP1::cost + EXP2::cost + EXP3::cost + 2;
template <typename M1, typename M2, typename M3> typedef typename M1::type type;
static const_ret_type apply ( const M1& m1, const M2& m2, const M3& m3 , long r, long c) typedef const typename M1::type const_ret_type;
{ return m1(r,c)*m2(r,c)*m3(r,c); } const static long cost = M1::cost + M2::cost + M3::cost + 2;
};
const_ret_type apply (long r, long c) const
{ return this->m1(r,c)*this->m2(r,c)*this->m3(r,c); }
}; };
template < template <
...@@ -1956,7 +2076,7 @@ namespace dlib ...@@ -1956,7 +2076,7 @@ namespace dlib
typename EXP2, typename EXP2,
typename EXP3 typename EXP3
> >
inline const matrix_ternary_exp<EXP1,EXP2,EXP3,op_pointwise_multiply3> inline const matrix_op<op_pointwise_multiply3<EXP1,EXP2,EXP3> >
pointwise_multiply ( pointwise_multiply (
const matrix_exp<EXP1>& a, const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b, const matrix_exp<EXP2>& b,
...@@ -1982,35 +2102,35 @@ namespace dlib ...@@ -1982,35 +2102,35 @@ namespace dlib
<< "\n\tc.nr(): " << c.nr() << "\n\tc.nr(): " << c.nr()
<< "\n\tc.nc(): " << c.nc() << "\n\tc.nc(): " << c.nc()
); );
typedef matrix_ternary_exp<EXP1,EXP2,EXP3,op_pointwise_multiply3> exp;
return exp(a.ref(),b.ref(),c.ref()); typedef op_pointwise_multiply3<EXP1,EXP2,EXP3> op;
return matrix_op<op>(op(a.ref(),b.ref(),c.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_pointwise_multiply4 template <typename M1, typename M2, typename M3, typename M4>
{ struct op_pointwise_multiply4 : basic_op_mmmm<M1,M2,M3,M4>
template <typename EXP1, typename EXP2, typename EXP3, typename EXP4>
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2,EXP3,EXP4>
{ {
typedef typename EXP1::type type; op_pointwise_multiply4( const M1& m1_, const M2& m2_, const M3& m3_, const M4& m4_) :
typedef const typename EXP1::type const_ret_type; basic_op_mmmm<M1,M2,M3,M4>(m1_,m2_,m3_,m4_){}
const static long cost = EXP1::cost + EXP2::cost + EXP3::cost + EXP4::cost + 3;
template <typename M1, typename M2, typename M3, typename M4> typedef typename M1::type type;
static const_ret_type apply ( const M1& m1, const M2& m2, const M3& m3, const M4& m4 , long r, long c) typedef const typename M1::type const_ret_type;
{ return m1(r,c)*m2(r,c)*m3(r,c)*m4(r,c); } const static long cost = M1::cost + M2::cost + M3::cost + M4::cost + 3;
};
const_ret_type apply (long r, long c) const
{ return this->m1(r,c)*this->m2(r,c)*this->m3(r,c)*this->m4(r,c); }
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2, typename EXP2,
typename EXP3, typename EXP3,
typename EXP4 typename EXP4
> >
inline const matrix_fourary_exp<EXP1,EXP2,EXP3,EXP4,op_pointwise_multiply4> pointwise_multiply ( inline const matrix_op<op_pointwise_multiply4<EXP1,EXP2,EXP3,EXP4> > pointwise_multiply (
const matrix_exp<EXP1>& a, const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b, const matrix_exp<EXP2>& b,
const matrix_exp<EXP3>& c, const matrix_exp<EXP3>& c,
...@@ -2044,8 +2164,8 @@ namespace dlib ...@@ -2044,8 +2164,8 @@ namespace dlib
<< "\n\td.nc(): " << d.nc() << "\n\td.nc(): " << d.nc()
); );
typedef matrix_fourary_exp<EXP1,EXP2,EXP3,EXP4,op_pointwise_multiply4> exp; typedef op_pointwise_multiply4<EXP1,EXP2,EXP3,EXP4> op;
return exp(a.ref(),b.ref(),c.ref(),d.ref()); return matrix_op<op>(op(a.ref(),b.ref(),c.ref(),d.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -2223,20 +2343,18 @@ namespace dlib ...@@ -2223,20 +2343,18 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <long lower, long upper> template <typename M, long lower, long upper>
struct op_clamp struct op_clamp : basic_op_m<M>
{ {
template <typename EXP> op_clamp( const M& m_) : basic_op_m<M>(m_){}
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
const static long cost = EXP::cost + 1;
template <typename M> typedef typename M::type type;
static const_ret_type apply ( const M& m, long r, long c) typedef const typename M::type const_ret_type;
const static long cost = M::cost + 1;
const_ret_type apply ( long r, long c) const
{ {
const type temp = m(r,c); const type temp = this->m(r,c);
if (temp > static_cast<type>(upper)) if (temp > static_cast<type>(upper))
return static_cast<type>(upper); return static_cast<type>(upper);
else if (temp < static_cast<type>(lower)) else if (temp < static_cast<type>(lower))
...@@ -2245,36 +2363,39 @@ namespace dlib ...@@ -2245,36 +2363,39 @@ namespace dlib
return temp; return temp;
} }
}; };
};
template < template <
long l, long l,
long u, long u,
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_clamp<l,u> > clamp ( const matrix_op<op_clamp<EXP,l,u> > clamp (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_clamp<l,u> > exp; typedef op_clamp<EXP,l,u> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_clamp2 template <typename M>
{ struct op_clamp2 : basic_op_m<M>
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{ {
typedef typename EXP::type type; typedef typename M::type type;
typedef const typename EXP::type const_ret_type;
const static long cost = EXP::cost + 2;
template <typename M> op_clamp2( const M& m_, const type& l, const type& u) :
static const_ret_type apply ( const M& m, const type& lower, const type& upper, long r, long c) basic_op_m<M>(m_), lower(l), upper(u){}
const type& lower;
const type& upper;
typedef const typename M::type const_ret_type;
const static long cost = M::cost + 2;
const_ret_type apply ( long r, long c) const
{ {
const type temp = m(r,c); const type temp = this->m(r,c);
if (temp > upper) if (temp > upper)
return upper; return upper;
else if (temp < lower) else if (temp < lower)
...@@ -2283,53 +2404,55 @@ namespace dlib ...@@ -2283,53 +2404,55 @@ namespace dlib
return temp; return temp;
} }
}; };
};
template < template <
typename EXP typename EXP
> >
const matrix_scalar_ternary_exp<EXP,typename EXP::type, op_clamp2> clamp ( const matrix_op<op_clamp2<EXP> > clamp (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const typename EXP::type& lower, const typename EXP::type& lower,
const typename EXP::type& upper const typename EXP::type& upper
) )
{ {
typedef matrix_scalar_ternary_exp<EXP,typename EXP::type, op_clamp2> exp; typedef op_clamp2<EXP> op;
return exp(m.ref(),lower, upper); return matrix_op<op>(op(m.ref(),lower, upper));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_reshape struct op_reshape
{ {
template <typename EXP> op_reshape(const M& m_, const long& rows_, const long& cols_) : m(m_),rows(rows_),cols(cols_) {}
struct op : public has_destructive_aliasing const M& m;
{ const long rows;
const static long cost = EXP::cost+1; const long cols;
const static long cost = M::cost+1;
const static long NR = 0; const static long NR = 0;
const static long NC = 0; const static long NC = 0;
typedef typename EXP::type type; typedef typename M::type type;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
template <typename M> const_ret_type apply ( long r, long c) const
static const_ret_type apply ( const M& m, const long& , const long& cols, long r, long c)
{ {
const long idx = r*cols + c; const long idx = r*cols + c;
return m(idx/m.nc(), idx%m.nc()); return m(idx/m.nc(), idx%m.nc());
} }
template <typename M1 > long nr () const { return rows; }
static long nr (const M1& , const long& rows, const long& ) { return rows; } long nc () const { return cols; }
template <typename M1>
static long nc (const M1& , const long&, const long& cols ) { return cols; } template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_scalar_ternary_exp<EXP, long, op_reshape> reshape ( const matrix_op<op_reshape<EXP> > reshape (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
const long& rows, const long& rows,
const long& cols const long& cols
...@@ -2344,8 +2467,8 @@ namespace dlib ...@@ -2344,8 +2467,8 @@ namespace dlib
<< "\n\t cols: " << cols << "\n\t cols: " << cols
); );
typedef matrix_scalar_ternary_exp<EXP, long, op_reshape> exp; typedef op_reshape<EXP> op;
return exp(m.ref(), rows, cols); return matrix_op<op>(op(m.ref(), rows, cols));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -2407,34 +2530,37 @@ namespace dlib ...@@ -2407,34 +2530,37 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_scale_columns struct op_scale_columns
{ {
template <typename EXP1, typename EXP2> op_scale_columns(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {}
struct op : has_nondestructive_aliasing const M1& m1;
{ const M2& m2;
const static long cost = EXP1::cost + EXP2::cost + 1;
typedef typename EXP1::type type;
typedef const typename EXP1::type const_ret_type;
typedef typename EXP1::mem_manager_type mem_manager_type;
const static long NR = EXP1::NR;
const static long NC = EXP1::NC;
template <typename M1, typename M2> const static long cost = M1::cost + M2::cost + 1;
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c) typedef typename M1::type type;
{ return m1(r,c)*m2(c); } typedef const typename M1::type const_ret_type;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
const static long NR = M1::NR;
const static long NC = M1::NC;
template <typename M1, typename M2> const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(c); }
static long nr (const M1& m1, const M2& ) { return m1.nr(); }
template <typename M1, typename M2> long nr () const { return m1.nr(); }
static long nc (const M1& m1, const M2& ) { return m1.nc(); } long nc () const { return m1.nc(); }
};
template <typename U> bool aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || m2.aliases(item) ; }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.destructively_aliases(item) || m2.aliases(item); }
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
const matrix_binary_exp<EXP1,EXP2,op_scale_columns> scale_columns ( const matrix_op<op_scale_columns<EXP1,EXP2> > scale_columns (
const matrix_exp<EXP1>& m, const matrix_exp<EXP1>& m,
const matrix_exp<EXP2>& v const matrix_exp<EXP2>& v
) )
...@@ -2451,8 +2577,8 @@ namespace dlib ...@@ -2451,8 +2577,8 @@ namespace dlib
<< "\n\tv.nr(): " << v.nr() << "\n\tv.nr(): " << v.nr()
<< "\n\tv.nc(): " << v.nc() << "\n\tv.nc(): " << v.nc()
); );
typedef matrix_binary_exp<EXP1,EXP2,op_scale_columns> exp; typedef op_scale_columns<EXP1,EXP2> op;
return exp(m.ref(),v.ref()); return matrix_op<op>(op(m.ref(),v.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -2563,157 +2689,173 @@ namespace dlib ...@@ -2563,157 +2689,173 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_tensor_product struct op_tensor_product
{ {
template <typename EXP1, typename EXP2> op_tensor_product(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {}
struct op : public has_destructive_aliasing const M1& m1;
{ const M2& m2;
const static long cost = EXP1::cost + EXP2::cost + 1;
const static long NR = EXP1::NR*EXP2::NR;
const static long NC = EXP1::NC*EXP2::NC;
typedef typename EXP1::type type;
typedef const typename EXP1::type const_ret_type;
typedef typename EXP1::mem_manager_type mem_manager_type;
template <typename M1, typename M2> const static long cost = M1::cost + M2::cost + 1;
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c) const static long NR = M1::NR*M2::NR;
const static long NC = M1::NC*M2::NC;
typedef typename M1::type type;
typedef const typename M1::type const_ret_type;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
const_ret_type apply ( long r, long c) const
{ {
return m1(r/m2.nr(),c/m2.nc())*m2(r%m2.nr(),c%m2.nc()); return m1(r/m2.nr(),c/m2.nc())*m2(r%m2.nr(),c%m2.nc());
} }
long nr () const { return m1.nr()*m2.nr(); }
long nc () const { return m1.nc()*m2.nc(); }
template <typename M1, typename M2> template <typename U> bool aliases ( const matrix_exp<U>& item) const
static long nr (const M1& m1, const M2& m2 ) { return m1.nr()*m2.nr(); } { return m1.aliases(item) || m2.aliases(item); }
template <typename M1, typename M2> template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
static long nc (const M1& m1, const M2& m2 ) { return m1.nc()*m2.nc(); } { return m1.aliases(item) || m2.aliases(item); }
};
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
inline const matrix_binary_exp<EXP1,EXP2,op_tensor_product> tensor_product ( inline const matrix_op<op_tensor_product<EXP1,EXP2> > tensor_product (
const matrix_exp<EXP1>& a, const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b const matrix_exp<EXP2>& b
) )
{ {
COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true));
typedef matrix_binary_exp<EXP1,EXP2,op_tensor_product> exp; typedef op_tensor_product<EXP1,EXP2> op;
return exp(a.ref(),b.ref()); return matrix_op<op>(op(a.ref(),b.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_lowerm
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+1;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, long r, long c) struct op_lowerm : basic_op_m<M>
{
op_lowerm( const M& m_) : basic_op_m<M>(m_){}
const static long cost = M::cost+1;
typedef typename M::type type;
typedef const typename M::type const_ret_type;
const_ret_type apply ( long r, long c) const
{ {
if (r >= c) if (r >= c)
return m(r,c); return this->m(r,c);
else else
return 0; return 0;
} }
};
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, const type& s, long r, long c) struct op_lowerm_s : basic_op_m<M>
{
typedef typename M::type type;
op_lowerm_s( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){}
const type s;
const static long cost = M::cost+1;
typedef const typename M::type const_ret_type;
const_ret_type apply ( long r, long c) const
{ {
if (r > c) if (r > c)
return m(r,c); return this->m(r,c);
else if (r==c) else if (r==c)
return s; return s;
else else
return 0; return 0;
} }
}; };
};
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_lowerm> lowerm ( const matrix_op<op_lowerm<EXP> > lowerm (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_lowerm> exp; typedef op_lowerm<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
template < template <
typename EXP typename EXP
> >
const matrix_scalar_binary_exp<EXP, typename EXP::type,op_lowerm> lowerm ( const matrix_op<op_lowerm_s<EXP> > lowerm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
typename EXP::type s typename EXP::type s
) )
{ {
typedef matrix_scalar_binary_exp<EXP, typename EXP::type, op_lowerm> exp; typedef op_lowerm_s<EXP> op;
return exp(m.ref(),s); return matrix_op<op>(op(m.ref(),s));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct op_upperm template <typename M>
{ struct op_upperm : basic_op_m<M>
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{ {
const static long cost = EXP::cost+1; op_upperm( const M& m_) : basic_op_m<M>(m_){}
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M> const static long cost = M::cost+1;
static const_ret_type apply ( const M& m, long r, long c) typedef typename M::type type;
typedef const typename M::type const_ret_type;
const_ret_type apply ( long r, long c) const
{ {
if (r <= c) if (r <= c)
return m(r,c); return this->m(r,c);
else else
return 0; return 0;
} }
};
template <typename M> template <typename M>
static const_ret_type apply ( const M& m, const type& s, long r, long c) struct op_upperm_s : basic_op_m<M>
{
typedef typename M::type type;
op_upperm_s( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){}
const type s;
const static long cost = M::cost+1;
typedef const typename M::type const_ret_type;
const_ret_type apply ( long r, long c) const
{ {
if (r < c) if (r < c)
return m(r,c); return this->m(r,c);
else if (r==c) else if (r==c)
return s; return s;
else else
return 0; return 0;
} }
}; };
};
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_upperm> upperm ( const matrix_op<op_upperm<EXP> > upperm (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_upperm> exp; typedef op_upperm<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
template < template <
typename EXP typename EXP
> >
const matrix_scalar_binary_exp<EXP, typename EXP::type,op_upperm> upperm ( const matrix_op<op_upperm_s<EXP> > upperm (
const matrix_exp<EXP>& m, const matrix_exp<EXP>& m,
typename EXP::type s typename EXP::type s
) )
{ {
typedef matrix_scalar_binary_exp<EXP, typename EXP::type ,op_upperm> exp; typedef op_upperm_s<EXP> op;
return exp(m.ref(),s); return matrix_op<op>(op(m.ref(),s));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -2815,21 +2957,23 @@ namespace dlib ...@@ -2815,21 +2957,23 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_cart_prod struct op_cart_prod
{ {
template <typename EXP1, typename EXP2> op_cart_prod(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {}
struct op : has_destructive_aliasing const M1& m1;
{ const M2& m2;
const static long cost = EXP1::cost+EXP2::cost+1;
typedef typename EXP1::type type;
typedef const typename EXP1::const_ret_type const_ret_type;
typedef typename EXP1::mem_manager_type mem_manager_type; const static long cost = M1::cost+M2::cost+1;
const static long NR = EXP1::NR+EXP2::NR; typedef typename M1::type type;
const static long NC = EXP1::NC*EXP2::NC; typedef const typename M1::const_ret_type const_ret_type;
template <typename M1, typename M2> typedef typename M1::mem_manager_type mem_manager_type;
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c) typedef typename M1::layout_type layout_type;
const static long NR = M1::NR+M2::NR;
const static long NC = M1::NC*M2::NC;
const_ret_type apply ( long r, long c) const
{ {
if (r < m1.nr()) if (r < m1.nr())
return m1(r, c/m2.nc()); return m1(r, c/m2.nc());
...@@ -2837,70 +2981,75 @@ namespace dlib ...@@ -2837,70 +2981,75 @@ namespace dlib
return m2(r-m1.nr(), c%m2.nc()); return m2(r-m1.nr(), c%m2.nc());
} }
template <typename M1, typename M2> long nr () const { return m1.nr() + m2.nr(); }
static long nr (const M1& m1, const M2& m2) { return m1.nr() + m2.nr(); } long nc () const { return m1.nc() * m2.nc(); }
template <typename M1, typename M2>
static long nc (const M1& m1, const M2& m2) { return m1.nc() * m2.nc(); } template <typename U> bool aliases ( const matrix_exp<U>& item) const
}; { return m1.aliases(item) || m2.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || m2.aliases(item); }
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
const matrix_binary_exp<EXP1,EXP2,op_cart_prod> cartesian_product ( const matrix_op<op_cart_prod<EXP1,EXP2> > cartesian_product (
const matrix_exp<EXP1>& a, const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b const matrix_exp<EXP2>& b
) )
{ {
COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true)); COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true));
typedef matrix_binary_exp<EXP1,EXP2,op_cart_prod> exp; typedef op_cart_prod<EXP1,EXP2> op;
return exp(a.ref(),b.ref()); return matrix_op<op>(op(a.ref(),b.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_mat_to_vect struct op_mat_to_vect
{ {
template <typename EXP> op_mat_to_vect(const M& m_) : m(m_) {}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost+1; const static long cost = M::cost+1;
const static long NR = EXP::NC*EXP::NR; const static long NR = M::NC*M::NR;
const static long NC = 1; const static long NC = 1;
typedef typename EXP::type type; typedef typename M::type type;
typedef typename EXP::const_ret_type const_ret_type; typedef typename M::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type; typedef typename M::mem_manager_type mem_manager_type;
template <typename M> typedef typename M::layout_type layout_type;
static const_ret_type apply ( const M& m, long r, long )
{ return m(r/m.nc(), r%m.nc()); }
template <typename M> const_ret_type apply ( long r, long ) const { return m(r/m.nc(), r%m.nc()); }
static long nr (const M& m) { return m.size(); }
template <typename M> long nr () const { return m.size(); }
static long nc (const M& m) { return 1; } long nc () const { return 1; }
};
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template < template <
typename EXP typename EXP
> >
const matrix_unary_exp<EXP,op_mat_to_vect> reshape_to_column_vector ( const matrix_op<op_mat_to_vect<EXP> > reshape_to_column_vector (
const matrix_exp<EXP>& m const matrix_exp<EXP>& m
) )
{ {
typedef matrix_unary_exp<EXP,op_mat_to_vect> exp; typedef op_mat_to_vect<EXP> op;
return exp(m.ref()); return matrix_op<op>(op(m.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_join_rows struct op_join_rows
{ {
template <typename EXP1, typename EXP2> op_join_rows(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {}
struct op : public has_destructive_aliasing const M1& m1;
{ const M2& m2;
template <typename T, typename U, bool selection> template <typename T, typename U, bool selection>
struct type_selector; struct type_selector;
template <typename T, typename U> template <typename T, typename U>
...@@ -2910,19 +3059,19 @@ namespace dlib ...@@ -2910,19 +3059,19 @@ namespace dlib
// If both const_ret_types are references then we should use them as the const_ret_type type // If both const_ret_types are references then we should use them as the const_ret_type type
// but otherwise we should use the normal type. // but otherwise we should use the normal type.
typedef typename EXP1::const_ret_type T1; typedef typename M1::const_ret_type T1;
typedef typename EXP1::type T2; typedef typename M1::type T2;
typedef typename EXP2::const_ret_type T3; typedef typename M2::const_ret_type T3;
typedef typename type_selector<T1, T2, is_reference_type<T1>::value && is_reference_type<T3>::value>::type const_ret_type; typedef typename type_selector<T1, T2, is_reference_type<T1>::value && is_reference_type<T3>::value>::type const_ret_type;
const static long cost = EXP1::cost + EXP2::cost + 1; const static long cost = M1::cost + M2::cost + 1;
const static long NR = tmax<EXP1::NR, EXP2::NR>::value; const static long NR = tmax<M1::NR, M2::NR>::value;
const static long NC = (EXP1::NC*EXP2::NC != 0)? (EXP1::NC+EXP2::NC) : (0); const static long NC = (M1::NC*M2::NC != 0)? (M1::NC+M2::NC) : (0);
typedef typename EXP1::type type; typedef typename M1::type type;
typedef typename EXP1::mem_manager_type mem_manager_type; typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
template <typename M1, typename M2> const_ret_type apply (long r, long c) const
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
{ {
if (c < m1.nc()) if (c < m1.nc())
return m1(r,c); return m1(r,c);
...@@ -2930,18 +3079,20 @@ namespace dlib ...@@ -2930,18 +3079,20 @@ namespace dlib
return m2(r,c-m1.nc()); return m2(r,c-m1.nc());
} }
template <typename M1, typename M2> long nr () const { return m1.nr(); }
static long nr (const M1& m1, const M2& ) { return m1.nr(); } long nc () const { return m1.nc()+m2.nc(); }
template <typename M1, typename M2>
static long nc (const M1& m1, const M2& m2 ) { return m1.nc()+m2.nc(); } template <typename U> bool aliases ( const matrix_exp<U>& item) const
}; { return m1.aliases(item) || m2.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || m2.aliases(item); }
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
inline const matrix_binary_exp<EXP1,EXP2,op_join_rows> join_rows ( inline const matrix_op<op_join_rows<EXP1,EXP2> > join_rows (
const matrix_exp<EXP1>& a, const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b const matrix_exp<EXP2>& b
) )
...@@ -2958,17 +3109,19 @@ namespace dlib ...@@ -2958,17 +3109,19 @@ namespace dlib
<< "\n\tb.nr(): " << b.nr() << "\n\tb.nr(): " << b.nr()
); );
typedef matrix_binary_exp<EXP1,EXP2,op_join_rows> exp; typedef op_join_rows<EXP1,EXP2> op;
return exp(a.ref(),b.ref()); return matrix_op<op>(op(a.ref(),b.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_join_cols struct op_join_cols
{ {
template <typename EXP1, typename EXP2> op_join_cols(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {}
struct op : public has_destructive_aliasing const M1& m1;
{ const M2& m2;
template <typename T, typename U, bool selection> template <typename T, typename U, bool selection>
struct type_selector; struct type_selector;
template <typename T, typename U> template <typename T, typename U>
...@@ -2978,21 +3131,21 @@ namespace dlib ...@@ -2978,21 +3131,21 @@ namespace dlib
// If both const_ret_types are references then we should use them as the const_ret_type type // If both const_ret_types are references then we should use them as the const_ret_type type
// but otherwise we should use the normal type. // but otherwise we should use the normal type.
typedef typename EXP1::const_ret_type T1; typedef typename M1::const_ret_type T1;
typedef typename EXP1::type T2; typedef typename M1::type T2;
typedef typename EXP2::const_ret_type T3; typedef typename M2::const_ret_type T3;
typedef typename type_selector<T1, T2, is_reference_type<T1>::value && is_reference_type<T3>::value>::type const_ret_type; typedef typename type_selector<T1, T2, is_reference_type<T1>::value && is_reference_type<T3>::value>::type const_ret_type;
const static long cost = EXP1::cost + EXP2::cost + 1; const static long cost = M1::cost + M2::cost + 1;
const static long NC = tmax<EXP1::NC, EXP2::NC>::value; const static long NC = tmax<M1::NC, M2::NC>::value;
const static long NR = (EXP1::NR*EXP2::NR != 0)? (EXP1::NR+EXP2::NR) : (0); const static long NR = (M1::NR*M2::NR != 0)? (M1::NR+M2::NR) : (0);
typedef typename EXP1::type type; typedef typename M1::type type;
typedef typename EXP1::mem_manager_type mem_manager_type; typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
template <typename M1, typename M2> const_ret_type apply ( long r, long c) const
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
{ {
if (r < m1.nr()) if (r < m1.nr())
return m1(r,c); return m1(r,c);
...@@ -3000,18 +3153,20 @@ namespace dlib ...@@ -3000,18 +3153,20 @@ namespace dlib
return m2(r-m1.nr(),c); return m2(r-m1.nr(),c);
} }
template <typename M1, typename M2> long nr () const { return m1.nr()+m2.nr(); }
static long nr (const M1& m1, const M2& m2 ) { return m1.nr()+m2.nr(); } long nc () const { return m1.nc(); }
template <typename M1, typename M2>
static long nc (const M1& m1, const M2& ) { return m1.nc(); } template <typename U> bool aliases ( const matrix_exp<U>& item) const
}; { return m1.aliases(item) || m2.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const
{ return m1.aliases(item) || m2.aliases(item); }
}; };
template < template <
typename EXP1, typename EXP1,
typename EXP2 typename EXP2
> >
inline const matrix_binary_exp<EXP1,EXP2,op_join_cols> join_cols ( inline const matrix_op<op_join_cols<EXP1,EXP2> > join_cols (
const matrix_exp<EXP1>& a, const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b const matrix_exp<EXP2>& b
) )
...@@ -3028,8 +3183,8 @@ namespace dlib ...@@ -3028,8 +3183,8 @@ namespace dlib
<< "\n\tb.nc(): " << b.nc() << "\n\tb.nc(): " << b.nc()
); );
typedef matrix_binary_exp<EXP1,EXP2,op_join_cols> exp; typedef op_join_cols<EXP1,EXP2> op;
return exp(a.ref(),b.ref()); return matrix_op<op>(op(a.ref(),b.ref()));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
...@@ -15,516 +15,158 @@ namespace dlib ...@@ -15,516 +15,158 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < typename kernel_type, typename alloc > namespace impl
class kernel_matrix_exp;
template < typename kernel_type, typename alloc >
struct matrix_traits<kernel_matrix_exp<kernel_type,alloc> >
{
typedef typename kernel_type::scalar_type type;
typedef const type const_ret_type;
typedef typename kernel_type::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type;
const static long NR = 0;
const static long NC = 0;
const static long cost = 100;
};
template <
typename kernel_type,
typename alloc
>
class kernel_matrix_exp : public matrix_exp<kernel_matrix_exp<kernel_type,alloc> >
{ {
typedef typename kernel_type::sample_type sample_type; template <typename kernel_type, typename T>
public: inline const typename T::type& access ( const matrix_exp<T>& m, long i)
typedef typename matrix_traits<kernel_matrix_exp>::type type;
typedef typename matrix_traits<kernel_matrix_exp>::const_ret_type const_ret_type;
typedef typename matrix_traits<kernel_matrix_exp>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<kernel_matrix_exp>::layout_type layout_type;
const static long NR = matrix_traits<kernel_matrix_exp>::NR;
const static long NC = matrix_traits<kernel_matrix_exp>::NC;
const static long cost = matrix_traits<kernel_matrix_exp>::cost;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1, typename T2>
kernel_matrix_exp (T1,T2);
public:
kernel_matrix_exp (
const kernel_type& kern_,
const std::vector<sample_type,alloc>& m_
) :
m(m_),
kern(kern_)
{}
const type operator() (
long r,
long c
) const { return kern(m[r],m[c]); }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return m.size(); }
long nc (
) const { return m.size(); }
const std::vector<sample_type,alloc>& m;
const kernel_type& kern;
};
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
>
const kernel_matrix_exp<kernel_type,alloc> kernel_matrix (
const kernel_type& kern,
const std::vector<typename kernel_type::sample_type,alloc>& m
)
{ {
typedef kernel_matrix_exp<kernel_type,alloc> exp; return m(i);
return exp(kern,m);
} }
// ---------------------------------------------------------------------------------------- template <typename kernel_type, typename T, typename alloc>
// ---------------------------------------------------------------------------------------- inline const T& access ( const std::vector<T,alloc>& m, long i)
// ----------------------------------------------------------------------------------------
template <typename kernel_type>
struct op_kern_mat
{
template <typename EXP>
struct op : has_destructive_aliasing
{ {
const static long NR = 0; return m[i];
const static long NC = 0; }
typedef typename EXP::mem_manager_type mem_manager_type;
const static long cost = EXP::cost+100; template <typename kernel_type, typename T, typename alloc>
typedef typename kernel_type::scalar_type type; inline const T& access ( const std_vector_c<T,alloc>& m, long i)
typedef const type const_ret_type;
template <typename M>
static const const_ret_type apply ( const M& m, const kernel_type& kern, const long r, long c)
{ {
return kern(m(r),m(c)); return m[i];
} }
template <typename M> template <typename kernel_type>
static long nr (const M& m) { return m.size(); } inline const typename kernel_type::sample_type& access (
template <typename M> const typename kernel_type::sample_type& samp,
static long nc (const M& m) { return m.size(); } long
};
};
// ----------------------------------------------------------------------------------------
template <
typename EXP,
typename kernel_type
>
const matrix_scalar_binary_exp<EXP, kernel_type, op_kern_mat<kernel_type> > kernel_matrix (
const kernel_type& kernel,
const matrix_exp<EXP>& m
) )
{ {
// make sure requires clause is not broken return samp;
DLIB_ASSERT(is_vector(m) == true,
"\tconst matrix_exp kernel_matrix(kernel,m)"
<< "\n\t You have to supply this function with a row or column vector"
<< "\n\t m.nr(): " << m.nr()
<< "\n\t m.nc(): " << m.nc()
);
typedef matrix_scalar_binary_exp<EXP, kernel_type, op_kern_mat<kernel_type> > exp;
return exp(m.ref(),kernel);
} }
// ---------------------------------------------------------------------------------------- // --------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template < typename kernel_type, typename lhs_type >
class kernel_matrix_exp1;
template < typename kernel_type, typename lhs_type > template <typename kernel_type, typename T>
struct matrix_traits<kernel_matrix_exp1<kernel_type,lhs_type> > inline unsigned long size ( const matrix_exp<T>& m)
{ {
typedef typename kernel_type::scalar_type type; return m.size();
typedef const type const_ret_type; }
typedef typename kernel_type::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type;
const static long NR = 0;
const static long NC = 1;
const static long cost = 100;
};
template < template <typename kernel_type, typename T, typename alloc>
typename kernel_type, inline unsigned long size ( const std::vector<T,alloc>& m)
typename lhs_type
>
class kernel_matrix_exp1 : public matrix_exp<kernel_matrix_exp1<kernel_type,lhs_type> >
{ {
typedef typename kernel_type::sample_type sample_type; return m.size();
public: }
typedef typename matrix_traits<kernel_matrix_exp1>::type type;
typedef typename matrix_traits<kernel_matrix_exp1>::type const_ret_type;
typedef typename matrix_traits<kernel_matrix_exp1>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<kernel_matrix_exp1>::layout_type layout_type;
const static long NR = matrix_traits<kernel_matrix_exp1>::NR;
const static long NC = matrix_traits<kernel_matrix_exp1>::NC;
const static long cost = matrix_traits<kernel_matrix_exp1>::cost;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1, typename T2, typename T3>
kernel_matrix_exp1 (T1,T2,T3);
public:
kernel_matrix_exp1 (
const kernel_type& kern_,
const lhs_type& m_,
const sample_type& samp_
) :
m(m_),
kern(kern_),
samp(samp_)
{}
const type operator() (
long r,
long
) const { return kern(vector_to_matrix(m)(r),samp); }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return m.size(); }
long nc (
) const { return 1; }
const lhs_type& m;
const kernel_type& kern;
const sample_type& samp;
};
// ---------------------------------------------------------------------------------------- template <typename kernel_type, typename T, typename alloc>
inline unsigned long size ( const std_vector_c<T,alloc>& m)
{
return m.size();
}
template < template <typename kernel_type>
typename kernel_type, inline unsigned long size (
typename alloc const typename kernel_type::sample_type&
>
const kernel_matrix_exp1<kernel_type,std::vector<typename kernel_type::sample_type,alloc> > kernel_matrix (
const kernel_type& kern,
const std::vector<typename kernel_type::sample_type,alloc>& m,
const typename kernel_type::sample_type& samp
) )
{ {
typedef kernel_matrix_exp1<kernel_type,std::vector<typename kernel_type::sample_type,alloc> > exp; return 1;
return exp(kern,m,samp);
} }
// ---------------------------------------------------------------------------------------- // --------------------------------------------
template < template <typename T>
typename kernel_type, typename disable_if<is_matrix<T> >::type assert_is_vector(const T&)
typename EXP {}
>
const kernel_matrix_exp1<kernel_type,EXP> kernel_matrix ( template <typename T>
const kernel_type& kern, void assert_is_vector(const matrix_exp<T>& v)
const matrix_exp<EXP>& m,
const typename kernel_type::sample_type& samp
)
{ {
// make sure requires clause is not broken // make sure requires clause is not broken
DLIB_ASSERT(is_vector(m) == true, DLIB_ASSERT(is_vector(v) == true,
"\tconst matrix_exp kernel_matrix(kernel,m, samp)" "\tconst matrix_exp kernel_matrix()"
<< "\n\t You have to supply this function with a row or column vector" << "\n\t You have to supply this function with row or column vectors"
<< "\n\t m.nr(): " << m.nr() << "\n\t v.nr(): " << v.nr()
<< "\n\t m.nc(): " << m.nc() << "\n\t v.nc(): " << v.nc()
); );
typedef kernel_matrix_exp1<kernel_type,EXP> exp;
return exp(kern,m.ref(),samp);
} }
// ---------------------------------------------------------------------------------------- }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template < typename kernel_type, typename lhs_type >
class kernel_matrix_exp2;
template < typename kernel_type, typename lhs_type >
struct matrix_traits<kernel_matrix_exp2<kernel_type,lhs_type> >
{
typedef typename kernel_type::scalar_type type;
typedef const type const_ret_type;
typedef typename kernel_type::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type;
const static long NR = 1;
const static long NC = 0;
const static long cost = 100;
};
template < template <typename K, typename vect_type1, typename vect_type2>
typename kernel_type, struct op_kern_mat : does_not_alias
typename lhs_type
>
class kernel_matrix_exp2 : public matrix_exp<kernel_matrix_exp2<kernel_type,lhs_type> >
{ {
typedef typename kernel_type::sample_type sample_type; op_kern_mat(
public: const K& kern_,
typedef typename matrix_traits<kernel_matrix_exp2>::type type; const vect_type1& vect1_,
typedef typename matrix_traits<kernel_matrix_exp2>::const_ret_type const_ret_type; const vect_type2& vect2_
typedef typename matrix_traits<kernel_matrix_exp2>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<kernel_matrix_exp2>::layout_type layout_type;
const static long NR = matrix_traits<kernel_matrix_exp2>::NR;
const static long NC = matrix_traits<kernel_matrix_exp2>::NC;
const static long cost = matrix_traits<kernel_matrix_exp2>::cost;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1, typename T2, typename T3>
kernel_matrix_exp2 (T1,T2,T3);
public:
kernel_matrix_exp2 (
const kernel_type& kern_,
const lhs_type& m_,
const sample_type& samp_
) : ) :
m(m_),
kern(kern_), kern(kern_),
samp(samp_) vect1(vect1_),
{} vect2(vect2_)
const type operator() (
long ,
long c
) const { return kern(vector_to_matrix(m)(c),samp); }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return 1; }
long nc (
) const { return m.size(); }
const lhs_type& m;
const kernel_type& kern;
const sample_type& samp;
};
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
>
const kernel_matrix_exp2<kernel_type,std::vector<typename kernel_type::sample_type,alloc> > kernel_matrix (
const kernel_type& kern,
const typename kernel_type::sample_type& samp,
const std::vector<typename kernel_type::sample_type,alloc>& m
)
{ {
typedef kernel_matrix_exp2<kernel_type,std::vector<typename kernel_type::sample_type,alloc> > exp; // make sure the requires clauses get checked eventually
return exp(kern,m,samp); impl::assert_is_vector(vect1);
impl::assert_is_vector(vect2);
} }
// ---------------------------------------------------------------------------------------- const K& kern;
const vect_type1& vect1;
template < const vect_type2& vect2;
typename kernel_type,
typename EXP
>
const kernel_matrix_exp2<kernel_type,EXP> kernel_matrix (
const kernel_type& kern,
const typename kernel_type::sample_type& samp,
const matrix_exp<EXP>& m
)
{
// make sure requires clause is not broken
DLIB_ASSERT(is_vector(m) == true,
"\tconst matrix_exp kernel_matrix(kernel,samp,m)"
<< "\n\t You have to supply this function with a row or column vector"
<< "\n\t m.nr(): " << m.nr()
<< "\n\t m.nc(): " << m.nc()
);
typedef kernel_matrix_exp2<kernel_type,EXP> exp;
return exp(kern,m.ref(),samp);
}
// ---------------------------------------------------------------------------------------- typedef typename K::scalar_type type;
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template < typename kernel_type, typename lhs_type, typename rhs_type > const static long cost = 100;
class kernel_matrix_exp3; const static long NR = (is_same_type<vect_type1,typename K::sample_type>::value) ? 1 : 0;
const static long NC = (is_same_type<vect_type2,typename K::sample_type>::value) ? 1 : 0;
template < typename kernel_type, typename lhs_type, typename rhs_type >
struct matrix_traits<kernel_matrix_exp3<kernel_type,lhs_type,rhs_type> >
{
typedef typename kernel_type::scalar_type type;
typedef const type const_ret_type; typedef const type const_ret_type;
typedef typename kernel_type::mem_manager_type mem_manager_type; typedef typename K::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type; typedef row_major_layout layout_type;
const static long NR = 0;
const static long NC = 0;
const static long cost = 100;
};
template < const_ret_type apply (long r, long c ) const
typename kernel_type,
typename lhs_type,
typename rhs_type
>
class kernel_matrix_exp3 : public matrix_exp<kernel_matrix_exp3<kernel_type,lhs_type,rhs_type> >
{ {
typedef typename kernel_type::sample_type sample_type; return kern(impl::access<K>(vect1,r), impl::access<K>(vect2,c));
public: }
typedef typename matrix_traits<kernel_matrix_exp3>::type type;
typedef typename matrix_traits<kernel_matrix_exp3>::const_ret_type const_ret_type;
typedef typename matrix_traits<kernel_matrix_exp3>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<kernel_matrix_exp3>::layout_type layout_type;
const static long NR = matrix_traits<kernel_matrix_exp3>::NR;
const static long NC = matrix_traits<kernel_matrix_exp3>::NC;
const static long cost = matrix_traits<kernel_matrix_exp3>::cost;
private:
// This constructor exists simply for the purpose of causing a compile time error if
// someone tries to create an instance of this object with the wrong kind of objects.
template <typename T1, typename T2, typename T3>
kernel_matrix_exp3 (T1,T2,T3);
public:
kernel_matrix_exp3 (
const kernel_type& kern_,
const lhs_type& lhs_,
const rhs_type& rhs_
) :
lhs(lhs_),
rhs(rhs_),
kern(kern_)
{}
const type operator() (
long r,
long c
) const { return kern(vector_to_matrix(lhs)(r),vector_to_matrix(rhs)(c)); }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return lhs.size(); }
long nc (
) const { return rhs.size(); }
const lhs_type& lhs; long nr () const { return impl::size<K>(vect1); }
const rhs_type& rhs; long nc () const { return impl::size<K>(vect2); }
const kernel_type& kern;
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
typename kernel_type, typename K,
typename alloc typename V1,
typename V2
> >
const kernel_matrix_exp3<kernel_type,std::vector<typename kernel_type::sample_type,alloc>, std::vector<typename kernel_type::sample_type,alloc> > kernel_matrix ( const matrix_op<op_kern_mat<K,V1,V2> > kernel_matrix (
const kernel_type& kern, const K& kern,
const std::vector<typename kernel_type::sample_type,alloc>& lhs, const V1& v1,
const std::vector<typename kernel_type::sample_type,alloc>& rhs const V2& v2
) )
{ {
typedef kernel_matrix_exp3<kernel_type, std::vector<typename kernel_type::sample_type,alloc>, std::vector<typename kernel_type::sample_type,alloc> > exp; typedef op_kern_mat<K,V1,V2> op;
return exp(kern,lhs,rhs); return matrix_op<op>(op(kern,v1,v2));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
typename kernel_type, typename K,
typename EXP1, typename V
typename EXP2
> >
const kernel_matrix_exp3<kernel_type,EXP1,EXP2> kernel_matrix ( const matrix_op<op_kern_mat<K,V,V> > kernel_matrix (
const kernel_type& kern, const K& kern,
const matrix_exp<EXP1>& lhs, const V& v
const matrix_exp<EXP2>& rhs
) )
{ {
// make sure requires clause is not broken typedef op_kern_mat<K,V,V> op;
DLIB_ASSERT(is_vector(lhs) == true && is_vector(rhs) == true, return matrix_op<op>(op(kern,v,v));
"\tconst matrix_exp kernel_matrix(kernel,lhs,rhs)"
<< "\n\t You have to supply this function with row or column vectors"
<< "\n\t lhs.nr(): " << lhs.nr()
<< "\n\t lhs.nc(): " << lhs.nc()
<< "\n\t rhs.nr(): " << rhs.nr()
<< "\n\t rhs.nc(): " << rhs.nc()
);
typedef kernel_matrix_exp3<kernel_type,EXP1,EXP2> exp;
return exp(kern,lhs.ref(), rhs.ref());
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
} }
#endif // DLIB_SVm_KERNEL_MATRIX_ #endif // DLIB_SVm_KERNEL_MATRIX_
...@@ -11,205 +11,86 @@ ...@@ -11,205 +11,86 @@
namespace dlib namespace dlib
{ {
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Symmetric Kernel Matrices
// ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
typename kernel_type, typename kernel_type,
typename alloc typename V
> >
const matrix_exp kernel_matrix ( const matrix_exp kernel_matrix (
const kernel_type& kernel, const kernel_type& kernel,
const std::vector<typename kernel_type::sample_type,alloc>& m const V& v
); );
/*! /*!
requires requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h - kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h.
This kernel must also be capable of operating on the contents of v.
- V == dlib::matrix, std::vector, dlib::std_vector_c, or kernel_type::sample_type.
- if (V is a dlib::matrix) then
- is_vector(v) == true
ensures ensures
- if (V is of type kernel_type::sample_type) then
- returns a matrix R such that: - returns a matrix R such that:
- R::type == kernel_type::scalar_type - R::type == kernel_type::scalar_type
- R is a square matrix of m.size() rows by m.size() columns - R.size() == 1
- for all valid r and c: - R(0,0) == kernel(v,v)
- R(r,c) == kernel(m[r], m[c]) - else
!*/
// ----------------------------------------------------------------------------------------
template <
typename kernel_type
>
const matrix_exp kernel_matrix (
const kernel_type& kernel,
const matrix_exp& m
)
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
- is_vector(m) == true
- the elements of m must be the type of element the given kernel operates on.
(e.g. kernel(m(0), m(1)) should be a legal expression)
ensures
- returns a matrix R such that: - returns a matrix R such that:
- R::type == kernel_type::scalar_type - R::type == kernel_type::scalar_type
- R is a square matrix of m.size() rows by m.size() columns - R is a square matrix of v.size() rows by v.size() columns
- for all valid r and c: - for all valid r and c:
- R(r,c) == kernel(m(r), m(c)) - R(r,c) == kernel(v(r), v(c))
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Column or Row Kernel Matrices
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
>
const matrix_exp kernel_matrix (
const kernel_type& kern,
const std::vector<typename kernel_type::sample_type,alloc>& m,
const typename kernel_type::sample_type& samp
);
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
ensures
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- is_col_vector(R) == true
- R.size() == m.size()
- for all valid i:
- R(i) == kernel(m[i], samp)
!*/
// ----------------------------------------------------------------------------------------
template <
typename kernel_type
>
const matrix_exp kernel_matrix (
const kernel_type& kern,
const matrix_exp& m,
const typename kernel_type::sample_type& samp
);
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
- is_vector(m) == true
- the elements of m must be the type of element the given kernel operates on.
(e.g. kernel(m(0), m(1)) should be a legal expression)
ensures
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- is_col_vector(R) == true
- R.size() == m.size()
- for all valid i:
- R(i) == kernel(m(i), samp)
!*/ !*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
typename kernel_type, typename kernel_type,
typename alloc typename V1,
typename V2
> >
const matrix_exp kernel_matrix ( const matrix_exp kernel_matrix (
const kernel_type& kern, const kernel_type& kernel,
const typename kernel_type::sample_type& samp, const V1& v1,
const std::vector<typename kernel_type::sample_type,alloc>& m const V2& v2
); );
/*! /*!
requires requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h - kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
This kernel must also be capable of operating on the contents of v1 and v2.
- V1 == dlib::matrix, std::vector, dlib::std_vector_c, or kernel_type::sample_type.
- V2 == dlib::matrix, std::vector, dlib::std_vector_c, or kernel_type::sample_type.
- if (V1 is a dlib::matrix) then
- is_vector(v1) == true
- if (V2 is a dlib::matrix) then
- is_vector(v2) == true
ensures ensures
- if (V1 and V2 are of type kernel_type::sample_type) then
- returns a matrix R such that: - returns a matrix R such that:
- R::type == kernel_type::scalar_type - R::type == kernel_type::scalar_type
- is_row_vector(R) == true - R.size() == 1
- R.size() == m.size() - R(0,0) == kernel(v1,v2)
- for all valid i: - else if (V1 is of type kernel_type::sample_type) then
- R(i) == kernel(samp,m[i])
!*/
// ----------------------------------------------------------------------------------------
template <
typename kernel_type
>
const matrix_exp kernel_matrix (
const kernel_type& kern,
const typename kernel_type::sample_type& samp,
const matrix_exp& m
);
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
- is_vector(m) == true
- the elements of m must be the type of element the given kernel operates on.
(e.g. kernel(m(0), m(1)) should be a legal expression)
ensures
- returns a matrix R such that: - returns a matrix R such that:
- R::type == kernel_type::scalar_type - R::type == kernel_type::scalar_type
- is_row_vector(R) == true - R.nr() == 1
- R.size() == m.size() - R.nc() == v2.size()
- for all valid i: - for all valid c:
- R(i) == kernel(samp, m(i)) - R(0,c) == kernel(v1, v2(c))
!*/ - else if (V2 is of type kernel_type::sample_type) then
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Rectangular Kernel Matrices
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
>
const matrix_exp kernel_matrix (
const kernel_type& kern,
const std::vector<typename kernel_type::sample_type,alloc>& lhs,
const std::vector<typename kernel_type::sample_type,alloc>& rhs
);
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
ensures
- returns a matrix R such that: - returns a matrix R such that:
- R::type == kernel_type::scalar_type - R::type == kernel_type::scalar_type
- R.nr() == lhs.size() - R.nr() == v1.size()
- R.nc() == rhs.size() - R.nc() == 1
- for all valid r and c: - for all valid r:
- R(r,c) == kernel(lhs[r], rhs[c]) - R(r,0) == kernel(v1(r), v2)
!*/ - else
// ----------------------------------------------------------------------------------------
template <
typename kernel_type
>
const kernel_matrix_exp3<kernel_type,EXP1,EXP2> kernel_matrix (
const kernel_type& kern,
const matrix_exp& lhs,
const matrix_exp& rhs
);
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
- is_vector(lhs) == true
- is_vector(rhs) == true
- the elements of lhs and rhs must be the type of element the given kernel operates on.
(e.g. kernel(lhs(0), rhs(0)) should be a legal expression)
ensures
- returns a matrix R such that: - returns a matrix R such that:
- R::type == kernel_type::scalar_type - R::type == kernel_type::scalar_type
- R.nr() == lhs.size() - R.nr() == v1.size()
- R.nc() == rhs.size() - R.nc() == v2.size()
- for all valid r and c: - for all valid r and c:
- R(r,c) == kernel(lhs(r), rhs(c)) - R(r,c) == kernel(v1(r), v2(c))
!*/ !*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment