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_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(sqrt,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(log,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(log10,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(exp,7)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(conj,1)
DLIB_DEFINE_FUNCTION_M(op_conj, conj, std::conj ,1);
DLIB_MATRIX_SIMPLE_STD_FUNCTION(ceil,7)
DLIB_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
)
{
return matrix_unary_exp<EXP,op_sigmoid>(m.ref());
}
// ----------------------------------------------------------------------------------------
struct op_round_zeros
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
template <typename type, typename S>
inline type round_zeros_eps (const type& val, const S& eps)
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M, typename T>
static const_ret_type apply ( const M& m, const T& eps, long r, long c)
{
const type temp = m(r,c);
if (temp >= eps || temp <= -eps)
return temp;
else
return 0;
}
};
};
// 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);
template <
typename EXP
>
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_round_zeros> round_zeros (
const matrix_exp<EXP>& m
)
{
// you can only round matrices that contain built in scalar types like double, long, float, etc.
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());
}
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);
}
// ----------------------------------------------------------------------------------------
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 round_zeros (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;
}
};
};
template <
typename EXP
>
const matrix_unary_exp<EXP,op_cubed> cubed (
const matrix_exp<EXP>& m
)
{
return matrix_unary_exp<EXP,op_cubed>(m.ref());
}
// ----------------------------------------------------------------------------------------
struct op_squared
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
// 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);
const type eps = 10*std::numeric_limits<type>::epsilon();
if (val >= eps || val <= -eps)
return val;
else
return 0;
}
template <typename type>
inline type squared (const type& val)
{
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;
}
};
};
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 val*val;
}
// ----------------------------------------------------------------------------------------
template <typename type>
type cubed (const type& val)
{
return val*val*val;
}
struct op_pow
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
template <typename type, typename S>
inline type pow1 (const type& val, const S& s)
{
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)); }
};
};
// 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
));
return std::pow(val,s);
}
template <typename type, typename S>
inline type pow2 (const S& s, const type& val)
{
// 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
));
return std::pow(s,val);
}
template <typename type>
inline type reciprocal (const type& val)
{
// you can only compute reciprocal 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 ||
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
));
if (val != static_cast<type>(0))
return static_cast<type>((type)1.0/val);
else
return 0;
}
template <typename type>
inline type reciprocal_max (const type& val)
{
// you can only compute reciprocal_max 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
));
if (val != static_cast<type>(0))
return static_cast<type>((type)1.0/val);
else
return std::numeric_limits<type>::max();
}
template <
typename EXP,
typename S
>
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_pow> pow (
const matrix_exp<EXP>& m,
const S& s
)
{
// you can only round matrices that contain floats, doubles or long doubles.
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_scalar_binary_exp<EXP,typename EXP::type,op_pow>(m.ref(),s);
}
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_pow2
template <typename M, typename enabled = void>
struct op_round : basic_op_m<M>
{
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))); }
};
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
{
return static_cast<type>(std::floor(this->m(r,c)+0.5));
}
};
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
)
template <typename M>
struct op_round<M,typename enable_if_c<std::numeric_limits<typename M::type>::is_integer>::type >
: basic_op_m<M>
{
// you can only round 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_scalar_binary_exp<EXP,typename EXP::type,op_pow2>(m.ref(),s);
}
// ----------------------------------------------------------------------------------------
op_round( const M& m_) : basic_op_m<M>(m_){}
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);
else
return 0;
}
};
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> reciprocal (
const matrix_op<op_round<EXP> > round (
const matrix_exp<EXP>& m
)
{
// 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<typename EXP::type,std::complex<float> >::value == true ||
is_same_type<typename EXP::type,std::complex<double> >::value == true ||
is_same_type<typename EXP::type,std::complex<long double> >::value == true
));
return matrix_unary_exp<EXP,op_reciprocal>(m.ref());
// 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_reciprocal_max
template <typename M>
struct op_normalize : basic_op_m<M>
{
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+6;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{
const type temp = m(r,c);
if (temp != static_cast<type>(0))
return static_cast<type>((type)1.0/temp);
else
return std::numeric_limits<type>::max();
}
};
};
typedef typename M::type type;
template <
typename EXP
>
const matrix_unary_exp<EXP,op_reciprocal_max> reciprocal_max (
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());
}
op_normalize( const M& m_, const type& s_) : basic_op_m<M>(m_), s(s_){}
// ----------------------------------------------------------------------------------------
const type s;
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)
{
return m(r,c)*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 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 M, typename return_type = typename M::type>
struct op_abs : basic_op_m<M>
{
template <typename EXP, typename enabled = void>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{
return static_cast<type>(std::floor(m(r,c)+0.5));
}
};
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 = 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);
}
};
op_abs( 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
{
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
)
template <typename M, typename T>
struct op_abs<M, std::complex<T> > : basic_op_m<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());
}
// ----------------------------------------------------------------------------------------
op_abs( const M& m_) : basic_op_m<M>(m_){}
struct op_abs
{
template <typename EXP, typename return_type = typename EXP::type>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
typedef const typename EXP::type const_ret_type;
template <typename M>
static const_ret_type apply ( const M& m, long r, long c)
{
return static_cast<type>(std::abs(m(r,c)));
}
};
template <typename EXP, typename T>
struct op<EXP, std::complex<T> > : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::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)
{
return static_cast<type>(std::abs(m(r,c)));
}
};
const static long cost = M::cost;
typedef T type;
typedef const T const_ret_type;
const_ret_type apply ( long r, long c) const
{
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 M>
struct op_complex_matrix : basic_op_m<M>
{
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)
{
return type(m(r,c));
}
};
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(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 M1, typename M2>
struct op_complex_matrix2 : basic_op_mm<M1,M2>
{
template <typename EXP1, typename EXP2>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP1,EXP2>
{
const static long cost = EXP1::cost+EXP2::cost+1;
typedef std::complex<typename EXP1::type> type;
typedef const std::complex<typename EXP1::type> const_ret_type;
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)); }
};
op_complex_matrix2( const M1& m1_, const M2& m2_) : basic_op_mm<M1,M2>(m1_,m2_){}
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 M>
struct op_norm : basic_op_m<M>
{
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)); }
};
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 M>
struct op_real : basic_op_m<M>
{
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)); }
};
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 M>
struct op_imag : basic_op_m<M>
{
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)); }
};
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()));
}
// ----------------------------------------------------------------------------------------
struct op_rowm
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); }
template <typename M>
static long nr (const M& ) { return 1; }
template <typename M>
static long nc (const M& m) { return m.nc(); }
};
op_rowm(const M& m_, const long& row_) : m(m_), row(row_) {}
const M& m;
const long row;
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));
}
// ----------------------------------------------------------------------------------------
struct op_rowm2
template <typename M>
struct op_rowm2
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::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); }
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; }
};
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 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 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));
}
// ----------------------------------------------------------------------------------------
struct op_rowm_range
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;
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); }
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(); }
};
op_rowm_range( const M1& m1_, const M2& rows_) : m1(m1_), rows(rows_) {}
const M1& m1;
const M2& rows;
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;
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()));
}
// ----------------------------------------------------------------------------------------
struct op_colm
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;
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); }
template <typename M>
static long nr (const M& m) { return m.nr(); }
template <typename M>
static long nc (const M& ) { return 1; }
};
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 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); }
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));
}
// ----------------------------------------------------------------------------------------
struct op_colm2
template <typename M>
struct op_colm2
{
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::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); }
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; }
};
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 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); }
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));
}
// ----------------------------------------------------------------------------------------
struct op_colm_range
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;
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)); }
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(); }
};
op_colm_range( const M1& m1_, const M2& cols_) : m1(m1_), cols(cols_) {}
const M1& m1;
const M2& cols;
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;
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()));
}
// ----------------------------------------------------------------------------------------
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -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
)
{
typedef kernel_matrix_exp<kernel_type,alloc> exp;
return exp(kern,m);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename kernel_type>
struct op_kern_mat
{
template <typename EXP>
struct op : has_destructive_aliasing
template <typename kernel_type, typename T>
inline const typename T::type& access ( const matrix_exp<T>& m, long i)
{
const static long NR = 0;
const static long NC = 0;
typedef typename EXP::mem_manager_type mem_manager_type;
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)
{
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 kernel_type, typename T, typename alloc>
inline const T& access ( const std::vector<T,alloc>& m, long i)
{
return m[i];
}
// ----------------------------------------------------------------------------------------
template <typename kernel_type, typename T, typename alloc>
inline const T& access ( const std_vector_c<T,alloc>& m, long i)
{
return m[i];
}
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()
);
{
return samp;
}
typedef matrix_scalar_binary_exp<EXP, kernel_type, op_kern_mat<kernel_type> > exp;
return exp(m.ref(),kernel);
}
// --------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename kernel_type, typename T>
inline unsigned long size ( const matrix_exp<T>& m)
{
return m.size();
}
template < typename kernel_type, typename lhs_type >
class kernel_matrix_exp1;
template <typename kernel_type, typename T, typename alloc>
inline unsigned long size ( const std::vector<T,alloc>& m)
{
return m.size();
}
template < typename kernel_type, typename lhs_type >
struct matrix_traits<kernel_matrix_exp1<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 = 0;
const static long NC = 1;
const static long cost = 100;
};
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 lhs_type
>
class kernel_matrix_exp1 : public matrix_exp<kernel_matrix_exp1<kernel_type,lhs_type> >
{
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;
template <typename kernel_type>
inline unsigned long size (
const typename kernel_type::sample_type&
)
{
return 1;
}
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_)
template <typename T>
typename disable_if<is_matrix<T> >::type assert_is_vector(const T&)
{}
const type operator() (
long r,
long
) const { return kern(vector_to_matrix(m)(r),samp); }
template <typename U>
bool aliases (
const matrix_exp<U>&
) const { return false; }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>&
) const { return false; }
long nr (
) const { return m.size(); }
long nc (
) const { return 1; }
const lhs_type& m;
const kernel_type& kern;
const sample_type& samp;
};
// ----------------------------------------------------------------------------------------
template <typename T>
void assert_is_vector(const matrix_exp<T>& v)
{
// make sure requires clause is not broken
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()
);
}
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
)
{
typedef kernel_matrix_exp1<kernel_type,std::vector<typename kernel_type::sample_type,alloc> > exp;
return exp(kern,m,samp);
}
// ----------------------------------------------------------------------------------------
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
)
{
// 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()
);
template <typename K, typename vect_type1, typename vect_type2>
struct op_kern_mat : does_not_alias
{
op_kern_mat(
const K& kern_,
const vect_type1& vect1_,
const vect_type2& vect2_
) :
kern(kern_),
vect1(vect1_),
vect2(vect2_)
{
// make sure the requires clauses get checked eventually
impl::assert_is_vector(vect1);
impl::assert_is_vector(vect2);
}
typedef kernel_matrix_exp1<kernel_type,EXP> exp;
return exp(kern,m.ref(),samp);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
const K& kern;
const vect_type1& vect1;
const vect_type2& vect2;
template < typename kernel_type, typename lhs_type >
class kernel_matrix_exp2;
typedef typename K::scalar_type type;
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> >
{
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_
) :
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
)
{
typedef kernel_matrix_exp2<kernel_type,std::vector<typename kernel_type::sample_type,alloc> > exp;
return exp(kern,m,samp);
}
// ----------------------------------------------------------------------------------------
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 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 >
class kernel_matrix_exp3;
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> >
{
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(); }
const_ret_type apply (long r, long c ) const
{
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
);
/*!
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
- 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
- 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))
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Column or Row Kernel Matrices
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
>
const matrix_exp kernel_matrix (
const kernel_type& kern,
const std::vector<typename kernel_type::sample_type,alloc>& m,
const typename kernel_type::sample_type& samp
);
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
ensures
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- is_col_vector(R) == true
- R.size() == m.size()
- for all valid i:
- R(i) == kernel(m[i], samp)
!*/
// ----------------------------------------------------------------------------------------
template <
typename kernel_type
>
const matrix_exp kernel_matrix (
const kernel_type& kern,
const matrix_exp& m,
const typename kernel_type::sample_type& samp
);
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
- is_vector(m) == true
- the elements of m must be the type of element the given kernel operates on.
(e.g. kernel(m(0), m(1)) should be a legal expression)
ensures
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- is_col_vector(R) == true
- R.size() == m.size()
- for all valid i:
- R(i) == kernel(m(i), samp)
!*/
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
>
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
);
/*!
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_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
const V& v
);
/*!
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)
- 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
- 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))
- if (V is of type kernel_type::sample_type) then
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- 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 v.size() rows by v.size() columns
- for all valid r and c:
- R(r,c) == kernel(v(r), v(c))
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Rectangular Kernel Matrices
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename kernel_type,
typename alloc
typename V1,
typename V2
>
const matrix_exp kernel_matrix (
const kernel_type& kern,
const std::vector<typename kernel_type::sample_type,alloc>& lhs,
const std::vector<typename kernel_type::sample_type,alloc>& rhs
);
/*!
requires
- kernel == a kernel function object as defined by the file dlib/svm/kernel_abstract.h
ensures
- returns a matrix R such that:
- 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
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
- 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)
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
- 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))
- if (V1 and V2 are of type kernel_type::sample_type) then
- returns a matrix R such that:
- R::type == kernel_type::scalar_type
- 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
- 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() == 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() == v1.size()
- R.nc() == v2.size()
- for all valid r and 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