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

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

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

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%403705
parent 31785ca3
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#ifndef DLIB_MATRIx_ #ifndef DLIB_MATRIx_
#define DLIB_MATRIx_ #define DLIB_MATRIx_
#include "matrix_fwd.h" #include "matrix_exp.h"
#include "matrix_abstract.h" #include "matrix_abstract.h"
#include "../algs.h" #include "../algs.h"
#include "../serialize.h" #include "../serialize.h"
...@@ -29,178 +29,6 @@ ...@@ -29,178 +29,6 @@
namespace dlib namespace dlib
{ {
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// We want to return the compile time constant if our NR and NC dimensions
// aren't zero but if they are then we want to call ref_.nx() and return
// the correct values.
template < typename exp_type, long NR >
struct get_nr_helper
{
static inline long get(const exp_type&) { return NR; }
};
template < typename exp_type >
struct get_nr_helper<exp_type,0>
{
static inline long get(const exp_type& m) { return m.nr(); }
};
template < typename exp_type, long NC >
struct get_nc_helper
{
static inline long get(const exp_type&) { return NC; }
};
template < typename exp_type >
struct get_nc_helper<exp_type,0>
{
static inline long get(const exp_type& m) { return m.nc(); }
};
template <typename EXP>
struct matrix_traits
{
typedef typename EXP::type type;
typedef typename EXP::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type;
typedef typename EXP::layout_type layout_type;
const static long NR = EXP::NR;
const static long NC = EXP::NC;
const static long cost = EXP::cost;
};
template <
typename EXP
>
class matrix_exp
{
/*!
REQUIREMENTS ON EXP
EXP should be something convertible to a matrix_exp. That is,
it should inherit from matrix_exp
!*/
public:
typedef typename matrix_traits<EXP>::type type;
typedef typename matrix_traits<EXP>::const_ret_type const_ret_type;
typedef typename matrix_traits<EXP>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<EXP>::layout_type layout_type;
const static long NR = matrix_traits<EXP>::NR;
const static long NC = matrix_traits<EXP>::NC;
const static long cost = matrix_traits<EXP>::cost;
typedef matrix<type,NR,NC,mem_manager_type,layout_type> matrix_type;
typedef EXP exp_type;
inline const_ret_type operator() (
long r,
long c
) const
{
DLIB_ASSERT(r < nr() && c < nc() && r >= 0 && c >= 0,
"\tconst type matrix_exp::operator(r,c)"
<< "\n\tYou must give a valid row and column"
<< "\n\tr: " << r
<< "\n\tc: " << c
<< "\n\tnr(): " << nr()
<< "\n\tnc(): " << nc()
<< "\n\tthis: " << this
);
return ref()(r,c);
}
const_ret_type operator() (
long i
) const
{
COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0);
DLIB_ASSERT(nc() == 1 || nr() == 1,
"\tconst type matrix_exp::operator(i)"
<< "\n\tYou can only use this operator on column or row vectors"
<< "\n\ti: " << i
<< "\n\tnr(): " << nr()
<< "\n\tnc(): " << nc()
<< "\n\tthis: " << this
);
DLIB_ASSERT( ((nc() == 1 && i < nr()) || (nr() == 1 && i < nc())) && i >= 0,
"\tconst type matrix_exp::operator(i)"
<< "\n\tYou must give a valid row/column number"
<< "\n\ti: " << i
<< "\n\tnr(): " << nr()
<< "\n\tnc(): " << nc()
<< "\n\tthis: " << this
);
if (nc() == 1)
return ref()(i,0);
else
return ref()(0,i);
}
long size (
) const { return nr()*nc(); }
long nr (
) const { return get_nr_helper<exp_type,NR>::get(ref()); }
long nc (
) const { return get_nc_helper<exp_type,NC>::get(ref()); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return ref().aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return ref().destructively_aliases(item); }
inline const exp_type& ref (
) const { return *static_cast<const exp_type*>(this); }
inline operator const type (
) const
{
COMPILE_TIME_ASSERT(NC == 1 || NC == 0);
COMPILE_TIME_ASSERT(NR == 1 || NR == 0);
DLIB_ASSERT(nr() == 1 && nc() == 1,
"\tmatrix_exp::operator const type() const"
<< "\n\tYou can only use this operator on a 1x1 matrix"
<< "\n\tnr(): " << nr()
<< "\n\tnc(): " << nc()
<< "\n\tthis: " << this
);
// Put the expression contained in this matrix_exp into
// a temporary 1x1 matrix so that the expression will encounter
// all the overloads of matrix_assign() and have the chance to
// go through any applicable optimizations.
matrix<type,1,1,mem_manager_type,layout_type> temp(ref());
return temp(0);
}
protected:
matrix_exp() {}
matrix_exp(const matrix_exp& ) {}
private:
matrix_exp& operator= (const matrix_exp&);
};
// ----------------------------------------------------------------------------------------
// something is a matrix if it is convertible to a matrix_exp object
template <typename T>
struct is_matrix<T, typename enable_if<is_convertible<T, const matrix_exp<typename T::exp_type>& > >::type >
{ static const bool value = true; };
/*
is_matrix<T>::value == 1 if T is a matrix type else 0
*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// This template will perform the needed loop for element multiplication using whichever // This template will perform the needed loop for element multiplication using whichever
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#undef DLIB_MATRIx_ABSTRACT_ #undef DLIB_MATRIx_ABSTRACT_
#ifdef DLIB_MATRIx_ABSTRACT_ #ifdef DLIB_MATRIx_ABSTRACT_
#include "matrix_exp_abstract.h"
#include "../serialize.h" #include "../serialize.h"
#include "../memory_manager.h" #include "../memory_manager.h"
#include "matrix_data_layout_abstract.h" #include "matrix_data_layout_abstract.h"
...@@ -10,186 +11,6 @@ ...@@ -10,186 +11,6 @@
namespace dlib namespace dlib
{ {
// ----------------------------------------------------------------------------------------
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager,
typename layout
>
class matrix;
// ----------------------------------------------------------------------------------------
template <
typename EXP
>
class matrix_exp
{
/*!
REQUIREMENTS ON EXP
- must be an object that inherits publicly from matrix_exp (this class).
WHAT THIS OBJECT REPRESENTS
This object represents an expression that evaluates to a matrix
of nr() rows and nc() columns.
The reason for having an object that represents an expression is that it
allows us to use the "expression templates" technique to eliminate the
temporary matrix objects that would normally be returned from expressions
such as M = A+B+C+D; Normally each invocation of the + operator would
construct and return a temporary matrix object but using this technique we
can avoid creating all of these temporary objects and receive a large
speed boost.
Note that every time you invoke operator() on this object it recomputes
its result which may not be what you want to do. For example, if you
are going to be accessing the same element over and over it might
be faster to assign the matrix_exp to a temporary matrix and then
use that temporary.
const_ret_type typedef (defined below)
The purpose of the const_ret_type typedef is to allow matrix expressions
to return their elements by reference when appropriate. So const_ret_type
should be one of the following types:
- const type
- const type&
!*/
public:
typedef typename EXP::type type;
typedef typename EXP::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type;
typedef typename EXP::layout_type layout_type;
const static long cost = EXP::cost;
const static long NR = EXP::NR;
const static long NC = EXP::NC;
typedef matrix<type,NR,NC, mem_manager_type,layout_type> matrix_type;
typedef EXP exp_type;
const_ret_type operator() (
long r,
long c
) const;
/*!
requires
- 0 <= r < nr()
- 0 <= c < nc()
ensures
- returns ref()(r,c)
(i.e. returns the value at the given row and column that would be in
the matrix represented by this matrix expression)
!*/
const_ret_type operator() (
long i
) const;
/*!
requires
- nc() == 1 || nr() == 1 (i.e. this must be a column or row vector)
- if (nc() == 1) then
- 0 <= i < nr()
- else
- 0 <= i < nc()
ensures
- if (nc() == 1) then
- returns (*this)(i,0)
- else
- returns (*this)(0,i)
!*/
operator const type (
) const;
/*!
requires
- nr() == 1
- nc() == 1
ensures
- returns (*this)(0,0)
!*/
long nr (
) const;
/*!
ensures
- returns the number of rows in this matrix expression.
!*/
long nc (
) const;
/*!
ensures
- returns the number of columns in this matrix expression.
!*/
long size (
) const;
/*!
ensures
- returns nr()*nc()
!*/
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const;
/*!
ensures
- if (A change to the state of item could cause a change to the state of *this
matrix_exp object. ) then
- returns true
- This happens when this matrix_exp contains item in some way.
- else
- returns false
!*/
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const;
/*!
ensures
- if (aliases(item)) then
- if (nr() != item.nr() || nc() != item.nc()
- returns true
(i.e. if this expression has different dimensions than item then
we have destructive aliasing)
- returns true if the following assignment would evaluate incorrectly:
for (long r = 0; r < nr(); ++r)
for (long c = 0; c < nc(); ++c)
item(r,c) = (*this)(r,c)
- That is, if this matrix expression aliases item in such a way that a modification
to element item(r,c) causes a change in the value of something other than
(*this)(r,c) then this function returns true.
- returns false if none of the above conditions say we should return true
- else
- returns false
!*/
inline const exp_type& ref (
) const;
/*!
ensures
- returns a reference to the expression contained in *this.
(i.e. returns *static_cast<const exp_type*>(this) )
!*/
protected:
// Only derived classes of matrix_exp may call the matrix_exp constructors.
matrix_exp(const matrix_exp&);
matrix_exp();
private:
// no one may ever use the assignment operator on a matrix_exp
matrix_exp& operator= (const matrix_exp&);
};
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
/* /*
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "../enable_if.h" #include "../enable_if.h"
#include "matrix_assign_fwd.h" #include "matrix_assign_fwd.h"
#include "matrix_default_mul.h" #include "matrix_default_mul.h"
#include "matrix_conj_trans.h"
namespace dlib namespace dlib
{ {
...@@ -70,8 +71,20 @@ namespace dlib ...@@ -70,8 +71,20 @@ namespace dlib
struct has_matrix_multiply<matrix_div_scal_exp<T> > struct has_matrix_multiply<matrix_div_scal_exp<T> >
{ const static bool value = has_matrix_multiply<T>::value; }; { const static bool value = has_matrix_multiply<T>::value; };
template <typename T, typename OP> template <typename T>
struct has_matrix_multiply<matrix_unary_exp<T,OP> > struct has_matrix_multiply<matrix_op<T> >
{ const static bool value = has_matrix_multiply<T>::value; };
template <typename T>
struct has_matrix_multiply<op_trans<T> >
{ const static bool value = has_matrix_multiply<T>::value; };
template <typename T>
struct has_matrix_multiply<op_conj_trans<T> >
{ const static bool value = has_matrix_multiply<T>::value; };
template <typename T>
struct has_matrix_multiply<op_conj<T> >
{ const static bool value = has_matrix_multiply<T>::value; }; { const static bool value = has_matrix_multiply<T>::value; };
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
...@@ -112,31 +125,31 @@ namespace dlib ...@@ -112,31 +125,31 @@ namespace dlib
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_scalar_binary_exp<matrix<T,NR,NC,MM,L>,long,op_colm> > struct matrix_type_id<matrix_op<op_colm<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = column_matrix; const static int value = column_matrix;
}; };
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_scalar_binary_exp<matrix<T,NR,NC,MM,L>,long,op_rowm> > struct matrix_type_id<matrix_op<op_rowm<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = row_matrix; const static int value = row_matrix;
}; };
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,L>,long,op_colm2> > struct matrix_type_id<matrix_op<op_colm2<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = column_matrix; const static int value = column_matrix;
}; };
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_scalar_ternary_exp<matrix<T,NR,NC,MM,L>,long,op_rowm2> > struct matrix_type_id<matrix_op<op_rowm2<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = row_matrix; const static int value = row_matrix;
}; };
template <typename T, long NR, long NC, typename MM, typename L> template <typename T, long NR, long NC, typename MM, typename L>
struct matrix_type_id<matrix_sub_exp<matrix<T,NR,NC,MM,L> > > struct matrix_type_id<matrix_op<op_subm<matrix<T,NR,NC,MM,L> > > >
{ {
const static int value = general_matrix; const static int value = general_matrix;
}; };
...@@ -215,8 +228,16 @@ namespace dlib ...@@ -215,8 +228,16 @@ namespace dlib
struct same_exp<matrix_div_scal_exp<T>, matrix_div_scal_exp<U>, layout > struct same_exp<matrix_div_scal_exp<T>, matrix_div_scal_exp<U>, layout >
{ const static bool value = same_exp<T,U,layout>::value; }; { const static bool value = same_exp<T,U,layout>::value; };
template <typename T, typename U, typename OP, typename layout> template <typename T, typename U, typename layout>
struct same_exp<matrix_unary_exp<T,OP>, matrix_unary_exp<U,OP>, layout > struct same_exp<matrix_op<op_trans<T> >, matrix_op<op_trans<U> >, layout >
{ const static bool value = same_exp<T,U,layout>::value; };
template <typename T, typename U, typename layout>
struct same_exp<matrix_op<op_conj<T> >, matrix_op<op_conj<U> >, layout >
{ const static bool value = same_exp<T,U,layout>::value; };
template <typename T, typename U, typename layout>
struct same_exp<matrix_op<op_conj_trans<T> >, matrix_op<op_conj_trans<U> >, layout >
{ const static bool value = same_exp<T,U,layout>::value; }; { const static bool value = same_exp<T,U,layout>::value; };
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
...@@ -410,7 +431,7 @@ namespace dlib ...@@ -410,7 +431,7 @@ namespace dlib
> >
void matrix_assign_blas_proxy ( void matrix_assign_blas_proxy (
dest_exp& dest, dest_exp& dest,
const matrix_unary_exp<src_exp,op_trans>& src, const matrix_op<op_trans<src_exp> >& src,
typename src_exp::type alpha, typename src_exp::type alpha,
bool add_to, bool add_to,
bool transpose bool transpose
...@@ -574,13 +595,13 @@ namespace dlib ...@@ -574,13 +595,13 @@ namespace dlib
> >
void matrix_assign_blas_proxy ( void matrix_assign_blas_proxy (
dest_exp& dest, dest_exp& dest,
const matrix_unary_exp<src_exp,op_trans>& src, const matrix_op<op_trans<src_exp> >& src,
typename src_exp::type alpha, typename src_exp::type alpha,
bool add_to, bool add_to,
bool transpose bool transpose
) )
{ {
matrix_assign_blas_proxy(dest, src.m, alpha, add_to, !transpose); matrix_assign_blas_proxy(dest, src.op.m, alpha, add_to, !transpose);
} }
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
......
This diff is collapsed.
...@@ -22,44 +22,44 @@ namespace dlib ...@@ -22,44 +22,44 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename M>
struct op_conj_trans struct op_conj_trans
{ {
template <typename EXP> op_conj_trans( const M& m_) : m(m_){}
struct op : has_destructive_aliasing const M& m;
{
const static long cost = EXP::cost;
const static long NR = EXP::NC;
const static long NC = EXP::NR;
typedef typename EXP::type type;
typedef typename EXP::type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type;
template <typename M>
static const const_ret_type apply ( const M& m, long r, long c)
{ return std::conj(m(c,r)); }
template <typename M> const static long cost = M::cost;
static long nr (const M& m) { return m.nc(); } const static long NR = M::NC;
template <typename M> const static long NC = M::NR;
static long nc (const M& m) { return m.nr(); } typedef typename M::type type;
}; typedef typename M::type const_ret_type;
typedef typename M::mem_manager_type mem_manager_type;
typedef typename M::layout_type layout_type;
const_ret_type apply (long r, long c) const { return std::conj(m(c,r)); }
long nr () const { return m.nc(); }
long nc () const { return m.nr(); }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); }
}; };
template <typename EXP> template <typename EXP>
const matrix_unary_exp<EXP,op_conj_trans> trans ( const matrix_op<op_conj_trans<EXP> > trans (
const matrix_unary_exp<EXP,op_conj>& m const matrix_op<op_conj<EXP> >& m
) )
{ {
typedef matrix_unary_exp<EXP,op_conj_trans> exp; typedef op_conj_trans<EXP> op;
return exp(m.m); return matrix_op<op>(op(m.op.m));
} }
template <typename EXP> template <typename EXP>
const matrix_unary_exp<EXP,op_conj_trans> conj ( const matrix_op<op_conj_trans<EXP> > conj (
const matrix_unary_exp<EXP,op_trans>& m const matrix_op<op_trans<EXP> >& m
) )
{ {
typedef matrix_unary_exp<EXP,op_conj_trans> exp; typedef op_conj_trans<EXP> op;
return exp(m.m); return matrix_op<op>(op(m.op.m));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATRIx_EXP_h_
#define DLIB_MATRIx_EXP_h_
#include "../algs.h"
#include "../is_kind.h"
#include "matrix_fwd.h"
#include "matrix_exp_abstract.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
// We want to return the compile time constant if our NR and NC dimensions
// aren't zero but if they are then we want to call ref_.nx() and return
// the correct values.
template < typename exp_type, long NR >
struct get_nr_helper
{
static inline long get(const exp_type&) { return NR; }
};
template < typename exp_type >
struct get_nr_helper<exp_type,0>
{
static inline long get(const exp_type& m) { return m.nr(); }
};
template < typename exp_type, long NC >
struct get_nc_helper
{
static inline long get(const exp_type&) { return NC; }
};
template < typename exp_type >
struct get_nc_helper<exp_type,0>
{
static inline long get(const exp_type& m) { return m.nc(); }
};
template <typename EXP>
struct matrix_traits
{
typedef typename EXP::type type;
typedef typename EXP::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type;
typedef typename EXP::layout_type layout_type;
const static long NR = EXP::NR;
const static long NC = EXP::NC;
const static long cost = EXP::cost;
};
// ----------------------------------------------------------------------------------------
template <
typename EXP
>
class matrix_exp
{
/*!
REQUIREMENTS ON EXP
EXP should be something convertible to a matrix_exp. That is,
it should inherit from matrix_exp
!*/
public:
typedef typename matrix_traits<EXP>::type type;
typedef typename matrix_traits<EXP>::const_ret_type const_ret_type;
typedef typename matrix_traits<EXP>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<EXP>::layout_type layout_type;
const static long NR = matrix_traits<EXP>::NR;
const static long NC = matrix_traits<EXP>::NC;
const static long cost = matrix_traits<EXP>::cost;
typedef matrix<type,NR,NC,mem_manager_type,layout_type> matrix_type;
typedef EXP exp_type;
inline const_ret_type operator() (
long r,
long c
) const
{
DLIB_ASSERT(r < nr() && c < nc() && r >= 0 && c >= 0,
"\tconst type matrix_exp::operator(r,c)"
<< "\n\tYou must give a valid row and column"
<< "\n\tr: " << r
<< "\n\tc: " << c
<< "\n\tnr(): " << nr()
<< "\n\tnc(): " << nc()
<< "\n\tthis: " << this
);
return ref()(r,c);
}
const_ret_type operator() (
long i
) const
{
COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0);
DLIB_ASSERT(nc() == 1 || nr() == 1,
"\tconst type matrix_exp::operator(i)"
<< "\n\tYou can only use this operator on column or row vectors"
<< "\n\ti: " << i
<< "\n\tnr(): " << nr()
<< "\n\tnc(): " << nc()
<< "\n\tthis: " << this
);
DLIB_ASSERT( ((nc() == 1 && i < nr()) || (nr() == 1 && i < nc())) && i >= 0,
"\tconst type matrix_exp::operator(i)"
<< "\n\tYou must give a valid row/column number"
<< "\n\ti: " << i
<< "\n\tnr(): " << nr()
<< "\n\tnc(): " << nc()
<< "\n\tthis: " << this
);
if (nc() == 1)
return ref()(i,0);
else
return ref()(0,i);
}
long size (
) const { return nr()*nc(); }
long nr (
) const { return get_nr_helper<exp_type,NR>::get(ref()); }
long nc (
) const { return get_nc_helper<exp_type,NC>::get(ref()); }
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const { return ref().aliases(item); }
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const { return ref().destructively_aliases(item); }
inline const exp_type& ref (
) const { return *static_cast<const exp_type*>(this); }
inline operator const type (
) const
{
COMPILE_TIME_ASSERT(NC == 1 || NC == 0);
COMPILE_TIME_ASSERT(NR == 1 || NR == 0);
DLIB_ASSERT(nr() == 1 && nc() == 1,
"\tmatrix_exp::operator const type() const"
<< "\n\tYou can only use this operator on a 1x1 matrix"
<< "\n\tnr(): " << nr()
<< "\n\tnc(): " << nc()
<< "\n\tthis: " << this
);
// Put the expression contained in this matrix_exp into
// a temporary 1x1 matrix so that the expression will encounter
// all the overloads of matrix_assign() and have the chance to
// go through any applicable optimizations.
matrix<type,1,1,mem_manager_type,layout_type> temp(ref());
return temp(0);
}
protected:
matrix_exp() {}
matrix_exp(const matrix_exp& ) {}
private:
matrix_exp& operator= (const matrix_exp&);
};
// ----------------------------------------------------------------------------------------
// something is a matrix if it is convertible to a matrix_exp object
template <typename T>
struct is_matrix<T, typename enable_if<is_convertible<T, const matrix_exp<typename T::exp_type>& > >::type >
{ static const bool value = true; };
/*
is_matrix<T>::value == 1 if T is a matrix type else 0
*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_EXP_h_
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MATRIx_EXP_ABSTRACT_
#ifdef DLIB_MATRIx_EXP_ABSTRACT_
#include "matrix_fwd.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename EXP
>
class matrix_exp
{
/*!
REQUIREMENTS ON EXP
- must be an object that inherits publicly from matrix_exp (this class).
WHAT THIS OBJECT REPRESENTS
This object represents an expression that evaluates to a matrix
of nr() rows and nc() columns.
The reason for having an object that represents an expression is that it
allows us to use the "expression templates" technique to eliminate the
temporary matrix objects that would normally be returned from expressions
such as M = A+B+C+D; Normally each invocation of the + operator would
construct and return a temporary matrix object but using this technique we
can avoid creating all of these temporary objects and receive a large
speed boost.
Note that every time you invoke operator() on this object it recomputes
its result which may not be what you want to do. For example, if you
are going to be accessing the same element over and over it might
be faster to assign the matrix_exp to a temporary matrix and then
use that temporary.
const_ret_type typedef (defined below)
The purpose of the const_ret_type typedef is to allow matrix expressions
to return their elements by reference when appropriate. So const_ret_type
should be one of the following types:
- const type
- const type&
!*/
public:
typedef typename EXP::type type;
typedef typename EXP::const_ret_type const_ret_type;
typedef typename EXP::mem_manager_type mem_manager_type;
typedef typename EXP::layout_type layout_type;
const static long cost = EXP::cost;
const static long NR = EXP::NR;
const static long NC = EXP::NC;
typedef matrix<type,NR,NC, mem_manager_type,layout_type> matrix_type;
typedef EXP exp_type;
const_ret_type operator() (
long r,
long c
) const;
/*!
requires
- 0 <= r < nr()
- 0 <= c < nc()
ensures
- returns ref()(r,c)
(i.e. returns the value at the given row and column that would be in
the matrix represented by this matrix expression)
!*/
const_ret_type operator() (
long i
) const;
/*!
requires
- nc() == 1 || nr() == 1 (i.e. this must be a column or row vector)
- if (nc() == 1) then
- 0 <= i < nr()
- else
- 0 <= i < nc()
ensures
- if (nc() == 1) then
- returns (*this)(i,0)
- else
- returns (*this)(0,i)
!*/
operator const type (
) const;
/*!
requires
- nr() == 1
- nc() == 1
ensures
- returns (*this)(0,0)
!*/
long nr (
) const;
/*!
ensures
- returns the number of rows in this matrix expression.
!*/
long nc (
) const;
/*!
ensures
- returns the number of columns in this matrix expression.
!*/
long size (
) const;
/*!
ensures
- returns nr()*nc()
!*/
template <typename U>
bool aliases (
const matrix_exp<U>& item
) const;
/*!
ensures
- if (A change to the state of item could cause a change to the state of *this
matrix_exp object. ) then
- returns true
- This happens when this matrix_exp contains item in some way.
- else
- returns false
!*/
template <typename U>
bool destructively_aliases (
const matrix_exp<U>& item
) const;
/*!
ensures
- if (aliases(item)) then
- if (nr() != item.nr() || nc() != item.nc()
- returns true
(i.e. if this expression has different dimensions than item then
we have destructive aliasing)
- returns true if the following assignment would evaluate incorrectly:
for (long r = 0; r < nr(); ++r)
for (long c = 0; c < nc(); ++c)
item(r,c) = (*this)(r,c)
- That is, if this matrix expression aliases item in such a way that a modification
to element item(r,c) causes a change in the value of something other than
(*this)(r,c) then this function returns true.
- returns false if none of the above conditions say we should return true
- else
- returns false
!*/
inline const exp_type& ref (
) const;
/*!
ensures
- returns a reference to the expression contained in *this.
(i.e. returns *static_cast<const exp_type*>(this) )
!*/
protected:
// Only derived classes of matrix_exp may call the matrix_exp constructors.
matrix_exp(const matrix_exp&);
matrix_exp();
private:
// no one may ever use the assignment operator on a matrix_exp
matrix_exp& operator= (const matrix_exp&);
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_EXP_ABSTRACT_
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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