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 @@
#ifndef DLIB_MATRIx_
#define DLIB_MATRIx_
#include "matrix_fwd.h"
#include "matrix_exp.h"
#include "matrix_abstract.h"
#include "../algs.h"
#include "../serialize.h"
......@@ -29,178 +29,6 @@
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
......
......@@ -3,6 +3,7 @@
#undef DLIB_MATRIx_ABSTRACT_
#ifdef DLIB_MATRIx_ABSTRACT_
#include "matrix_exp_abstract.h"
#include "../serialize.h"
#include "../memory_manager.h"
#include "matrix_data_layout_abstract.h"
......@@ -10,186 +11,6 @@
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 @@
#include "../enable_if.h"
#include "matrix_assign_fwd.h"
#include "matrix_default_mul.h"
#include "matrix_conj_trans.h"
namespace dlib
{
......@@ -70,8 +71,20 @@ namespace dlib
struct has_matrix_multiply<matrix_div_scal_exp<T> >
{ const static bool value = has_matrix_multiply<T>::value; };
template <typename T, typename OP>
struct has_matrix_multiply<matrix_unary_exp<T,OP> >
template <typename T>
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; };
// ------------------------------------------------------------------------------------
......@@ -112,31 +125,31 @@ namespace dlib
// ------------------------------------------------------------------------------------
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;
};
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;
};
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;
};
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;
};
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;
};
......@@ -215,8 +228,16 @@ namespace dlib
struct same_exp<matrix_div_scal_exp<T>, matrix_div_scal_exp<U>, layout >
{ const static bool value = same_exp<T,U,layout>::value; };
template <typename T, typename U, typename OP, typename layout>
struct same_exp<matrix_unary_exp<T,OP>, matrix_unary_exp<U,OP>, layout >
template <typename T, typename U, typename 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; };
// ------------------------------------------------------------------------------------
......@@ -410,7 +431,7 @@ namespace dlib
>
void matrix_assign_blas_proxy (
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,
bool add_to,
bool transpose
......@@ -574,13 +595,13 @@ namespace dlib
>
void matrix_assign_blas_proxy (
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,
bool add_to,
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
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>
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>
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
int get_inc (const matrix<T,NR,NC,MM,L>& ) { return 1; }
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>
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;
}
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>
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;
}
......@@ -366,27 +366,27 @@ namespace dlib
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;
}
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>
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;
}
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
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>
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>
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>
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>
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>
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>
......@@ -504,8 +504,8 @@ namespace dlib
const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs);
const int ldb = get_ld(src.rhs);
......@@ -534,8 +534,8 @@ namespace dlib
const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs);
const int lda = get_ld(src.lhs);
const T* B = get_ptr(src.rhs.m);
const int ldb = get_ld(src.rhs.m);
const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest);
......@@ -558,10 +558,10 @@ namespace dlib
const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const T* B = get_ptr(src.rhs.m);
const int ldb = get_ld(src.rhs.m);
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest);
......@@ -587,8 +587,8 @@ namespace dlib
const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs);
const int ldb = get_ld(src.rhs);
......@@ -615,10 +615,10 @@ namespace dlib
const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const T* B = get_ptr(src.rhs.m);
const int ldb = get_ld(src.rhs.m);
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest);
......@@ -645,8 +645,8 @@ namespace dlib
const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs);
const int lda = get_ld(src.lhs);
const T* B = get_ptr(src.rhs.m);
const int ldb = get_ld(src.rhs.m);
const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest);
......@@ -669,10 +669,10 @@ namespace dlib
const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const T* B = get_ptr(src.rhs.m);
const int ldb = get_ld(src.rhs.m);
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest);
......@@ -696,10 +696,10 @@ namespace dlib
const int M = static_cast<int>(src.nr());
const int N = static_cast<int>(src.nc());
const int K = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const T* B = get_ptr(src.rhs.m);
const int ldb = get_ld(src.rhs.m);
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* B = get_ptr(src.rhs.op.m);
const int ldb = get_ld(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* C = get_ptr(dest);
......@@ -775,8 +775,8 @@ namespace dlib
const int N = static_cast<int>(src.rhs.nc());
const T* A = get_ptr(src.rhs);
const int lda = get_ld(src.rhs);
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest);
......@@ -797,8 +797,8 @@ namespace dlib
const int N = static_cast<int>(src.lhs.nc());
const T* A = get_ptr(src.lhs);
const int lda = get_ld(src.lhs);
const T* X = get_ptr(src.rhs.m);
const int incX = get_inc(src.rhs.m);
const T* X = get_ptr(src.rhs.op.m);
const int incX = get_inc(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest);
......@@ -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 CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasTrans;
const int M = static_cast<int>(src.lhs.m.nr());
const int N = static_cast<int>(src.lhs.m.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const int M = static_cast<int>(src.lhs.op.m.nr());
const int N = static_cast<int>(src.lhs.op.m.nc());
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* X = get_ptr(src.rhs);
const int incX = get_inc(src.rhs);
......@@ -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 CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasNoTrans;
const int M = static_cast<int>(src.rhs.m.nr());
const int N = static_cast<int>(src.rhs.m.nc());
const T* A = get_ptr(src.rhs.m);
const int lda = get_ld(src.rhs.m);
const int M = static_cast<int>(src.rhs.op.m.nr());
const int N = static_cast<int>(src.rhs.op.m.nc());
const T* A = get_ptr(src.rhs.op.m);
const int lda = get_ld(src.rhs.op.m);
const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs);
......@@ -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 CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasNoTrans;
const int M = static_cast<int>(src.rhs.m.nr());
const int N = static_cast<int>(src.rhs.m.nc());
const T* A = get_ptr(src.rhs.m);
const int lda = get_ld(src.rhs.m);
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const int M = static_cast<int>(src.rhs.op.m.nr());
const int N = static_cast<int>(src.rhs.op.m.nc());
const T* A = get_ptr(src.rhs.op.m);
const int lda = get_ld(src.rhs.op.m);
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest);
......@@ -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 CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasTrans;
const int M = static_cast<int>(src.lhs.m.nr());
const int N = static_cast<int>(src.lhs.m.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const T* X = get_ptr(src.rhs.m);
const int incX = get_inc(src.rhs.m);
const int M = static_cast<int>(src.lhs.op.m.nr());
const int N = static_cast<int>(src.lhs.op.m.nc());
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* X = get_ptr(src.rhs.op.m);
const int incX = get_inc(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest);
......@@ -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 CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasConjTrans;
const int M = static_cast<int>(src.rhs.m.nr());
const int N = static_cast<int>(src.rhs.m.nc());
const T* A = get_ptr(src.rhs.m);
const int lda = get_ld(src.rhs.m);
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const int M = static_cast<int>(src.rhs.op.m.nr());
const int N = static_cast<int>(src.rhs.op.m.nc());
const T* A = get_ptr(src.rhs.op.m);
const int lda = get_ld(src.rhs.op.m);
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest);
......@@ -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 CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasConjTrans;
const int M = static_cast<int>(src.rhs.m.nr());
const int N = static_cast<int>(src.rhs.m.nc());
const T* A = get_ptr(src.rhs.m);
const int lda = get_ld(src.rhs.m);
const int M = static_cast<int>(src.rhs.op.m.nr());
const int N = static_cast<int>(src.rhs.op.m.nc());
const T* A = get_ptr(src.rhs.op.m);
const int lda = get_ld(src.rhs.op.m);
const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs);
......@@ -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 CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasConjTrans;
const int M = static_cast<int>(src.lhs.m.nr());
const int N = static_cast<int>(src.lhs.m.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const int M = static_cast<int>(src.lhs.op.m.nr());
const int N = static_cast<int>(src.lhs.op.m.nc());
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* X = get_ptr(src.rhs);
const int incX = get_inc(src.rhs);
......@@ -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 CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const CBLAS_TRANSPOSE TransA = CblasConjTrans;
const int M = static_cast<int>(src.lhs.m.nr());
const int N = static_cast<int>(src.lhs.m.nc());
const T* A = get_ptr(src.lhs.m);
const int lda = get_ld(src.lhs.m);
const T* X = get_ptr(src.rhs.m);
const int incX = get_inc(src.rhs.m);
const int M = static_cast<int>(src.lhs.op.m.nr());
const int N = static_cast<int>(src.lhs.op.m.nc());
const T* A = get_ptr(src.lhs.op.m);
const int lda = get_ld(src.lhs.op.m);
const T* X = get_ptr(src.rhs.op.m);
const int incX = get_inc(src.rhs.op.m);
const T beta = static_cast<T>(add_to?1:0);
T* Y = get_ptr(dest);
......@@ -1033,8 +1033,8 @@ namespace dlib
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const int M = static_cast<int>(dest.nr());
const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs);
const int incY = get_inc(src.rhs);
......@@ -1061,8 +1061,8 @@ namespace dlib
const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (add_to == false)
zero_matrix(dest);
......@@ -1085,10 +1085,10 @@ namespace dlib
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const int M = static_cast<int>(dest.nr());
const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (add_to == false)
zero_matrix(dest);
......@@ -1118,8 +1118,8 @@ namespace dlib
const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (add_to == false)
zero_matrix(dest);
......@@ -1145,8 +1145,8 @@ namespace dlib
const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (transpose == false)
......@@ -1175,10 +1175,10 @@ namespace dlib
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const int M = static_cast<int>(dest.nr());
const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (transpose == false)
......@@ -1208,10 +1208,10 @@ namespace dlib
const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor;
const int M = static_cast<int>(dest.nr());
const int N = static_cast<int>(dest.nc());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (add_to == false)
zero_matrix(dest);
......@@ -1254,8 +1254,8 @@ namespace dlib
{
//cout << "BLAS DOT: trans(cv)*cv" << endl;
const int N = static_cast<int>(src.lhs.size());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs);
const int incY = get_inc(src.rhs);
......@@ -1274,8 +1274,8 @@ namespace dlib
const int N = static_cast<int>(src.lhs.size());
const T* X = get_ptr(src.lhs);
const int incX = get_inc(src.lhs);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (add_to == false)
dest(0) = alpha*cblas_dot(N, X, incX, Y, incY);
......@@ -1289,11 +1289,11 @@ namespace dlib
DLIB_ADD_BLAS_BINDING(trans(cv)*trans(rv))
{
//cout << "BLAS DOT: trans(cv)*trans(rv)" << endl;
const int N = static_cast<int>(src.lhs.m.size());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const int N = static_cast<int>(src.lhs.op.m.size());
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (add_to == false)
dest(0) = alpha*cblas_dot(N, X, incX, Y, incY);
......@@ -1311,9 +1311,9 @@ namespace dlib
DLIB_ADD_BLAS_BINDING(conj(rv)*cv)
{
//cout << "BLAS DOTC: conj(rv)*cv" << endl;
const int N = static_cast<int>(src.lhs.m.size());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const int N = static_cast<int>(src.lhs.op.m.size());
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs);
const int incY = get_inc(src.rhs);
......@@ -1329,9 +1329,9 @@ namespace dlib
DLIB_ADD_BLAS_BINDING(conj(trans(cv))*cv)
{
//cout << "BLAS DOTC: conj(trans(cv))*cv" << endl;
const int N = static_cast<int>(src.lhs.m.size());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const int N = static_cast<int>(src.lhs.op.m.size());
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs);
const int incY = get_inc(src.rhs);
......@@ -1347,11 +1347,11 @@ namespace dlib
DLIB_ADD_BLAS_BINDING(trans(conj(cv))*trans(rv))
{
//cout << "BLAS DOTC: trans(conj(cv))*trans(rv)" << endl;
const int N = static_cast<int>(src.lhs.m.size());
const T* X = get_ptr(src.lhs.m);
const int incX = get_inc(src.lhs.m);
const T* Y = get_ptr(src.rhs.m);
const int incY = get_inc(src.rhs.m);
const int N = static_cast<int>(src.lhs.op.m.size());
const T* X = get_ptr(src.lhs.op.m);
const int incX = get_inc(src.lhs.op.m);
const T* Y = get_ptr(src.rhs.op.m);
const int incY = get_inc(src.rhs.op.m);
if (add_to == false)
dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY);
......
......@@ -22,44 +22,44 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_conj_trans
{
template <typename EXP>
struct op : has_destructive_aliasing
{
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)); }
op_conj_trans( const M& m_) : m(m_){}
const M& m;
template <typename M>
static long nr (const M& m) { return m.nc(); }
template <typename M>
static long nc (const M& m) { return m.nr(); }
};
const static long cost = M::cost;
const static long NR = M::NC;
const static long NC = 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>
const matrix_unary_exp<EXP,op_conj_trans> trans (
const matrix_unary_exp<EXP,op_conj>& m
const matrix_op<op_conj_trans<EXP> > trans (
const matrix_op<op_conj<EXP> >& m
)
{
typedef matrix_unary_exp<EXP,op_conj_trans> exp;
return exp(m.m);
typedef op_conj_trans<EXP> op;
return matrix_op<op>(op(m.op.m));
}
template <typename EXP>
const matrix_unary_exp<EXP,op_conj_trans> conj (
const matrix_unary_exp<EXP,op_trans>& m
const matrix_op<op_conj_trans<EXP> > conj (
const matrix_op<op_trans<EXP> >& m
)
{
typedef matrix_unary_exp<EXP,op_conj_trans> exp;
return exp(m.m);
typedef op_conj_trans<EXP> op;
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
// ----------------------------------------------------------------------------------------
// 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>
......@@ -1520,7 +187,7 @@ namespace dlib
const_ret_type operator() (
long c
) const { return std::pow(10,start + c*inc); }
) const { return std::pow((T)10,start + c*inc); }
template <typename U>
bool aliases (
......@@ -1609,5 +276,5 @@ namespace dlib
}
#endif // DLIB_MATRIx_UTILITIES_
#endif // DLIB_MATRIx_EXPRESSIONS_H_
......@@ -4,6 +4,7 @@
#define DLIB_MATRIx_MATH_FUNCTIONS
#include "matrix_math_functions_abstract.h"
#include "matrix_op.h"
#include "matrix_utilities.h"
#include "matrix.h"
#include "../algs.h"
......@@ -17,349 +18,214 @@ namespace dlib
// ----------------------------------------------------------------------------------------
#define DLIB_MATRIX_SIMPLE_STD_FUNCTION(name,extra_cost) struct op_##name { \
template <typename EXP> \
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP> \
{ \
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_DEFINE_FUNCTION_M(op_sqrt, sqrt, std::sqrt ,7);
DLIB_DEFINE_FUNCTION_M(op_log, log, std::log ,7);
DLIB_DEFINE_FUNCTION_M(op_log10, log10, std::log10 ,7);
DLIB_DEFINE_FUNCTION_M(op_exp, exp, std::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_MATRIX_SIMPLE_STD_FUNCTION(floor,7)
DLIB_DEFINE_FUNCTION_M(op_ceil, ceil, std::ceil ,7);
DLIB_DEFINE_FUNCTION_M(op_floor, floor, std::floor ,7);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(sin,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(cos,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(tan,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(sinh,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(cosh,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(tanh,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(asin,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(acos,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan,7)
DLIB_DEFINE_FUNCTION_M(op_sin, sin, std::sin ,7);
DLIB_DEFINE_FUNCTION_M(op_cos, cos, std::cos ,7);
DLIB_DEFINE_FUNCTION_M(op_tan, tan, std::tan ,7);
DLIB_DEFINE_FUNCTION_M(op_sinh, sinh, std::sinh ,7);
DLIB_DEFINE_FUNCTION_M(op_cosh, cosh, std::cosh ,7);
DLIB_DEFINE_FUNCTION_M(op_tanh, tanh, std::tanh ,7);
DLIB_DEFINE_FUNCTION_M(op_asin, asin, std::asin ,7);
DLIB_DEFINE_FUNCTION_M(op_acos, acos, std::acos ,7);
DLIB_DEFINE_FUNCTION_M(op_atan, atan, std::atan ,7);
// ----------------------------------------------------------------------------------------
struct op_sigmoid
namespace impl
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
template <typename type>
inline type sigmoid (const type& val)
{
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>(1/(1 + std::exp(-m(r,c))));
return static_cast<type>(1/(1 + std::exp(-val)));
}
};
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_sigmoid> sigmoid (
const matrix_exp<EXP>& m
)
template <typename type, typename S>
inline type round_zeros_eps (const type& val, const S& eps)
{
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
{
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;
if (val >= eps || val <= -eps)
return val;
else
return 0;
}
};
};
template <
typename EXP
>
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_round_zeros> round_zeros (
const matrix_exp<EXP>& m
)
template <typename type>
inline type round_zeros (const type& val)
{
// 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_scalar_binary_exp<EXP,typename EXP::type, op_round_zeros> exp;
return exp(m.ref(),10*std::numeric_limits<typename EXP::type>::epsilon());
}
COMPILE_TIME_ASSERT(is_built_in_scalar_type<type>::value);
template <
typename EXP
>
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_round_zeros> round_zeros (
const matrix_exp<EXP>& m,
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);
const type eps = 10*std::numeric_limits<type>::epsilon();
if (val >= eps || val <= -eps)
return val;
else
return 0;
}
// ----------------------------------------------------------------------------------------
struct op_cubed
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
template <typename type>
inline type squared (const type& val)
{
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)
{
const type temp = m(r,c);
return temp*temp*temp;
return val*val;
}
};
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_cubed> cubed (
const matrix_exp<EXP>& m
)
template <typename type>
type cubed (const type& val)
{
return matrix_unary_exp<EXP,op_cubed>(m.ref());
return val*val*val;
}
// ----------------------------------------------------------------------------------------
struct op_squared
template <typename type, typename S>
inline type pow1 (const type& val, const S& s)
{
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);
return temp*temp;
}
};
};
// you can only call pow() on matrices that contain floats, doubles or long doubles.
COMPILE_TIME_ASSERT((
is_same_type<type,float>::value == true ||
is_same_type<type,double>::value == true ||
is_same_type<type,long double>::value == true
));
template <
typename EXP
>
const matrix_unary_exp<EXP,op_squared> squared (
const matrix_exp<EXP>& m
)
{
return matrix_unary_exp<EXP,op_squared>(m.ref());
return std::pow(val,s);
}
// ----------------------------------------------------------------------------------------
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
)
template <typename type, typename S>
inline type pow2 (const S& s, const type& val)
{
// 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((
is_same_type<typename EXP::type,float>::value == true ||
is_same_type<typename EXP::type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true
is_same_type<type,float>::value == true ||
is_same_type<type,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>
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.
// you can only compute reciprocal matrices that contain floats, doubles or long doubles.
COMPILE_TIME_ASSERT((
is_same_type<typename EXP::type,float>::value == true ||
is_same_type<typename EXP::type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true
is_same_type<type,float>::value == true ||
is_same_type<type,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
{
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);
if (val != static_cast<type>(0))
return static_cast<type>((type)1.0/val);
else
return 0;
}
};
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_reciprocal> reciprocal (
const matrix_exp<EXP>& m
)
template <typename type>
inline type reciprocal_max (const type& val)
{
// 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((
is_same_type<typename EXP::type,float>::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,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
is_same_type<type,float>::value == true ||
is_same_type<type,double>::value == true ||
is_same_type<type,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>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
op_round( const M& m_) : basic_op_m<M>(m_){}
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;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
return static_cast<type>(std::floor(this->m(r,c)+0.5));
}
};
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);
if (temp != static_cast<type>(0))
return static_cast<type>((type)1.0/temp);
else
return std::numeric_limits<type>::max();
op_round( const M& m_) : basic_op_m<M>(m_){}
const static long cost = M::cost;
typedef typename M::type type;
typedef typename M::const_ret_type const_ret_type;
const_ret_type apply (long r, long c) const
{
return this->m(r,c);
}
};
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_reciprocal_max> reciprocal_max (
const matrix_op<op_round<EXP> > round (
const matrix_exp<EXP>& m
)
{
// you can only compute reciprocal_max matrices that contain floats, doubles or long doubles.
COMPILE_TIME_ASSERT((
is_same_type<typename EXP::type,float>::value == true ||
is_same_type<typename EXP::type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true
));
return matrix_unary_exp<EXP,op_reciprocal_max>(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<typename EXP::type>::value);
typedef op_round<EXP> op;
return matrix_op<op>(op(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>
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 <
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
)
{
......@@ -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,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)));
if (temp != 0.0)
temp = 1.0/temp;
return exp(m.ref(),temp);
return matrix_op<op>(op(m.ref(),temp));
}
// ----------------------------------------------------------------------------------------
struct op_round
{
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)
template <typename M, typename return_type = typename M::type>
struct op_abs : basic_op_m<M>
{
return static_cast<type>(std::floor(m(r,c)+0.5));
}
};
op_abs( const M& m_) : basic_op_m<M>(m_){}
template <typename EXP>
struct op<EXP,typename enable_if_c<std::numeric_limits<typename EXP::type>::is_integer>::type >
: 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;
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);
return static_cast<type>(std::abs(this->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());
}
// ----------------------------------------------------------------------------------------
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)
template <typename M, typename T>
struct op_abs<M, std::complex<T> > : basic_op_m<M>
{
return static_cast<type>(std::abs(m(r,c)));
}
};
op_abs( const M& m_) : basic_op_m<M>(m_){}
template <typename EXP, typename T>
struct op<EXP, std::complex<T> > : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost;
const static long cost = M::cost;
typedef T type;
typedef const T const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
const_ret_type apply ( long r, long c) const
{
return static_cast<type>(std::abs(m(r,c)));
return static_cast<type>(std::abs(this->m(r,c)));
}
};
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_abs> abs (
const matrix_op<op_abs<EXP> > abs (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<EXP,op_abs> exp;
return exp(m.ref());
typedef op_abs<EXP> op;
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>
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 <
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
)
{
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 EXP1, typename EXP2>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP1,EXP2>
template <typename M1, typename M2>
struct op_complex_matrix2 : basic_op_mm<M1,M2>
{
const static long cost = EXP1::cost+EXP2::cost+1;
typedef std::complex<typename EXP1::type> type;
typedef const std::complex<typename EXP1::type> const_ret_type;
op_complex_matrix2( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){}
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
{ return type(m1(r,c),m2(r,c)); }
};
const static long cost = M1::cost+M2::cost+1;
typedef std::complex<typename M1::type> type;
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 <
typename EXP1,
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<EXP2>& imag_part
)
......@@ -532,89 +350,84 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan,7)
<< "\n\timag_part.nr(): " << imag_part.nr()
<< "\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>
static const_ret_type apply ( const M& m, long r, long c)
{ return std::norm(m(r,c)); }
};
struct op_norm : basic_op_m<M>
{
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 <
typename EXP
>
const matrix_unary_exp<EXP,op_norm> norm (
const matrix_op<op_norm<EXP> > norm (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<EXP,op_norm> exp;
return exp(m.ref());
typedef op_norm<EXP> op;
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>
static const_ret_type apply ( const M& m, long r, long c)
{ return std::real(m(r,c)); }
};
struct op_real : basic_op_m<M>
{
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 <
typename EXP
>
const matrix_unary_exp<EXP,op_real> real (
const matrix_op<op_real<EXP> > real (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<EXP,op_real> exp;
return exp(m.ref());
typedef op_real<EXP> op;
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>
static const_ret_type apply ( const M& m, long r, long c)
{ return std::imag(m(r,c)); }
};
struct op_imag : basic_op_m<M>
{
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 <
typename EXP
>
const matrix_unary_exp<EXP,op_imag> imag (
const matrix_op<op_imag<EXP> > imag (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<EXP,op_imag> exp;
return exp(m.ref());
typedef op_imag<EXP> op;
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 @@
#define DLIB_MATRIx_SUBEXP_
#include "matrix_subexp_abstract.h"
#include "matrix_op.h"
#include "matrix.h"
#include "../geometry/rectangle.h"
#include "matrix_expressions.h"
......@@ -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 <
typename EXP
>
const matrix_sub_exp<EXP> subm (
const matrix_op<op_subm<EXP> > subm (
const matrix_exp<EXP>& m,
long r,
long c,
......@@ -81,8 +116,8 @@ namespace dlib
<< "\n\tnc: " << nc
);
typedef matrix_sub_exp<EXP> exp;
return exp(m.ref(),r,c,nr,nc);
typedef op_subm<EXP> op;
return matrix_op<op>(op(m.ref(),r,c,nr,nc));
}
// ----------------------------------------------------------------------------------------
......@@ -90,7 +125,7 @@ namespace dlib
template <
typename EXP
>
const matrix_sub_exp<EXP> subm (
const matrix_op<op_subm<EXP> > subm (
const matrix_exp<EXP>& m,
const rectangle& rect
)
......@@ -106,18 +141,46 @@ namespace dlib
<< "\n\trect.bottom(): " << rect.bottom()
);
typedef matrix_sub_exp<EXP> exp;
return exp(m.ref(),rect.top(),rect.left(),rect.height(),rect.width());
typedef op_subm<EXP> op;
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 <
typename EXP,
typename EXPr,
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<EXPr>& rows,
const matrix_exp<EXPc>& cols
......@@ -143,38 +206,39 @@ namespace dlib
<< "\n\tcols.nc(): " << cols.nc()
);
typedef matrix_sub_range_exp<EXP,EXPr,EXPc> exp;
return exp(m.ref(),rows.ref(),cols.ref());
typedef op_subm_range<EXP,EXPr,EXPc> op;
return matrix_op<op>(op(m.ref(),rows.ref(),cols.ref()));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_rowm
{
template <typename EXP>
struct op : has_destructive_aliasing
{
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); }
op_rowm(const M& m_, const long& row_) : m(m_), row(row_) {}
const M& m;
const long row;
template <typename M>
static long nr (const M& ) { return 1; }
template <typename M>
static long nc (const M& m) { return m.nc(); }
};
const static long cost = M::cost;
const static long NR = 1;
const static long NC = 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 <
typename EXP
>
const matrix_scalar_binary_exp<EXP,long,op_rowm> rowm (
const matrix_op<op_rowm<EXP> > rowm (
const matrix_exp<EXP>& m,
long row
)
......@@ -187,38 +251,40 @@ namespace dlib
<< "\n\trow: " << row
);
typedef matrix_scalar_binary_exp<EXP,long,op_rowm> exp;
return exp(m.ref(),row);
typedef op_rowm<EXP> op;
return matrix_op<op>(op(m.ref(),row));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_rowm2
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost;
op_rowm2(const M& m_, const long& row_, const long& len) : m(m_), row(row_), length(len) {}
const M& m;
const long row;
const long length;
const static long cost = M::cost;
const static long NR = 1;
const static long NC = 0;
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 , long c)
{ return m(row,c); }
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); }
template <typename M>
static long nr (const M& , long, long) { return 1; }
template <typename M>
static long nc (const M& , long, long length) { return length; }
};
long nr () const { return 1; }
long nc () const { 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 <
typename EXP
>
const matrix_scalar_ternary_exp<EXP,long,op_rowm2> rowm (
const matrix_op<op_rowm2<EXP> > rowm (
const matrix_exp<EXP>& m,
long row,
long length
......@@ -234,40 +300,43 @@ namespace dlib
<< "\n\tlength: " << length
);
typedef matrix_scalar_ternary_exp<EXP,long,op_rowm2> exp;
return exp(m.ref(),row, length);
typedef op_rowm2<EXP> op;
return matrix_op<op>(op(m.ref(), row, length));
}
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_rowm_range
{
template <typename EXP1, typename EXP2>
struct op : has_destructive_aliasing
{
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;
op_rowm_range( const M1& m1_, const M2& rows_) : m1(m1_), rows(rows_) {}
const M1& m1;
const M2& rows;
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& rows , long r, long c)
{ return m1(rows(r),c); }
const static long cost = M1::cost+M2::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 = M1::NC;
template <typename M1, typename M2>
static long nr (const M1& , const M2& rows ) { return rows.size(); }
template <typename M1, typename M2>
static long nc (const M1& m1, const M2& ) { return m1.nc(); }
};
const_ret_type apply ( long r, long c) const { return m1(rows(r),c); }
long nr () const { return rows.size(); }
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 <
typename EXP1,
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<EXP2>& rows
)
......@@ -286,38 +355,39 @@ namespace dlib
<< "\n\trows.nc(): " << rows.nc()
);
typedef matrix_binary_exp<EXP1,EXP2,op_rowm_range> exp;
return exp(m.ref(),rows.ref());
typedef op_rowm_range<EXP1,EXP2> op;
return matrix_op<op>(op(m.ref(),rows.ref()));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_colm
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost;
const static long NR = EXP::NR;
op_colm(const M& m_, const long& col_) : m(m_), col(col_) {}
const M& m;
const long col;
const static long cost = M::cost;
const static long NR = M::NR;
const static long NC = 1;
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 col, long r, long)
{ return m(r,col); }
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 r, long) const { return m(r,col); }
template <typename M>
static long nr (const M& m) { return m.nr(); }
template <typename M>
static long nc (const M& ) { return 1; }
};
long nr () const { return m.nr(); }
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 <
typename EXP
>
const matrix_scalar_binary_exp<EXP,long,op_colm> colm (
const matrix_op<op_colm<EXP> > colm (
const matrix_exp<EXP>& m,
long col
)
......@@ -330,38 +400,40 @@ namespace dlib
<< "\n\tcol: " << col
);
typedef matrix_scalar_binary_exp<EXP,long,op_colm> exp;
return exp(m.ref(),col);
typedef op_colm<EXP> op;
return matrix_op<op>(op(m.ref(),col));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_colm2
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost;
op_colm2(const M& m_, const long& col_, const long& len) : m(m_), col(col_), length(len) {}
const M& m;
const long col;
const long length;
const static long cost = M::cost;
const static long NR = 0;
const static long NC = 1;
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 col, long , long r, long )
{ return m(r,col); }
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 r, long ) const { return m(r,col); }
template <typename M>
static long nr (const M&, long, long length) { return length; }
template <typename M>
static long nc (const M&, long, long) { return 1; }
};
long nr () const { return length; }
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 <
typename EXP
>
const matrix_scalar_ternary_exp<EXP,long,op_colm2> colm (
const matrix_op<op_colm2<EXP> > colm (
const matrix_exp<EXP>& m,
long col,
long length
......@@ -377,40 +449,43 @@ namespace dlib
<< "\n\tlength: " << length
);
typedef matrix_scalar_ternary_exp<EXP,long,op_colm2> exp;
return exp(m.ref(),col, length);
typedef op_colm2<EXP> op;
return matrix_op<op>(op(m.ref(),col, length));
}
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_colm_range
{
template <typename EXP1, typename EXP2>
struct op : has_destructive_aliasing
{
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;
op_colm_range( const M1& m1_, const M2& cols_) : m1(m1_), cols(cols_) {}
const M1& m1;
const M2& cols;
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& cols , long r, long c)
{ return m1(r,cols(c)); }
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 = M1::NR;
const static long NC = M2::NC*M2::NR;
const static long cost = M1::cost+M2::cost;
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& , const M2& cols ) { return cols.size(); }
};
const_ret_type apply (long r, long c) const { return m1(r,cols(c)); }
long nr () const { return m1.nr(); }
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 <
typename EXP1,
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<EXP2>& cols
)
......@@ -429,8 +504,8 @@ namespace dlib
<< "\n\tcols.nc(): " << cols.nc()
);
typedef matrix_binary_exp<EXP1,EXP2,op_colm_range> exp;
return exp(m.ref(),cols.ref());
typedef op_colm_range<EXP1,EXP2> op;
return matrix_op<op>(op(m.ref(),cols.ref()));
}
// ----------------------------------------------------------------------------------------
......
......@@ -15,6 +15,7 @@
#include "../std_allocator.h"
#include "matrix_expressions.h"
#include "matrix_math_functions.h"
#include "matrix_op.h"
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 <
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 (
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 <
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 (
const vector_type& vector
)
{
typedef matrix_array_exp<vector_type> exp;
return exp(vector);
typedef op_array_to_mat<vector_type> op;
return matrix_op<op>(op(vector));
}
// ----------------------------------------------------------------------------------------
......@@ -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 <
typename value_type,
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
)
{
typedef matrix_std_vector_exp<std::vector<value_type,alloc> > exp;
return exp(vector);
typedef op_std_vect_to_mat<std::vector<value_type,alloc> > op;
return matrix_op<op>(op(vector));
}
// ----------------------------------------------------------------------------------------
......@@ -329,35 +394,45 @@ namespace dlib
typename value_type,
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
)
{
typedef matrix_std_vector_exp<std_vector_c<value_type,alloc> > exp;
return exp(vector);
typedef op_std_vect_to_mat<std_vector_c<value_type,alloc> > op;
return matrix_op<op>(op(vector));
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
struct op_pointer_to_col_vect : has_nondestructive_aliasing
template <typename T>
struct op_pointer_to_col_vect : does_not_alias
{
op_pointer_to_col_vect(
const T* ptr_,
const long size_
) : ptr(ptr_), size(size_){}
const T* ptr;
const long size;
const static long cost = 1;
const static long NR = 0;
const static long NC = 1;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
typedef T type;
typedef const T& const_ret_type;
static const_ret_type apply (const T* val, long r, long, long, long )
{ return val[r]; }
typedef memory_manager<char>::kernel_1a mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long ) const { return ptr[r]; }
long nr () const { return size; }
long nc () const { return 1; }
};
template <
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,
long nr
)
......@@ -367,31 +442,43 @@ namespace dlib
<< "\n\t nr must be bigger than 0"
<< "\n\t nr: " << nr
);
typedef dynamic_matrix_scalar_unary_exp<const T*,op_pointer_to_col_vect<T> > exp;
return exp(nr,1,ptr);
typedef op_pointer_to_col_vect<T> op;
return matrix_op<op>(op(ptr, nr));
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
struct op_pointer_to_mat : has_nondestructive_aliasing
template <typename T>
struct op_pointer_to_mat : does_not_alias
{
op_pointer_to_mat(
const T* ptr_,
const long nr_,
const long nc_
) : ptr(ptr_), rows(nr_), cols(nc_){}
const T* ptr;
const long rows;
const long cols;
const static long cost = 1;
const static long NR = 0;
const static long NC = 0;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
typedef T type;
typedef const T& const_ret_type;
static const_ret_type apply (const T* val, long r, long c, long , long nc )
{ return val[r*nc + c]; }
typedef memory_manager<char>::kernel_1a mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c) const { return ptr[r*cols + c]; }
long nr () const { return rows; }
long nc () const { return cols; }
};
template <
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,
long nr,
long nc
......@@ -403,45 +490,47 @@ namespace dlib
<< "\n\t nr: " << nr
<< "\n\t nc: " << nc
);
typedef dynamic_matrix_scalar_unary_exp<const T*,op_pointer_to_mat<T> > exp;
return exp(nr,nc,ptr);
typedef op_pointer_to_mat<T> op;
return matrix_op<op>(op(ptr,nr,nc));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_trans
{
template <typename EXP>
struct op : has_destructive_aliasing
{
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::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 r, long c)
{ return m(c,r); }
op_trans( const M& m_) : m(m_){}
const M& m;
const static long cost = M::cost;
const static long NR = M::NC;
const static long NC = M::NR;
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 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 <
typename EXP
typename M
>
const matrix_unary_exp<EXP,op_trans> trans (
const matrix_exp<EXP>& m
const matrix_op<op_trans<M> > trans (
const matrix_exp<M>& m
)
{
typedef matrix_unary_exp<EXP,op_trans> exp;
return exp(m.ref());
typedef op_trans<M> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
// I introduced this struct because it avoids an inane compiler warning from gcc
......@@ -540,20 +629,21 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <long R, long C>
template <typename M, long R, long C>
struct op_removerc
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+2;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1);
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1);
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 r, long c)
op_removerc( const M& m_) : m(m_){}
const M& m;
const static long cost = M::cost+2;
const static long NR = (M::NR==0) ? 0 : (M::NR - 1);
const static long NC = (M::NC==0) ? 0 : (M::NC - 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_ret_type apply (long r, long c) const
{
if (r < R)
{
......@@ -571,26 +661,29 @@ namespace dlib
}
}
template <typename M>
static long nr (const M& m) { return m.nr() - 1; }
template <typename M>
static long nc (const M& m) { return m.nc() - 1; }
};
long nr () const { return m.nr() - 1; }
long nc () const { 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
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+2;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1);
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1);
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 R, long C, long r, long c)
op_removerc2( const M& m_, const long R_, const long C_) : m(m_), R(R_), C(C_){}
const M& m;
const long R;
const long C;
const static long cost = M::cost+2;
const static long NR = (M::NR==0) ? 0 : (M::NR - 1);
const static long NC = (M::NC==0) ? 0 : (M::NC - 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_ret_type apply (long r, long c) const
{
if (r < R)
{
......@@ -608,11 +701,11 @@ namespace dlib
}
}
template <typename M, typename S>
static long nr (const M& m, S&, S&) { return m.nr() - 1; }
template <typename M, typename S>
static long nc (const M& m, S&, S&) { return m.nc() - 1; }
};
long nr () const { return m.nr() - 1; }
long nc () const { 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 <
......@@ -620,7 +713,7 @@ namespace dlib
long C,
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
)
{
......@@ -636,14 +729,14 @@ namespace dlib
<< "\n\tR: " << R
<< "\n\tC: " << C
);
typedef matrix_unary_exp<EXP,op_removerc<R,C> > exp;
return exp(m.ref());
typedef op_removerc<EXP,R,C> op;
return matrix_op<op>(op(m.ref()));
}
template <
typename EXP
>
const matrix_scalar_ternary_exp<EXP,long,op_removerc2> removerc (
const matrix_op<op_removerc2<EXP> > removerc (
const matrix_exp<EXP>& m,
long R,
long C
......@@ -657,26 +750,26 @@ namespace dlib
<< "\n\tR: " << R
<< "\n\tC: " << C
);
typedef matrix_scalar_ternary_exp<EXP,long,op_removerc2 > exp;
return exp(m.ref(),R,C);
typedef op_removerc2<EXP> op;
return matrix_op<op>(op(m.ref(),R,C));
}
// ----------------------------------------------------------------------------------------
template <long C>
template <typename M, long C>
struct op_remove_col
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = EXP::NR;
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1);
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 r, long c)
op_remove_col( const M& m_) : m(m_){}
const M& m;
const static long cost = M::cost+1;
const static long NR = M::NR;
const static long NC = (M::NC==0) ? 0 : (M::NC - 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_ret_type apply ( long r, long c) const
{
if (c < C)
{
......@@ -688,26 +781,28 @@ namespace dlib
}
}
template <typename M>
static long nr (const M& m) { return m.nr(); }
template <typename M>
static long nc (const M& m) { return m.nc() - 1; }
};
long nr () const { return m.nr(); }
long nc () const { 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
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = EXP::NR;
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1);
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 C, long r, long c)
op_remove_col2( const M& m_, const long C_) : m(m_), C(C_){}
const M& m;
const long C;
const static long cost = M::cost+1;
const static long NR = M::NR;
const static long NC = (M::NC==0) ? 0 : (M::NC - 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_ret_type apply ( long r, long c) const
{
if (c < C)
{
......@@ -719,18 +814,18 @@ namespace dlib
}
}
template <typename M>
static long nr (const M& m) { return m.nr(); }
template <typename M>
static long nc (const M& m) { return m.nc() - 1; }
};
long nr () const { return m.nr(); }
long nc () const { 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 <
long C,
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
)
{
......@@ -744,14 +839,14 @@ namespace dlib
<< "\n\tm.nc(): " << m.nc()
<< "\n\tC: " << C
);
typedef matrix_unary_exp<EXP,op_remove_col<C> > exp;
return exp(m.ref());
typedef op_remove_col<EXP,C> op;
return matrix_op<op>(op(m.ref()));
}
template <
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,
long C
)
......@@ -763,26 +858,26 @@ namespace dlib
<< "\n\tm.nc(): " << m.nc()
<< "\n\tC: " << C
);
typedef matrix_scalar_binary_exp<EXP,long,op_remove_col2> exp;
return exp(m.ref(),C);
typedef op_remove_col2<EXP> op;
return matrix_op<op>(op(m.ref(),C));
}
// ----------------------------------------------------------------------------------------
template <long R>
template <typename M, long R>
struct op_remove_row
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = (EXP::NR==0) ? 0 : (EXP::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 r, long c)
op_remove_row( const M& m_) : m(m_){}
const M& m;
const static long cost = M::cost+1;
const static long NR = (M::NR==0) ? 0 : (M::NR - 1);
const static long NC = 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 r, long c) const
{
if (r < R)
{
......@@ -794,26 +889,28 @@ namespace dlib
}
}
template <typename M>
static long nr (const M& m) { return m.nr() - 1; }
template <typename M>
static long nc (const M& m) { return m.nc(); }
};
long nr () const { return m.nr() - 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 <typename M>
struct op_remove_row2
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = (EXP::NR==0) ? 0 : (EXP::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 R, long r, long c)
op_remove_row2( const M& m_, const long R_) : m(m_), R(R_){}
const M& m;
const long R;
const static long cost = M::cost+1;
const static long NR = (M::NR==0) ? 0 : (M::NR - 1);
const static long NC = 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 r, long c) const
{
if (r < R)
{
......@@ -825,18 +922,18 @@ namespace dlib
}
}
template <typename M>
static long nr (const M& m) { return m.nr() - 1; }
template <typename M>
static long nc (const M& m) { return m.nc(); }
};
long nr () const { return m.nr() - 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 <
long R,
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
)
{
......@@ -850,14 +947,14 @@ namespace dlib
<< "\n\tm.nc(): " << m.nc()
<< "\n\tR: " << R
);
typedef matrix_unary_exp<EXP,op_remove_row<R> > exp;
return exp(m.ref());
typedef op_remove_row<EXP,R> op;
return matrix_op<op>(op(m.ref()));
}
template <
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,
long R
)
......@@ -869,26 +966,27 @@ namespace dlib
<< "\n\tm.nc(): " << m.nc()
<< "\n\tR: " << R
);
typedef matrix_scalar_binary_exp<EXP,long,op_remove_row2 > exp;
return exp(m.ref(),R);
typedef op_remove_row2<EXP> op;
return matrix_op<op>(op(m.ref(),R));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_diagm
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long N = EXP::NC*EXP::NR;
op_diagm( const M& m_) : m(m_){}
const M& m;
const static long cost = M::cost+1;
const static long N = M::NC*M::NR;
const static long NR = N;
const static long NC = N;
typedef typename EXP::type type;
typedef const typename EXP::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 r, long c)
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
{
if (r==c)
return m(r);
......@@ -896,17 +994,17 @@ namespace dlib
return 0;
}
template <typename M>
static long nr (const M& m) { 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(); }
};
long nr () const { return (m.nr()>m.nc())? m.nr():m.nc(); }
long nc () const { 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 <
typename EXP
>
const matrix_unary_exp<EXP,op_diagm> diagm (
const matrix_op<op_diagm<EXP> > diagm (
const matrix_exp<EXP>& m
)
{
......@@ -918,102 +1016,104 @@ namespace dlib
<< "\n\tm.nr(): " << m.nr()
<< "\n\tm.nc(): " << m.nc()
);
typedef matrix_unary_exp<EXP,op_diagm> exp;
return exp(m.ref());
typedef op_diagm<EXP> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_diag
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost;
const static long NR = (EXP::NC&&EXP::NR)? (tmin<EXP::NR,EXP::NC>::value) : (0);
op_diag( const M& m_) : m(m_){}
const M& m;
const static long cost = M::cost;
const static long NR = (M::NC&&M::NR)? (tmin<M::NR,M::NC>::value) : (0);
const static long NC = 1;
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 r, long )
{ return m(r,r); }
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 r, long ) const { return m(r,r); }
template <typename M>
static long nr (const M& m) { return std::min(m.nc(),m.nr()); }
template <typename M>
static long nc (const M& ) { return 1; }
};
long nr () const { return std::min(m.nc(),m.nr()); }
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 <
typename EXP
>
const matrix_unary_exp<EXP,op_diag> diag (
const matrix_op<op_diag<EXP> > diag (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<EXP,op_diag> exp;
return exp(m.ref());
typedef op_diag<EXP> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
template <typename target_type>
template <typename M, typename target_type>
struct op_cast
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost;
op_cast( const M& m_) : m(m_){}
const M& m;
const static long cost = M::cost;
const static long NR = M::NR;
const static long NC = M::NC;
typedef target_type type;
typedef const target_type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{ return static_cast<target_type>(m(r,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 { 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 <
typename target_type,
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
)
{
typedef matrix_unary_exp<EXP,op_cast<target_type> > exp;
return exp(m.ref());
typedef op_cast<EXP, target_type> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
struct op_lessthan
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
namespace impl
{
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)
template <typename type, typename S>
inline type lessthan(const type& val, const S& s)
{
if (m(r,c) < s)
if (val < s)
return 1;
else
return 0;
}
};
};
}
DLIB_DEFINE_OP_MS(op_lessthan, impl::lessthan, 1);
template <
typename EXP,
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 S& s
)
......@@ -1022,14 +1122,15 @@ namespace dlib
// long, float, etc.
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 <
typename EXP,
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 matrix_exp<EXP>& m
)
......@@ -1038,88 +1139,81 @@ namespace dlib
// long, float, etc.
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>
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, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
template <typename type, typename S>
inline type lessthan_eq(const type& val, const S& s)
{
if (m(r,c) <= s)
if (val <= s)
return 1;
else
return 0;
}
};
};
}
DLIB_DEFINE_OP_MS(op_lessthan_eq, impl::lessthan_eq, 1);
template <
typename EXP,
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 S& s
)
{
// you can only use this relational operator with the built in scalar types like
// 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 <
typename EXP,
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 matrix_exp<EXP>& m
)
{
// you can only use this relational operator with the built in scalar types like
// 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>
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, typename S>
static const_ret_type apply ( const M& m, const S& s, long r, long c)
template <typename type, typename S>
inline type greaterthan(const type& val, const S& s)
{
if (m(r,c) > s)
if (val > s)
return 1;
else
return 0;
}
};
};
}
DLIB_DEFINE_OP_MS(op_greaterthan, impl::greaterthan, 1);
template <
typename EXP,
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 S& s
)
......@@ -1128,14 +1222,15 @@ namespace dlib
// long, float, etc.
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 <
typename EXP,
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 matrix_exp<EXP>& m
)
......@@ -1144,88 +1239,81 @@ namespace dlib
// long, float, etc.
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
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
namespace impl
{
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)
template <typename type, typename S>
inline type greaterthan_eq(const type& val, const S& s)
{
if (m(r,c) >= s)
if (val >= s)
return 1;
else
return 0;
}
};
};
}
DLIB_DEFINE_OP_MS(op_greaterthan_eq, impl::greaterthan_eq, 1);
template <
typename EXP,
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 S& s
)
{
// you can only use this relational operator with the built in scalar types like
// 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 <
typename EXP,
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 matrix_exp<EXP>& m
)
{
// you can only use this relational operator with the built in scalar types like
// 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
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
namespace impl
{
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)
template <typename type, typename S>
inline type equal_to(const type& val, const S& s)
{
if (m(r,c) == s)
if (val == s)
return 1;
else
return 0;
}
};
};
}
DLIB_DEFINE_OP_MS(op_equal_to, impl::equal_to, 1);
template <
typename EXP,
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 S& s
)
......@@ -1234,14 +1322,15 @@ namespace dlib
// long, float, etc.
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 <
typename EXP,
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 matrix_exp<EXP>& m
)
......@@ -1250,35 +1339,32 @@ namespace dlib
// long, float, etc.
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
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
namespace impl
{
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)
template <typename type, typename S>
inline type not_equal_to(const type& val, const S& s)
{
if (m(r,c) != s)
if (val != s)
return 1;
else
return 0;
}
};
};
}
DLIB_DEFINE_OP_MS(op_not_equal_to, impl::not_equal_to, 1);
template <
typename EXP,
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 S& s
)
......@@ -1287,14 +1373,15 @@ namespace dlib
// long, float, etc.
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 <
typename EXP,
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 matrix_exp<EXP>& m
)
......@@ -1303,7 +1390,8 @@ namespace dlib
// long, float, etc.
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
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_sumr
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost;
op_sumr(const M& m_) : m(m_) {}
const M& m;
const static long cost = M::cost;
const static long NR = 1;
const static long NC = EXP::NC;
typedef typename EXP::type type;
typedef const typename EXP::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 , long c)
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 , long c) const
{
type temp = m(0,c);
for (long r = 1; r < m.nr(); ++r)
......@@ -1440,17 +1529,17 @@ namespace dlib
return temp;
}
template <typename M>
static long nr (const M& ) { return 1; }
template <typename M>
static long nc (const M& m) { return m.nc(); }
};
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 <
typename EXP
>
const matrix_unary_exp<EXP,op_sumr> sum_rows (
const matrix_op<op_sumr<EXP> > sum_rows (
const matrix_exp<EXP>& m
)
{
......@@ -1459,25 +1548,26 @@ namespace dlib
<< "\n\t The matrix can't be empty"
<< "\n\t m.size(): " << m.size()
);
typedef matrix_unary_exp<EXP,op_sumr> exp;
return exp(m.ref());
typedef op_sumr<EXP> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_sumc
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost;
const static long NR = EXP::NR;
op_sumc(const M& m_) : m(m_) {}
const M& m;
const static long cost = M::cost;
const static long NR = M::NR;
const static long NC = 1;
typedef typename EXP::type type;
typedef const typename EXP::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 r, long )
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 ) const
{
type temp = m(r,0);
for (long c = 1; c < m.nc(); ++c)
......@@ -1485,17 +1575,17 @@ namespace dlib
return temp;
}
template <typename M>
static long nr (const M& m) { return m.nr(); }
template <typename M>
static long nc (const M& ) { return 1; }
};
long nr () const { return m.nr(); }
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 <
typename EXP
>
const matrix_unary_exp<EXP,op_sumc> sum_cols (
const matrix_op<op_sumc<EXP> > sum_cols (
const matrix_exp<EXP>& m
)
{
......@@ -1504,8 +1594,8 @@ namespace dlib
<< "\n\t The matrix can't be empty"
<< "\n\t m.size(): " << m.size()
);
typedef matrix_unary_exp<EXP,op_sumc> exp;
return exp(m.ref());
typedef op_sumc<EXP> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
......@@ -1644,22 +1734,32 @@ namespace dlib
template <
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 NR = 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 const T& const_ret_type;
static const_ret_type apply (const T& val, long , long, long, long )
{ return val; }
const_ret_type apply (long, long ) const { return val; }
long nr() const { return rows; }
long nc() const { return cols; }
};
template <
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 nc,
const T& val
......@@ -1671,8 +1771,8 @@ namespace dlib
<< "\n\tnr: " << nr
<< "\n\tnc: " << nc
);
typedef dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > exp;
return exp(nr,nc,val);
typedef op_uniform_matrix_3<T> op;
return matrix_op<op>(op(nr, nc, val));
}
// ----------------------------------------------------------------------------------------
......@@ -1680,7 +1780,7 @@ namespace dlib
template <
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 nc
)
......@@ -1691,8 +1791,8 @@ namespace dlib
<< "\n\tnr: " << nr
<< "\n\tnc: " << nc
);
typedef dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > exp;
return exp(nr,nc,0);
typedef op_uniform_matrix_3<T> op;
return matrix_op<op>(op(nr, nc, 0));
}
// ----------------------------------------------------------------------------------------
......@@ -1700,7 +1800,7 @@ namespace dlib
template <
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 nc
)
......@@ -1711,8 +1811,8 @@ namespace dlib
<< "\n\tnr: " << nr
<< "\n\tnc: " << nc
);
typedef dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > exp;
return exp(nr,nc,1);
typedef op_uniform_matrix_3<T> op;
return matrix_op<op>(op(nr, nc, 1));
}
// ----------------------------------------------------------------------------------------
......@@ -1722,16 +1822,23 @@ namespace dlib
long NR_,
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 NR = NR_;
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 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 <
......@@ -1739,14 +1846,14 @@ namespace dlib
long NR,
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
)
{
COMPILE_TIME_ASSERT(NR > 0 && NC > 0);
typedef matrix_scalar_unary_exp<T,op_uniform_matrix_2<T,NR,NC> > exp;
return exp(val);
typedef op_uniform_matrix_2<T,NR,NC> op;
return matrix_op<op>(op(val));
}
// ----------------------------------------------------------------------------------------
......@@ -1757,16 +1864,19 @@ namespace dlib
long NC_,
T val
>
struct op_uniform_matrix : has_nondestructive_aliasing
struct op_uniform_matrix : does_not_alias
{
const static long cost = 1;
const static long NR = NR_;
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 const T const_ret_type;
static const_ret_type apply ( long , long )
{ return val; }
const_ret_type apply ( long , long ) const { return val; }
long nr() const { return NR; }
long nc() const { return NC; }
};
template <
......@@ -1775,12 +1885,12 @@ namespace dlib
long NC,
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);
typedef matrix_zeroary_exp<op_uniform_matrix<T,NR,NC,val> > exp;
return exp();
typedef op_uniform_matrix<T,NR,NC,val> op;
return matrix_op<op>(op());
}
// ----------------------------------------------------------------------------------------
......@@ -1788,22 +1898,29 @@ namespace dlib
template <
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 NR = 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 const T const_ret_type;
static const_ret_type apply (const T&, long r, long c, long, long)
{ return static_cast<type>(r == c); }
const_ret_type apply (long r, long c) const { return static_cast<type>(r == c); }
long nr() const { return size; }
long nc() const { return size; }
};
template <
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
)
{
......@@ -1812,10 +1929,8 @@ namespace dlib
<< "\n\tsize must be bigger than 0"
<< "\n\tsize: " << size
);
typedef dynamic_matrix_scalar_unary_exp<T,op_identity_matrix_2<T> > exp;
// the scalar value of the dynamic_matrix_scalar_unary_exp just isn't
// used by this operator
return exp(size,size,0);
typedef op_identity_matrix_2<T> op;
return matrix_op<op>(op(size));
}
// ----------------------------------------------------------------------------------------
......@@ -1824,51 +1939,56 @@ namespace dlib
typename T,
long N
>
struct op_identity_matrix : has_nondestructive_aliasing
struct op_identity_matrix : does_not_alias
{
const static long cost = 1;
const static long NR = 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 const T const_ret_type;
static const_ret_type apply ( long r, long c)
{ return static_cast<type>(r == c); }
const_ret_type apply ( long r, long c) const { return static_cast<type>(r == c); }
template <typename M>
static long nr (const M&) { return NR; }
template <typename M>
static long nc (const M&) { return NC; }
long nr () const { return NR; }
long nc () const { return NC; }
};
template <
typename T,
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);
typedef matrix_zeroary_exp<op_identity_matrix<T,N> > exp;
return exp();
typedef op_identity_matrix<T,N> op;
return matrix_op<op>(op());
}
// ----------------------------------------------------------------------------------------
template <long R, long C>
template <typename M, long R, long C>
struct op_rotate
{
template <typename EXP>
struct op : has_destructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost + 1;
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+R)%m.nr(),(c+C)%m.nc()); }
};
op_rotate(const M& m_) : m(m_) {}
const M& m;
const static long cost = M::cost + 1;
const static long NR = M::NR;
const static long NC = 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 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 <
......@@ -1876,18 +1996,17 @@ namespace dlib
long C,
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
)
{
typedef matrix_unary_exp<EXP,op_rotate<R,C> > exp;
return exp(m.ref());
typedef op_rotate<EXP,R,C> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
struct op_pointwise_multiply
namespace impl
{
// 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.
......@@ -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<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 EXP1, typename EXP2>
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2>
template <typename M1, typename M2>
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;
const static long cost = EXP1::cost + EXP2::cost + 1;
const static long cost = M1::cost + M2::cost + 1;
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
{ return m1(r,c)*m2(r,c); }
};
const_ret_type apply ( long r, long c) const
{ return this->m1(r,c)*this->m2(r,c); }
};
template <
typename EXP1,
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<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::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0);
DLIB_ASSERT(a.nr() == b.nr() &&
......@@ -1930,25 +2051,24 @@ namespace dlib
<< "\n\tb.nr(): " << b.nr()
<< "\n\tb.nc(): " << b.nc()
);
typedef matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> exp;
return exp(a.ref(),b.ref());
typedef op_pointwise_multiply<EXP1,EXP2> op;
return matrix_op<op>(op(a.ref(),b.ref()));
}
// ----------------------------------------------------------------------------------------
struct op_pointwise_multiply3
{
template <typename EXP1, typename EXP2, typename EXP3>
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2,EXP3>
template <typename M1, typename M2, typename M3>
struct op_pointwise_multiply3 : basic_op_mmm<M1,M2,M3>
{
typedef typename EXP1::type type;
typedef const typename EXP1::type const_ret_type;
const static long cost = EXP1::cost + EXP2::cost + EXP3::cost + 2;
op_pointwise_multiply3( const M1& m1_, const M2& m2_, const M3& m3_) :
basic_op_mmm<M1,M2,M3>(m1_,m2_,m3_){}
template <typename M1, typename M2, typename M3>
static const_ret_type apply ( const M1& m1, const M2& m2, const M3& m3 , long r, long c)
{ return m1(r,c)*m2(r,c)*m3(r,c); }
};
typedef typename M1::type type;
typedef const typename M1::type const_ret_type;
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 <
......@@ -1956,7 +2076,7 @@ namespace dlib
typename EXP2,
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 (
const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b,
......@@ -1982,35 +2102,35 @@ namespace dlib
<< "\n\tc.nr(): " << c.nr()
<< "\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 EXP1, typename EXP2, typename EXP3, typename EXP4>
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2,EXP3,EXP4>
template <typename M1, typename M2, typename M3, typename M4>
struct op_pointwise_multiply4 : basic_op_mmmm<M1,M2,M3,M4>
{
typedef typename EXP1::type type;
typedef const typename EXP1::type const_ret_type;
const static long cost = EXP1::cost + EXP2::cost + EXP3::cost + EXP4::cost + 3;
op_pointwise_multiply4( const M1& m1_, const M2& m2_, const M3& m3_, const M4& m4_) :
basic_op_mmmm<M1,M2,M3,M4>(m1_,m2_,m3_,m4_){}
template <typename M1, typename M2, typename M3, typename M4>
static const_ret_type apply ( const M1& m1, const M2& m2, const M3& m3, const M4& m4 , long r, long c)
{ return m1(r,c)*m2(r,c)*m3(r,c)*m4(r,c); }
};
typedef typename M1::type type;
typedef const typename M1::type const_ret_type;
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 <
typename EXP1,
typename EXP2,
typename EXP3,
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<EXP2>& b,
const matrix_exp<EXP3>& c,
......@@ -2044,8 +2164,8 @@ namespace dlib
<< "\n\td.nc(): " << d.nc()
);
typedef matrix_fourary_exp<EXP1,EXP2,EXP3,EXP4,op_pointwise_multiply4> exp;
return exp(a.ref(),b.ref(),c.ref(),d.ref());
typedef op_pointwise_multiply4<EXP1,EXP2,EXP3,EXP4> op;
return matrix_op<op>(op(a.ref(),b.ref(),c.ref(),d.ref()));
}
// ----------------------------------------------------------------------------------------
......@@ -2223,20 +2343,18 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <long lower, long upper>
struct op_clamp
template <typename M, long lower, long upper>
struct op_clamp : basic_op_m<M>
{
template <typename EXP>
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;
op_clamp( const M& m_) : basic_op_m<M>(m_){}
template <typename M>
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 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))
return static_cast<type>(upper);
else if (temp < static_cast<type>(lower))
......@@ -2245,36 +2363,39 @@ namespace dlib
return temp;
}
};
};
template <
long l,
long u,
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
)
{
typedef matrix_unary_exp<EXP,op_clamp<l,u> > exp;
return exp(m.ref());
typedef op_clamp<EXP,l,u> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
struct op_clamp2
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
template <typename M>
struct op_clamp2 : basic_op_m<M>
{
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
const static long cost = EXP::cost + 2;
typedef typename M::type type;
template <typename M>
static const_ret_type apply ( const M& m, const type& lower, const type& upper, long r, long c)
op_clamp2( const M& m_, const type& l, const type& u) :
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)
return upper;
else if (temp < lower)
......@@ -2283,53 +2404,55 @@ namespace dlib
return temp;
}
};
};
template <
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 typename EXP::type& lower,
const typename EXP::type& upper
)
{
typedef matrix_scalar_ternary_exp<EXP,typename EXP::type, op_clamp2> exp;
return exp(m.ref(),lower, upper);
typedef op_clamp2<EXP> op;
return matrix_op<op>(op(m.ref(),lower, upper));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_reshape
{
template <typename EXP>
struct op : public has_destructive_aliasing
{
const static long cost = EXP::cost+1;
op_reshape(const M& m_, const long& rows_, const long& cols_) : m(m_),rows(rows_),cols(cols_) {}
const M& m;
const long rows;
const long cols;
const static long cost = M::cost+1;
const static long NR = 0;
const static long NC = 0;
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 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;
template <typename M>
static const_ret_type apply ( const M& m, const long& , const long& cols, long r, long c)
const_ret_type apply ( long r, long c) const
{
const long idx = r*cols + c;
return m(idx/m.nc(), idx%m.nc());
}
template <typename M1 >
static long nr (const M1& , const long& rows, const long& ) { return rows; }
template <typename M1>
static long nc (const M1& , const long&, const long& cols ) { return cols; }
};
long nr () const { return rows; }
long nc () const { 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 <
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 long& rows,
const long& cols
......@@ -2344,8 +2467,8 @@ namespace dlib
<< "\n\t cols: " << cols
);
typedef matrix_scalar_ternary_exp<EXP, long, op_reshape> exp;
return exp(m.ref(), rows, cols);
typedef op_reshape<EXP> op;
return matrix_op<op>(op(m.ref(), rows, cols));
}
// ----------------------------------------------------------------------------------------
......@@ -2407,34 +2530,37 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_scale_columns
{
template <typename EXP1, typename EXP2>
struct op : has_nondestructive_aliasing
{
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;
op_scale_columns(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {}
const M1& m1;
const M2& m2;
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
{ return m1(r,c)*m2(c); }
const static long cost = M1::cost + M2::cost + 1;
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 static long NR = M1::NR;
const static long NC = M1::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(); }
};
const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(c); }
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.aliases(item); }
};
template <
typename EXP1,
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<EXP2>& v
)
......@@ -2451,8 +2577,8 @@ namespace dlib
<< "\n\tv.nr(): " << v.nr()
<< "\n\tv.nc(): " << v.nc()
);
typedef matrix_binary_exp<EXP1,EXP2,op_scale_columns> exp;
return exp(m.ref(),v.ref());
typedef op_scale_columns<EXP1,EXP2> op;
return matrix_op<op>(op(m.ref(),v.ref()));
}
// ----------------------------------------------------------------------------------------
......@@ -2563,157 +2689,173 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_tensor_product
{
template <typename EXP1, typename EXP2>
struct op : public has_destructive_aliasing
{
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;
op_tensor_product(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {}
const M1& m1;
const M2& m2;
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
const static long cost = M1::cost + M2::cost + 1;
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());
}
long nr () const { return m1.nr()*m2.nr(); }
long nc () const { return m1.nc()*m2.nc(); }
template <typename M1, typename M2>
static long nr (const M1& m1, const M2& m2 ) { return m1.nr()*m2.nr(); }
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 <
typename EXP1,
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<EXP2>& b
)
{
COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true));
typedef matrix_binary_exp<EXP1,EXP2,op_tensor_product> exp;
return exp(a.ref(),b.ref());
typedef op_tensor_product<EXP1,EXP2> op;
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>
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)
return m(r,c);
return this->m(r,c);
else
return 0;
}
};
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)
return m(r,c);
return this->m(r,c);
else if (r==c)
return s;
else
return 0;
}
};
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_lowerm> lowerm (
const matrix_op<op_lowerm<EXP> > lowerm (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<EXP,op_lowerm> exp;
return exp(m.ref());
typedef op_lowerm<EXP> op;
return matrix_op<op>(op(m.ref()));
}
template <
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,
typename EXP::type s
)
{
typedef matrix_scalar_binary_exp<EXP, typename EXP::type, op_lowerm> exp;
return exp(m.ref(),s);
typedef op_lowerm_s<EXP> op;
return matrix_op<op>(op(m.ref(),s));
}
// ----------------------------------------------------------------------------------------
struct op_upperm
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
template <typename M>
struct op_upperm : basic_op_m<M>
{
const static long cost = EXP::cost+1;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
op_upperm( const M& m_) : basic_op_m<M>(m_){}
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
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)
return m(r,c);
return this->m(r,c);
else
return 0;
}
};
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)
return m(r,c);
return this->m(r,c);
else if (r==c)
return s;
else
return 0;
}
};
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_upperm> upperm (
const matrix_op<op_upperm<EXP> > upperm (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<EXP,op_upperm> exp;
return exp(m.ref());
typedef op_upperm<EXP> op;
return matrix_op<op>(op(m.ref()));
}
template <
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,
typename EXP::type s
)
{
typedef matrix_scalar_binary_exp<EXP, typename EXP::type ,op_upperm> exp;
return exp(m.ref(),s);
typedef op_upperm_s<EXP> op;
return matrix_op<op>(op(m.ref(),s));
}
// ----------------------------------------------------------------------------------------
......@@ -2815,21 +2957,23 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_cart_prod
{
template <typename EXP1, typename EXP2>
struct op : has_destructive_aliasing
{
const static long cost = EXP1::cost+EXP2::cost+1;
typedef typename EXP1::type type;
typedef const typename EXP1::const_ret_type const_ret_type;
op_cart_prod(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {}
const M1& m1;
const M2& m2;
typedef typename EXP1::mem_manager_type mem_manager_type;
const static long NR = EXP1::NR+EXP2::NR;
const static long NC = EXP1::NC*EXP2::NC;
const static long cost = M1::cost+M2::cost+1;
typedef typename M1::type type;
typedef const typename M1::const_ret_type const_ret_type;
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
typedef typename M1::mem_manager_type mem_manager_type;
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())
return m1(r, c/m2.nc());
......@@ -2837,70 +2981,75 @@ namespace dlib
return m2(r-m1.nr(), c%m2.nc());
}
template <typename M1, typename M2>
static long nr (const M1& m1, const M2& m2) { return m1.nr() + m2.nr(); }
template <typename M1, typename M2>
static long nc (const M1& m1, const M2& m2) { return m1.nc() * m2.nc(); }
};
long nr () const { return m1.nr() + m2.nr(); }
long nc () const { 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 <
typename EXP1,
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<EXP2>& b
)
{
COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true));
typedef matrix_binary_exp<EXP1,EXP2,op_cart_prod> exp;
return exp(a.ref(),b.ref());
typedef op_cart_prod<EXP1,EXP2> op;
return matrix_op<op>(op(a.ref(),b.ref()));
}
// ----------------------------------------------------------------------------------------
template <typename M>
struct op_mat_to_vect
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = EXP::NC*EXP::NR;
op_mat_to_vect(const M& m_) : m(m_) {}
const M& m;
const static long cost = M::cost+1;
const static long NR = M::NC*M::NR;
const static long NC = 1;
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 r, long )
{ return m(r/m.nc(), r%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;
template <typename M>
static long nr (const M& m) { return m.size(); }
template <typename M>
static long nc (const M& m) { return 1; }
};
const_ret_type apply ( long r, long ) const { return m(r/m.nc(), r%m.nc()); }
long nr () const { return m.size(); }
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 <
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
)
{
typedef matrix_unary_exp<EXP,op_mat_to_vect> exp;
return exp(m.ref());
typedef op_mat_to_vect<EXP> op;
return matrix_op<op>(op(m.ref()));
}
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_join_rows
{
template <typename EXP1, typename EXP2>
struct op : public has_destructive_aliasing
{
op_join_rows(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {}
const M1& m1;
const M2& m2;
template <typename T, typename U, bool selection>
struct type_selector;
template <typename T, typename U>
......@@ -2910,19 +3059,19 @@ namespace dlib
// 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.
typedef typename EXP1::const_ret_type T1;
typedef typename EXP1::type T2;
typedef typename EXP2::const_ret_type T3;
typedef typename M1::const_ret_type T1;
typedef typename M1::type T2;
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;
const static long cost = EXP1::cost + EXP2::cost + 1;
const static long NR = tmax<EXP1::NR, EXP2::NR>::value;
const static long NC = (EXP1::NC*EXP2::NC != 0)? (EXP1::NC+EXP2::NC) : (0);
typedef typename EXP1::type type;
typedef typename EXP1::mem_manager_type mem_manager_type;
const static long cost = M1::cost + M2::cost + 1;
const static long NR = tmax<M1::NR, M2::NR>::value;
const static long NC = (M1::NC*M2::NC != 0)? (M1::NC+M2::NC) : (0);
typedef typename M1::type type;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
const_ret_type apply (long r, long c) const
{
if (c < m1.nc())
return m1(r,c);
......@@ -2930,18 +3079,20 @@ namespace dlib
return m2(r,c-m1.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& m2 ) { return m1.nc()+m2.nc(); }
};
long nr () const { return m1.nr(); }
long nc () const { 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 <
typename EXP1,
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<EXP2>& b
)
......@@ -2958,17 +3109,19 @@ namespace dlib
<< "\n\tb.nr(): " << b.nr()
);
typedef matrix_binary_exp<EXP1,EXP2,op_join_rows> exp;
return exp(a.ref(),b.ref());
typedef op_join_rows<EXP1,EXP2> op;
return matrix_op<op>(op(a.ref(),b.ref()));
}
// ----------------------------------------------------------------------------------------
template <typename M1, typename M2>
struct op_join_cols
{
template <typename EXP1, typename EXP2>
struct op : public has_destructive_aliasing
{
op_join_cols(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {}
const M1& m1;
const M2& m2;
template <typename T, typename U, bool selection>
struct type_selector;
template <typename T, typename U>
......@@ -2978,21 +3131,21 @@ namespace dlib
// 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.
typedef typename EXP1::const_ret_type T1;
typedef typename EXP1::type T2;
typedef typename EXP2::const_ret_type T3;
typedef typename M1::const_ret_type T1;
typedef typename M1::type T2;
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;
const static long cost = EXP1::cost + EXP2::cost + 1;
const static long NC = tmax<EXP1::NC, EXP2::NC>::value;
const static long NR = (EXP1::NR*EXP2::NR != 0)? (EXP1::NR+EXP2::NR) : (0);
typedef typename EXP1::type type;
typedef typename EXP1::mem_manager_type mem_manager_type;
const static long cost = M1::cost + M2::cost + 1;
const static long NC = tmax<M1::NC, M2::NC>::value;
const static long NR = (M1::NR*M2::NR != 0)? (M1::NR+M2::NR) : (0);
typedef typename M1::type type;
typedef typename M1::mem_manager_type mem_manager_type;
typedef typename M1::layout_type layout_type;
template <typename M1, typename M2>
static const_ret_type apply ( const M1& m1, const M2& m2 , long r, long c)
const_ret_type apply ( long r, long c) const
{
if (r < m1.nr())
return m1(r,c);
......@@ -3000,18 +3153,20 @@ namespace dlib
return m2(r-m1.nr(),c);
}
template <typename M1, typename M2>
static long nr (const M1& m1, const M2& m2 ) { return m1.nr()+m2.nr(); }
template <typename M1, typename M2>
static long nc (const M1& m1, const M2& ) { return m1.nc(); }
};
long nr () const { return m1.nr()+m2.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.aliases(item) || m2.aliases(item); }
};
template <
typename EXP1,
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<EXP2>& b
)
......@@ -3028,8 +3183,8 @@ namespace dlib
<< "\n\tb.nc(): " << b.nc()
);
typedef matrix_binary_exp<EXP1,EXP2,op_join_cols> exp;
return exp(a.ref(),b.ref());
typedef op_join_cols<EXP1,EXP2> op;
return matrix_op<op>(op(a.ref(),b.ref()));
}
// ----------------------------------------------------------------------------------------
......
......@@ -15,516 +15,158 @@ namespace dlib
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template < typename kernel_type, typename alloc >
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> >
namespace impl
{
typedef typename kernel_type::sample_type sample_type;
public:
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
)
template <typename kernel_type, typename T>
inline const typename T::type& access ( const matrix_exp<T>& m, long i)
{
typedef kernel_matrix_exp<kernel_type,alloc> exp;
return exp(kern,m);
return m(i);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename kernel_type>
struct op_kern_mat
{
template <typename EXP>
struct op : has_destructive_aliasing
template <typename kernel_type, typename T, typename alloc>
inline const T& access ( const std::vector<T,alloc>& m, long i)
{
const static long NR = 0;
const static long NC = 0;
typedef typename EXP::mem_manager_type mem_manager_type;
return m[i];
}
const static long cost = EXP::cost+100;
typedef typename kernel_type::scalar_type type;
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)
template <typename kernel_type, typename T, typename alloc>
inline const T& access ( const std_vector_c<T,alloc>& m, long i)
{
return kern(m(r),m(c));
return m[i];
}
template <typename M>
static long nr (const M& m) { return m.size(); }
template <typename M>
static long nc (const M& m) { return m.size(); }
};
};
// ----------------------------------------------------------------------------------------
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
template <typename kernel_type>
inline const typename kernel_type::sample_type& access (
const typename kernel_type::sample_type& samp,
long
)
{
// make sure requires clause is not broken
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);
return samp;
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template < typename kernel_type, typename lhs_type >
class kernel_matrix_exp1;
// --------------------------------------------
template < typename kernel_type, typename lhs_type >
struct matrix_traits<kernel_matrix_exp1<kernel_type,lhs_type> >
template <typename kernel_type, typename T>
inline unsigned long size ( const matrix_exp<T>& m)
{
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 = 1;
const static long cost = 100;
};
return m.size();
}
template <
typename kernel_type,
typename lhs_type
>
class kernel_matrix_exp1 : public matrix_exp<kernel_matrix_exp1<kernel_type,lhs_type> >
template <typename kernel_type, typename T, typename alloc>
inline unsigned long size ( const std::vector<T,alloc>& m)
{
typedef typename kernel_type::sample_type sample_type;
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;
};
return m.size();
}
// ----------------------------------------------------------------------------------------
template <typename kernel_type, typename T, typename alloc>
inline unsigned long size ( const std_vector_c<T,alloc>& m)
{
return m.size();
}
template <
typename kernel_type,
typename alloc
>
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
template <typename kernel_type>
inline unsigned long size (
const typename kernel_type::sample_type&
)
{
typedef kernel_matrix_exp1<kernel_type,std::vector<typename kernel_type::sample_type,alloc> > exp;
return exp(kern,m,samp);
return 1;
}
// ----------------------------------------------------------------------------------------
// --------------------------------------------
template <
typename kernel_type,
typename EXP
>
const kernel_matrix_exp1<kernel_type,EXP> kernel_matrix (
const kernel_type& kern,
const matrix_exp<EXP>& m,
const typename kernel_type::sample_type& samp
)
template <typename T>
typename disable_if<is_matrix<T> >::type assert_is_vector(const T&)
{}
template <typename T>
void assert_is_vector(const matrix_exp<T>& v)
{
// make sure requires clause is not broken
DLIB_ASSERT(is_vector(m) == true,
"\tconst matrix_exp kernel_matrix(kernel,m, samp)"
<< "\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()
DLIB_ASSERT(is_vector(v) == true,
"\tconst matrix_exp kernel_matrix()"
<< "\n\t You have to supply this function with row or column vectors"
<< "\n\t v.nr(): " << v.nr()
<< "\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 <
typename kernel_type,
typename lhs_type
>
class kernel_matrix_exp2 : public matrix_exp<kernel_matrix_exp2<kernel_type,lhs_type> >
template <typename K, typename vect_type1, typename vect_type2>
struct op_kern_mat : does_not_alias
{
typedef typename kernel_type::sample_type sample_type;
public:
typedef typename matrix_traits<kernel_matrix_exp2>::type type;
typedef typename matrix_traits<kernel_matrix_exp2>::const_ret_type const_ret_type;
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_
op_kern_mat(
const K& kern_,
const vect_type1& vect1_,
const vect_type2& vect2_
) :
m(m_),
kern(kern_),
samp(samp_)
{}
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
)
vect1(vect1_),
vect2(vect2_)
{
typedef kernel_matrix_exp2<kernel_type,std::vector<typename kernel_type::sample_type,alloc> > exp;
return exp(kern,m,samp);
// make sure the requires clauses get checked eventually
impl::assert_is_vector(vect1);
impl::assert_is_vector(vect2);
}
// ----------------------------------------------------------------------------------------
template <
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);
}
const K& kern;
const vect_type1& vect1;
const vect_type2& vect2;
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
typedef typename K::scalar_type type;
template < typename kernel_type, typename lhs_type, typename rhs_type >
class kernel_matrix_exp3;
const static long cost = 100;
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 typename kernel_type::mem_manager_type mem_manager_type;
typedef typename K::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 lhs_type,
typename rhs_type
>
class kernel_matrix_exp3 : public matrix_exp<kernel_matrix_exp3<kernel_type,lhs_type,rhs_type> >
const_ret_type apply (long r, long c ) const
{
typedef typename kernel_type::sample_type sample_type;
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(); }
return kern(impl::access<K>(vect1,r), impl::access<K>(vect2,c));
}
const lhs_type& lhs;
const rhs_type& rhs;
const kernel_type& kern;
long nr () const { return impl::size<K>(vect1); }
long nc () const { return impl::size<K>(vect2); }
};
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
typename K,
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 kernel_type& kern,
const std::vector<typename kernel_type::sample_type,alloc>& lhs,
const std::vector<typename kernel_type::sample_type,alloc>& rhs
const matrix_op<op_kern_mat<K,V1,V2> > kernel_matrix (
const K& kern,
const V1& v1,
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;
return exp(kern,lhs,rhs);
typedef op_kern_mat<K,V1,V2> op;
return matrix_op<op>(op(kern,v1,v2));
}
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename EXP1,
typename EXP2
typename K,
typename V
>
const kernel_matrix_exp3<kernel_type,EXP1,EXP2> kernel_matrix (
const kernel_type& kern,
const matrix_exp<EXP1>& lhs,
const matrix_exp<EXP2>& rhs
const matrix_op<op_kern_mat<K,V,V> > kernel_matrix (
const K& kern,
const V& v
)
{
// make sure requires clause is not broken
DLIB_ASSERT(is_vector(lhs) == true && is_vector(rhs) == true,
"\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());
typedef op_kern_mat<K,V,V> op;
return matrix_op<op>(op(kern,v,v));
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SVm_KERNEL_MATRIX_
......@@ -11,205 +11,86 @@
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Symmetric Kernel Matrices
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
typename V
>
const matrix_exp kernel_matrix (
const kernel_type& kernel,
const std::vector<typename kernel_type::sample_type,alloc>& m
const V& v
);
/*!
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
- if (V is of type kernel_type::sample_type) then
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- R is a square matrix of m.size() rows by m.size() columns
- for all valid r and c:
- R(r,c) == kernel(m[r], m[c])
!*/
// ----------------------------------------------------------------------------------------
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
- R.size() == 1
- R(0,0) == kernel(v,v)
- else
- returns a matrix R such that:
- 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:
- R(r,c) == kernel(m(r), m(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)
- R(r,c) == kernel(v(r), v(c))
!*/
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
typename V1,
typename V2
>
const matrix_exp kernel_matrix (
const kernel_type& kern,
const typename kernel_type::sample_type& samp,
const std::vector<typename kernel_type::sample_type,alloc>& m
const kernel_type& kernel,
const V1& v1,
const V2& v2
);
/*!
requires
- 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
- if (V1 and V2 are of type kernel_type::sample_type) then
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- is_row_vector(R) == true
- R.size() == m.size()
- for all valid i:
- 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
- R.size() == 1
- R(0,0) == kernel(v1,v2)
- else if (V1 is of type kernel_type::sample_type) then
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- is_row_vector(R) == true
- R.size() == m.size()
- for all valid i:
- R(i) == kernel(samp, m(i))
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// 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
- R.nr() == 1
- R.nc() == v2.size()
- for all valid c:
- R(0,c) == kernel(v1, v2(c))
- else if (V2 is of type kernel_type::sample_type) then
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- R.nr() == lhs.size()
- R.nc() == rhs.size()
- for all valid r and c:
- R(r,c) == kernel(lhs[r], rhs[c])
!*/
// ----------------------------------------------------------------------------------------
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
- R.nr() == v1.size()
- R.nc() == 1
- for all valid r:
- R(r,0) == kernel(v1(r), v2)
- else
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- R.nr() == lhs.size()
- R.nc() == rhs.size()
- R.nr() == v1.size()
- R.nc() == v2.size()
- 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