Commit dd08cc4f authored by Davis King's avatar Davis King

Refactored a bunch of the matrix code into a cleaner form. I also added a

cost member to all the matrix expressions so that the complexity of an
expression can be measured and temporaries introduced when appropriate.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402732
parent 14121d95
......@@ -45,7 +45,7 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <typename T>
template <typename T, typename helper = void>
struct is_matrix : public default_is_kind_value
{
/*!
......@@ -54,6 +54,9 @@ namespace dlib
- else
- is_matrix<T>::value == false
!*/
// Don't set the helper to anything. Just let it be void.
ASSERT_ARE_SAME_TYPE(helper,void);
};
// ----------------------------------------------------------------------------------------
......
......@@ -29,72 +29,6 @@
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager,
typename layout
>
class matrix_ref
{
public:
typedef T type;
typedef matrix_ref ref_type;
typedef mem_manager mem_manager_type;
typedef layout layout_type;
const static long NR = num_rows;
const static long NC = num_cols;
matrix_ref (
const matrix<T,num_rows,num_cols,mem_manager,layout>& m_
) : m(m_) {}
matrix_ref (
const matrix_ref& i_
) : m(i_.m) {}
const T& operator() (
long r,
long c
) const { return m(r,c); }
long nr (
) const { return m.nr(); }
long nc (
) const { return m.nc(); }
long size (
) const { return m.size(); }
template <typename U, long iNR, long iNC, typename mm, typename l >
bool aliases (
const matrix<U,iNR,iNC,mm,l>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename mm, typename l>
bool destructively_aliases (
const matrix<U,iNR,iNC,mm,l>& item
) const { return false; }
bool aliases (
const matrix<T,num_rows,num_cols,mem_manager,layout>& item
) const { return (&m == &item); }
const matrix_ref ref(
) const { return *this; }
private:
// no assignment operator
matrix_ref& operator=(const matrix_ref&);
const matrix<T,num_rows,num_cols,mem_manager,layout>& m; // This is the item contained by this expression.
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
......@@ -102,48 +36,65 @@ 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 ref_type, long NR >
template < typename exp_type, long NR >
struct get_nr_helper
{
static inline long get(const ref_type&) { return NR; }
static inline long get(const exp_type&) { return NR; }
};
template < typename ref_type >
struct get_nr_helper<ref_type,0>
template < typename exp_type >
struct get_nr_helper<exp_type,0>
{
static inline long get(const ref_type& m) { return m.nr(); }
static inline long get(const exp_type& m) { return m.nr(); }
};
template < typename ref_type, long NC >
template < typename exp_type, long NC >
struct get_nc_helper
{
static inline long get(const ref_type&) { return NC; }
static inline long get(const exp_type&) { return NC; }
};
template < typename ref_type >
struct get_nc_helper<ref_type,0>
template < typename exp_type >
struct get_nc_helper<exp_type,0>
{
static inline long get(const ref_type& m) { return m.nc(); }
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::mem_manager_type mem_manager_type;
// TODO
//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;
};
// the matrix_exp for statically sized matrices
template <
typename EXP
>
class matrix_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 EXP::type type;
typedef typename EXP::ref_type ref_type;
typedef typename EXP::mem_manager_type mem_manager_type;
const static long NR = EXP::NR;
const static long NC = EXP::NC;
typedef matrix<type,NR,NC,mem_manager_type> matrix_type;
typedef typename matrix_traits<EXP>::type type;
typedef typename matrix_traits<EXP>::mem_manager_type mem_manager_type;
// TODO
//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;
matrix_exp (
const EXP& exp
) : ref_(exp.ref()) {}
typedef matrix<type,NR,NC,mem_manager_type> matrix_type;
typedef EXP exp_type;
inline const type operator() (
long r,
......@@ -193,10 +144,10 @@ namespace dlib
) const { return nr()*nc(); }
long nr (
) const { return get_nr_helper<ref_type,NR>::get(ref_); }
) const { return get_nr_helper<exp_type,NR>::get(ref_); }
long nc (
) const { return get_nc_helper<ref_type,NC>::get(ref_); }
) const { return get_nc_helper<exp_type,NC>::get(ref_); }
template <typename U, long iNR, long iNC, typename mm, typename l >
bool aliases (
......@@ -208,7 +159,7 @@ namespace dlib
const matrix<U,iNR,iNC,mm,l>& item
) const { return ref_.destructively_aliases(item); }
const ref_type& ref (
const exp_type& ref (
) const { return ref_; }
inline operator const type (
......@@ -226,32 +177,31 @@ namespace dlib
return ref_(0,0);
}
protected:
explicit matrix_exp (
const EXP& exp
) : ref_(exp) {}
matrix_exp(const matrix_exp& item) : ref_(item.ref_) {}
private:
matrix_exp& operator= (const matrix_exp&);
const ref_type ref_;
const exp_type& ref_;
};
// ----------------------------------------------------------------------------------------
// something is a matrix if it is convertible to a matrix_exp object
template <typename T>
struct is_matrix<matrix_exp<T> > { static const bool value = true; };
template <typename T, long NR, long NC, typename mm, typename l>
struct is_matrix<matrix_ref<T,NR,NC,mm,l> > { static const bool value = true; };
template <typename T, long NR, long NC, typename mm, typename l>
struct is_matrix<matrix<T,NR,NC,mm,l> > { static const bool value = true; };
template <typename T>
struct is_matrix<T&> { static const bool value = is_matrix<T>::value; };
template <typename T>
struct is_matrix<const T&> { static const bool value = is_matrix<T>::value; };
template <typename T>
struct is_matrix<const T> { static const bool value = is_matrix<T>::value; };
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
// dimension is provided as a compile time constant (if one is at all).
......@@ -264,9 +214,10 @@ namespace dlib
struct matrix_multiply_helper
{
typedef typename LHS::type type;
template <typename RHS_, typename LHS_>
inline const static type eval (
const RHS& rhs,
const LHS& lhs,
const RHS_& rhs,
const LHS_& lhs,
long r,
long c
)
......@@ -288,9 +239,10 @@ namespace dlib
struct matrix_multiply_helper <LHS,RHS,lhs_nc,0>
{
typedef typename LHS::type type;
template <typename RHS_, typename LHS_>
inline const static type eval (
const RHS& rhs,
const LHS& lhs,
const RHS_& rhs,
const LHS_& lhs,
long r,
long c
)
......@@ -304,33 +256,66 @@ namespace dlib
}
};
template <typename LHS, typename RHS>
class matrix_multiply_exp;
template <typename LHS, typename RHS>
struct matrix_traits<matrix_multiply_exp<LHS,RHS> >
{
typedef typename LHS::type type;
typedef typename LHS::mem_manager_type mem_manager_type;
const static long NR = LHS::NR;
const static long NC = RHS::NC;
const static bool lhs_is_costly = (LHS::cost > 4)&&(RHS::NC != 1);
const static bool rhs_is_costly = (RHS::cost > 4)&&(LHS::NR != 1);
// Note that if we decide that one of the matrices is too costly we will evaluate it
// into a temporary. Doing this resets its cost back to 1.
const static long lhs_cost = ((lhs_is_costly==true)? 1 : (LHS::cost));
const static long rhs_cost = ((rhs_is_costly==true)? 1 : (RHS::cost));
// The cost of evaluating an element of a matrix multiply is the cost of evaluating elements from
// RHS and LHS times the number of rows/columns in the RHS/LHS matrix. If we don't know the matrix
// dimensions then just assume it is really large.
const static long cost = (lhs_cost+rhs_cost)*
((tmax<LHS::NC,RHS::NR>::value!=0)? (tmax<LHS::NC,RHS::NR>::value):(10000));
};
template <typename T, bool is_ref> struct conditional_matrix_temp { typedef typename T::matrix_type type; };
template <typename T> struct conditional_matrix_temp<T,true> { typedef T& type; };
template <
typename LHS,
typename RHS,
unsigned long count = 0
typename RHS
>
class matrix_multiply_exp
class matrix_multiply_exp : public matrix_exp<matrix_multiply_exp<LHS,RHS> >
{
/*!
REQUIREMENTS ON LHS AND RHS
- they must be matrix_exp or matrix_ref objects (or
objects with a compatible interface).
- must be matrix_exp objects.
!*/
public:
typedef typename LHS::type type;
typedef matrix_multiply_exp ref_type;
typedef typename LHS::mem_manager_type mem_manager_type;
const static long NR = LHS::NR;
const static long NC = RHS::NC;
matrix_multiply_exp (
const matrix_multiply_exp& item
) : lhs(item.lhs), rhs(item.rhs) {}
typedef typename matrix_traits<matrix_multiply_exp>::type type;
typedef typename matrix_traits<matrix_multiply_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_multiply_exp>::NR;
const static long NC = matrix_traits<matrix_multiply_exp>::NC;
const static long cost = matrix_traits<matrix_multiply_exp>::cost;
const static bool lhs_is_costly = matrix_traits<matrix_multiply_exp>::lhs_is_costly;
const static bool rhs_is_costly = matrix_traits<matrix_multiply_exp>::rhs_is_costly;
typedef typename conditional_matrix_temp<const LHS,lhs_is_costly == false>::type LHS_ref_type;
typedef typename conditional_matrix_temp<const RHS,rhs_is_costly == false>::type RHS_ref_type;
inline matrix_multiply_exp (
const LHS& lhs_,
const RHS& rhs_
) :
matrix_exp<matrix_multiply_exp>(*this),
lhs(lhs_),
rhs(rhs_)
{
......@@ -360,6 +345,9 @@ namespace dlib
return matrix_multiply_helper<LHS,RHS>::eval(rhs,lhs,r,c);
}
inline const type operator() ( long i ) const
{ return matrix_exp<matrix_multiply_exp>::operator()(i); }
long nr (
) const { return lhs.nr(); }
......@@ -376,129 +364,62 @@ namespace dlib
const matrix<U,iNR,iNC,mm,l>& item
) const { return aliases(item); }
const ref_type& ref(
) const { return *this; }
const LHS lhs;
const RHS rhs;
LHS_ref_type lhs;
RHS_ref_type rhs;
};
template <
typename T,
long NR,
long NC,
typename EXP1,
typename EXP2,
typename MM,
typename L
>
inline const matrix_exp<matrix_multiply_exp<EXP1, matrix_multiply_exp<EXP2,typename matrix<T,NR,NC,MM,L>::ref_type >,0 > > operator* (
const matrix_exp<matrix_multiply_exp<EXP1,EXP2,1> >& m1,
const matrix<T,NR,NC,MM,L>& m2
)
{
// We are going to reorder the order of evaluation of the terms here. This way the
// multiplication will go faster.
typedef matrix_multiply_exp<EXP2,typename matrix<T,NR,NC,MM,L>::ref_type > exp_inner;
typedef matrix_multiply_exp<EXP1, exp_inner,0 > exp_outer;
return matrix_exp<exp_outer>(exp_outer(m1.ref().lhs,exp_inner(m1.ref().rhs,m2)));
}
template <
typename EXP1,
typename EXP2
>
inline const matrix_exp<matrix_multiply_exp<EXP1, EXP2 > > operator* (
template < typename EXP1, typename EXP2 >
inline const matrix_multiply_exp<EXP1, EXP2> operator* (
const matrix_exp<EXP1>& m1,
const matrix_exp<EXP2>& m2
)
{
typedef matrix_multiply_exp<EXP1, EXP2> exp;
return matrix_exp<exp>(exp(m1.ref(),m2.ref()));
return matrix_multiply_exp<EXP1, EXP2>(m1.ref(), m2.ref());
}
template <
typename T,
long NR,
long NC,
typename EXP,
typename MM,
typename L
>
inline const matrix_exp<matrix_multiply_exp<typename matrix<T,NR,NC,MM,L>::ref_type, matrix_exp<EXP> > > operator* (
const matrix<T,NR,NC,MM,L>& m1,
const matrix_exp<EXP>& m2
)
{
typedef matrix_multiply_exp<typename matrix<T,NR,NC,MM,L>::ref_type, matrix_exp<EXP> > exp;
return matrix_exp<exp>(exp(m1,m2));
}
// ----------------------------------------------------------------------------------------
template <
typename T,
long NR,
long NC,
typename EXP,
typename MM,
typename L
>
inline const matrix_exp<matrix_multiply_exp< matrix_exp<EXP>, typename matrix<T,NR,NC,MM,L>::ref_type, 1> > operator* (
const matrix_exp<EXP>& m1,
const matrix<T,NR,NC,MM,L>& m2
)
{
typedef matrix_multiply_exp< matrix_exp<EXP>, typename matrix<T,NR,NC,MM,L>::ref_type, 1 > exp;
return matrix_exp<exp>(exp(m1,m2));
}
template <typename LHS, typename RHS>
class matrix_add_exp;
template <
typename T,
long NR1,
long NC1,
long NR2,
long NC2,
typename MM1,
typename MM2,
typename L1,
typename L2
>
inline const matrix_exp<matrix_multiply_exp<typename matrix<T,NR1,NC1,MM1,L1>::ref_type,typename matrix<T,NR2,NC2,MM2,L2>::ref_type > > operator* (
const matrix<T,NR1,NC1,MM1,L1>& m1,
const matrix<T,NR2,NC2,MM2,L2>& m2
)
template <typename LHS, typename RHS>
struct matrix_traits<matrix_add_exp<LHS,RHS> >
{
typedef matrix_multiply_exp<typename matrix<T,NR1,NC1,MM1,L1>::ref_type, typename matrix<T,NR2,NC2,MM2,L2>::ref_type > exp;
return matrix_exp<exp>(exp(m1,m2));
}
// ----------------------------------------------------------------------------------------
typedef typename LHS::type type;
typedef typename LHS::mem_manager_type mem_manager_type;
const static long NR = (RHS::NR > LHS::NR) ? RHS::NR : LHS::NR;
const static long NC = (RHS::NC > LHS::NC) ? RHS::NC : LHS::NC;
const static long cost = LHS::cost+RHS::cost;
};
template <
typename LHS,
typename RHS
>
class matrix_add_expression
class matrix_add_exp : public matrix_exp<matrix_add_exp<LHS,RHS> >
{
/*!
REQUIREMENTS ON LHS AND RHS
- they must be matrix_exp or matrix_ref objects (or
objects with a compatible interface).
- must be matrix_exp objects.
!*/
public:
typedef typename LHS::type type;
typedef typename LHS::mem_manager_type mem_manager_type;
typedef matrix_add_expression ref_type;
const static long NR = (RHS::NR > LHS::NR) ? RHS::NR : LHS::NR;
const static long NC = (RHS::NC > LHS::NC) ? RHS::NC : LHS::NC;
matrix_add_expression (
const matrix_add_expression& item
) : lhs(item.lhs), rhs(item.rhs) {}
matrix_add_expression (
typedef typename matrix_traits<matrix_add_exp>::type type;
typedef typename matrix_traits<matrix_add_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_add_exp>::NR;
const static long NC = matrix_traits<matrix_add_exp>::NC;
const static long cost = matrix_traits<matrix_add_exp>::cost;
/*
matrix_add_exp (
const matrix_add_exp& item
) : matrix_exp<matrix_add_exp>(*this), lhs(item.lhs), rhs(item.rhs) {}
*/
matrix_add_exp (
const LHS& lhs_,
const RHS& rhs_
) :
matrix_exp<matrix_add_exp>(*this),
lhs(lhs_),
rhs(rhs_)
{
......@@ -526,6 +447,9 @@ namespace dlib
long c
) const { return lhs(r,c) + rhs(r,c); }
inline const type operator() ( long i ) const
{ return matrix_exp<matrix_add_exp>::operator()(i); }
template <typename U, long iNR, long iNC , typename mm, typename l>
bool aliases (
const matrix<U,iNR,iNC,mm,l>& item
......@@ -536,56 +460,65 @@ namespace dlib
const matrix<U,iNR,iNC,mm,l>& item
) const { return lhs.destructively_aliases(item) || rhs.destructively_aliases(item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return lhs.nr(); }
long nc (
) const { return lhs.nc(); }
const LHS lhs;
const RHS rhs;
const LHS& lhs;
const RHS& rhs;
};
template <
typename EXP1,
typename EXP2
>
inline const matrix_exp<matrix_add_expression<EXP1, EXP2 > > operator+ (
inline const matrix_add_exp<EXP1, EXP2> operator+ (
const matrix_exp<EXP1>& m1,
const matrix_exp<EXP2>& m2
)
{
typedef matrix_add_expression<EXP1, EXP2 > exp;
return matrix_exp<exp>(exp(m1.ref(),m2.ref()));
return matrix_add_exp<EXP1, EXP2>(m1.ref(),m2.ref());
}
// ----------------------------------------------------------------------------------------
template <typename LHS, typename RHS>
class matrix_subtract_exp;
template <typename LHS, typename RHS>
struct matrix_traits<matrix_subtract_exp<LHS,RHS> >
{
typedef typename LHS::type type;
typedef typename LHS::mem_manager_type mem_manager_type;
const static long NR = (RHS::NR > LHS::NR) ? RHS::NR : LHS::NR;
const static long NC = (RHS::NC > LHS::NC) ? RHS::NC : LHS::NC;
const static long cost = LHS::cost+RHS::cost;
};
template <
typename LHS,
typename RHS
>
class matrix_subtract_exp
class matrix_subtract_exp : public matrix_exp<matrix_subtract_exp<LHS,RHS> >
{
/*!
REQUIREMENTS ON LHS AND RHS
- they must be matrix_exp or matrix_ref objects (or
objects with a compatible interface).
- must be matrix_exp objects.
!*/
public:
typedef typename LHS::type type;
typedef typename LHS::mem_manager_type mem_manager_type;
typedef matrix_subtract_exp ref_type;
const static long NR = (RHS::NR > LHS::NR) ? RHS::NR : LHS::NR;
const static long NC = (RHS::NC > LHS::NC) ? RHS::NC : LHS::NC;
typedef typename matrix_traits<matrix_subtract_exp>::type type;
typedef typename matrix_traits<matrix_subtract_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_subtract_exp>::NR;
const static long NC = matrix_traits<matrix_subtract_exp>::NC;
const static long cost = matrix_traits<matrix_subtract_exp>::cost;
matrix_subtract_exp (
const LHS& lhs_,
const RHS& rhs_
) :
) : matrix_exp<matrix_subtract_exp>(*this),
lhs(lhs_),
rhs(rhs_)
{
......@@ -613,6 +546,9 @@ namespace dlib
long c
) const { return lhs(r,c) - rhs(r,c); }
inline const type operator() ( long i ) const
{ return matrix_exp<matrix_subtract_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename mm, typename l >
bool aliases (
const matrix<U,iNR,iNC, mm,l>& item
......@@ -623,59 +559,69 @@ namespace dlib
const matrix<U,iNR,iNC,mm,l>& item
) const { return lhs.destructively_aliases(item) || rhs.destructively_aliases(item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return lhs.nr(); }
long nc (
) const { return lhs.nc(); }
const LHS lhs;
const RHS rhs;
const LHS& lhs;
const RHS& rhs;
};
template <
typename EXP1,
typename EXP2
>
inline const matrix_exp<matrix_subtract_exp<EXP1, EXP2 > > operator- (
inline const matrix_subtract_exp<EXP1, EXP2> operator- (
const matrix_exp<EXP1>& m1,
const matrix_exp<EXP2>& m2
)
{
typedef matrix_subtract_exp<EXP1, EXP2 > exp;
return matrix_exp<exp>(exp(m1.ref(),m2.ref()));
return matrix_subtract_exp<EXP1, EXP2>(m1.ref(),m2.ref());
}
// ----------------------------------------------------------------------------------------
template <typename M, typename S>
class matrix_div_scal_exp;
template <typename M, typename S>
struct matrix_traits<matrix_div_scal_exp<M,S> >
{
typedef typename M::type type;
typedef typename M::mem_manager_type mem_manager_type;
const static long NR = M::NR;
const static long NC = M::NC;
const static long cost = M::cost+1;
};
template <
typename M,
typename S
>
class matrix_divscal_exp
class matrix_div_scal_exp : public matrix_exp<matrix_div_scal_exp<M,S> >
{
/*!
REQUIREMENTS ON M
- must be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
- must be a matrix_exp object.
REQUIREMENTS ON S
- must be some kind of scalar type
- must be some kind of scalar type capable of dividing the elements
of a matrix of type M
!*/
public:
typedef typename M::type type;
typedef typename M::mem_manager_type mem_manager_type;
typedef matrix_divscal_exp ref_type;
const static long NR = M::NR;
const static long NC = M::NC;
typedef typename matrix_traits<matrix_div_scal_exp>::type type;
typedef typename matrix_traits<matrix_div_scal_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_div_scal_exp>::NR;
const static long NC = matrix_traits<matrix_div_scal_exp>::NC;
const static long cost = matrix_traits<matrix_div_scal_exp>::cost;
matrix_divscal_exp (
matrix_div_scal_exp (
const M& m_,
const S& s_
) :
matrix_exp<matrix_div_scal_exp>(*this),
m(m_),
s(s_)
{}
......@@ -685,6 +631,9 @@ namespace dlib
long c
) const { return m(r,c)/s; }
inline const type operator() ( long i ) const
{ return matrix_exp<matrix_div_scal_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename mm , typename l>
bool aliases (
const matrix<U,iNR,iNC,mm,l>& item
......@@ -695,16 +644,13 @@ namespace dlib
const matrix<U,iNR,iNC,mm,l>& item
) const { return m.destructively_aliases(item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return m.nr(); }
long nc (
) const { return m.nc(); }
const M m;
const M& m;
const S s;
};
......@@ -712,42 +658,54 @@ namespace dlib
typename EXP,
typename S
>
inline const matrix_exp<matrix_divscal_exp<matrix_exp<EXP>, S> > operator/ (
inline const matrix_div_scal_exp<EXP, S> operator/ (
const matrix_exp<EXP>& m,
const S& s
)
{
typedef matrix_divscal_exp<matrix_exp<EXP>,S > exp;
return matrix_exp<exp>(exp(m,s));
return matrix_div_scal_exp<EXP,S>(m.ref(),s);
}
// ----------------------------------------------------------------------------------------
template <typename M, typename S>
class matrix_mul_scal_exp;
template <typename M, typename S>
struct matrix_traits<matrix_mul_scal_exp<M,S> >
{
typedef typename M::type type;
typedef typename M::mem_manager_type mem_manager_type;
const static long NR = M::NR;
const static long NC = M::NC;
const static long cost = M::cost+1;
};
template <
typename M,
typename S
>
class matrix_mulscal_exp
class matrix_mul_scal_exp : public matrix_exp<matrix_mul_scal_exp<M,S> >
{
/*!
REQUIREMENTS ON M
- must be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
- must be a matrix_exp object.
REQUIREMENTS ON S
- must be some kind of scalar type
!*/
public:
typedef typename M::type type;
typedef typename M::mem_manager_type mem_manager_type;
typedef matrix_mulscal_exp ref_type;
const static long NR = M::NR;
const static long NC = M::NC;
typedef typename matrix_traits<matrix_mul_scal_exp>::type type;
typedef typename matrix_traits<matrix_mul_scal_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_mul_scal_exp>::NR;
const static long NC = matrix_traits<matrix_mul_scal_exp>::NC;
const static long cost = matrix_traits<matrix_mul_scal_exp>::cost;
matrix_mulscal_exp (
matrix_mul_scal_exp (
const M& m_,
const S& s_
) :
matrix_exp<matrix_mul_scal_exp>(*this),
m(m_),
s(s_)
{}
......@@ -757,6 +715,9 @@ namespace dlib
long c
) const { return m(r,c)*s; }
inline const type operator() ( long i ) const
{ return matrix_exp<matrix_mul_scal_exp>::operator()(i); }
template <typename U, long iNR, long iNC , typename mm, typename l>
bool aliases (
const matrix<U,iNR,iNC,mm,l>& item
......@@ -767,16 +728,13 @@ namespace dlib
const matrix<U,iNR,iNC,mm,l>& item
) const { return m.destructively_aliases(item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return m.nr(); }
long nc (
) const { return m.nc(); }
const M m;
const M& m;
const S s;
};
......@@ -784,73 +742,67 @@ namespace dlib
typename EXP,
typename S
>
inline const matrix_exp<matrix_mulscal_exp<matrix_exp<EXP>, S> > operator* (
inline typename disable_if<is_matrix<S>, const matrix_mul_scal_exp<EXP, S> >::type operator* (
const matrix_exp<EXP>& m,
const S& s
)
{
typedef matrix_mulscal_exp<matrix_exp<EXP>,S > exp;
return matrix_exp<exp>(exp(m,s));
return matrix_mul_scal_exp<EXP,S>(m.ref(),s);
}
template <
typename EXP,
typename S
>
inline const matrix_exp<matrix_mulscal_exp<matrix_exp<EXP>, S> > operator* (
inline typename disable_if<is_matrix<S>, const matrix_mul_scal_exp<EXP, S> >::type operator* (
const S& s,
const matrix_exp<EXP>& m
)
{
typedef matrix_mulscal_exp<matrix_exp<EXP>,S > exp;
return matrix_exp<exp>(exp(m,s));
return matrix_mul_scal_exp<EXP,S>(m.ref(),s);
}
template <
typename EXP
>
inline const matrix_exp<matrix_mulscal_exp<matrix_exp<EXP>, float> > operator/ (
inline const matrix_mul_scal_exp<EXP, float> operator/ (
const matrix_exp<EXP>& m,
const float& s
)
{
typedef matrix_mulscal_exp<matrix_exp<EXP>,float > exp;
return matrix_exp<exp>(exp(m,1.0f/s));
return matrix_mul_scal_exp<EXP,float>(m.ref(),1.0f/s);
}
template <
typename EXP
>
inline const matrix_exp<matrix_mulscal_exp<matrix_exp<EXP>, double> > operator/ (
inline const matrix_mul_scal_exp<EXP, double> operator/ (
const matrix_exp<EXP>& m,
const double& s
)
{
typedef matrix_mulscal_exp<matrix_exp<EXP>,double > exp;
return matrix_exp<exp>(exp(m,1.0/s));
return matrix_mul_scal_exp<EXP,double>(m.ref(),1.0/s);
}
template <
typename EXP
>
inline const matrix_exp<matrix_mulscal_exp<matrix_exp<EXP>, long double> > operator/ (
inline const matrix_mul_scal_exp<matrix_exp<EXP>, long double> operator/ (
const matrix_exp<EXP>& m,
const long double& s
)
{
typedef matrix_mulscal_exp<matrix_exp<EXP>,long double > exp;
return matrix_exp<exp>(exp(m,1.0/s));
return matrix_mul_scal_exp<EXP,long double>(m.ref(),1.0/s);
}
template <
typename EXP
>
inline const matrix_exp<matrix_mulscal_exp<matrix_exp<EXP>, int> > operator- (
inline const matrix_mul_scal_exp<EXP, int> operator- (
const matrix_exp<EXP>& m
)
{
typedef matrix_mulscal_exp<matrix_exp<EXP>,int > exp;
return matrix_exp<exp>(exp(m,-1));
return matrix_mul_scal_exp<EXP,int>(m.ref(),-1);
}
// ----------------------------------------------------------------------------------------
......@@ -899,26 +851,44 @@ namespace dlib
typename mem_manager,
typename layout
>
class matrix : public matrix_exp<matrix_ref<T,num_rows,num_cols, mem_manager,layout> >
struct matrix_traits<matrix<T,num_rows, num_cols, mem_manager, layout> >
{
COMPILE_TIME_ASSERT(num_rows >= 0 && num_cols >= 0);
public:
typedef T type;
typedef matrix_ref<T,num_rows,num_cols,mem_manager,layout> ref_type;
typedef mem_manager mem_manager_type;
typedef layout layout_type;
const static long NR = num_rows;
const static long NC = num_cols;
const static long cost = 1;
};
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager,
typename layout
>
class matrix : public matrix_exp<matrix<T,num_rows,num_cols, mem_manager,layout> >
{
COMPILE_TIME_ASSERT(num_rows >= 0 && num_cols >= 0);
matrix () : matrix_exp<matrix_ref<T,num_rows,num_cols, mem_manager, layout> >(ref_type(*this))
public:
typedef typename matrix_traits<matrix>::type type;
typedef typename matrix_traits<matrix>::mem_manager_type mem_manager_type;
typedef typename matrix_traits<matrix>::layout_type layout_type;
const static long NR = matrix_traits<matrix>::NR;
const static long NC = matrix_traits<matrix>::NC;
const static long cost = matrix_traits<matrix>::cost;
matrix () : matrix_exp<matrix>(*this)
{
}
explicit matrix (
long length
) : matrix_exp<matrix_ref<T,num_rows,num_cols, mem_manager, layout> >(ref_type(*this))
) : matrix_exp<matrix>(*this)
{
// This object you are trying to call matrix(length) on is not a column or
// row vector.
......@@ -963,7 +933,7 @@ namespace dlib
matrix (
long rows,
long cols
) : matrix_exp<matrix_ref<T,num_rows,num_cols, mem_manager, layout> >(ref_type(*this))
) : matrix_exp<matrix>(*this)
{
DLIB_ASSERT( (NR == 0 || NR == rows) && ( NC == 0 || NC == cols) &&
rows >= 0 && cols >= 0,
......@@ -980,8 +950,11 @@ namespace dlib
template <typename EXP>
matrix (
const matrix_exp<EXP>& m
): matrix_exp<matrix_ref<T,num_rows,num_cols, mem_manager, layout> >(ref_type(*this))
): matrix_exp<matrix>(*this)
{
using namespace std;
// TODO
//cout << "copy" << endl;
// You get an error on this line if the matrix m contains a type that isn't
// the same as the type contained in the target matrix.
COMPILE_TIME_ASSERT((is_same_type<typename EXP::type,type>::value == true) ||
......@@ -1008,8 +981,11 @@ namespace dlib
matrix (
const matrix& m
): matrix_exp<matrix_ref<T,num_rows,num_cols, mem_manager, layout> >(ref_type(*this))
): matrix_exp<matrix>(*this)
{
using namespace std;
// TODO
//cout << "copy" << endl;
data.set_size(m.nr(),m.nc());
matrix_assign(*this, m);
}
......@@ -1017,7 +993,7 @@ namespace dlib
template <typename U, size_t len>
matrix (
U (&array)[len]
): matrix_exp<matrix_ref<T,num_rows,num_cols, mem_manager, layout> >(ref_type(*this))
): matrix_exp<matrix>(*this)
{
COMPILE_TIME_ASSERT(NR*NC == len && len > 0);
size_t idx = 0;
......@@ -1399,6 +1375,20 @@ namespace dlib
data.swap(item.data);
}
template <typename U, long iNR, long iNC, typename mm, typename l >
bool aliases (
const matrix<U,iNR,iNC,mm,l>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename mm, typename l>
bool destructively_aliases (
const matrix<U,iNR,iNC,mm,l>& item
) const { return false; }
bool aliases (
const matrix& item
) const { return (this == &item); }
private:
struct literal_assign_helper
{
......
......@@ -167,6 +167,7 @@ namespace dlib
const static long NR = EXP::NR;
const static long NC = EXP::NC;
typedef matrix<type,NR,NC, mem_manager_type> matrix_type;
const static long cost = EXP::cost;
matrix_exp (
const EXP& exp
......
......@@ -50,6 +50,9 @@ namespace dlib
// ----------------------------------------------------------------------------------------
// TODO
#if 0
template <
typename matrix_dest_type,
typename EXP1,
......@@ -117,6 +120,7 @@ namespace dlib
// ----------------------------------------------------------------------------------------
#endif
}
......
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATRIx_EXPRESSIONS_H_
#define DLIB_MATRIx_EXPRESSIONS_H_
#include "matrix_fwd.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// 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::mem_manager_type mem_manager_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>::mem_manager_type mem_manager_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;
matrix_unary_exp (
const M& m_
) :
matrix_exp<matrix_unary_exp>(*this),
m(m_)
{}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m,r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<matrix_unary_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return OP::destructively_aliases(m,item); }
long nr (
) const { return OP::nr(m); }
long nc (
) const { return OP::nc(m); }
private:
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::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
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>::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;
matrix_scalar_binary_exp (
const M& m_,
const S& s_
) :
matrix_exp<matrix_scalar_binary_exp>(*this),
m(m_),
s(s_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m,s,r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<matrix_scalar_binary_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return OP::destructively_aliases(m,item); }
long nr (
) const { return OP::nr(m); }
long nc (
) const { return OP::nc(m); }
private:
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::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
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>::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;
matrix_scalar_ternary_exp (
const M& m_,
const S& s1_,
const S& s2_
) :
matrix_exp<matrix_scalar_ternary_exp>(*this),
m(m_),
s1(s1_),
s2(s2_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m,s1,s2,r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<matrix_scalar_ternary_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return OP::destructively_aliases(m,item); }
long nr (
) const { return OP::nr(m); }
long nc (
) const { return OP::nc(m); }
private:
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::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
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>::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;
matrix_binary_exp (
const M1& m1_,
const M2& m2_
) :
matrix_exp<matrix_binary_exp>(*this),
m1(m1_),
m2(m2_)
{}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m1,m2,r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<matrix_binary_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m1.aliases(item) || m2.aliases(item); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& 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::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
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>::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;
matrix_ternary_exp (
const M1& m1_,
const M2& m2_,
const M3& m3_
) :
matrix_exp<matrix_ternary_exp>(*this),
m1(m1_),
m2(m2_),
m3(m3_)
{}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m1,m2,m3,r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<matrix_ternary_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& 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::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
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>::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;
matrix_fourary_exp (
const M1& m1_,
const M2& m2_,
const M3& m3_,
const M4& m4_
) :
matrix_exp<matrix_fourary_exp>(*this),
m1(m1_),
m2(m2_),
m3(m3_),
m4(m4_)
{}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m1,m2,m3,m4,r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<matrix_fourary_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) || m4.aliases(item); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& 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::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
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>::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;
dynamic_matrix_scalar_unary_exp (
long nr__,
long nc__,
const S& s_
) :
matrix_exp<dynamic_matrix_scalar_unary_exp>(*this),
nr_(nr__),
nc_(nc__),
s(s_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(s,r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<dynamic_matrix_scalar_unary_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) 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::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
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>::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;
matrix_scalar_unary_exp (
const S& s_
) :
matrix_exp<matrix_scalar_unary_exp>(*this),
s(s_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(s,r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<matrix_scalar_unary_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) 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::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const static long cost = OP::cost;
};
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>::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;
matrix_zeroary_exp (
) :
matrix_exp<matrix_zeroary_exp>(*this)
{}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(r,c); }
const typename OP::type operator() ( long i ) const
{ return matrix_exp<matrix_zeroary_exp>::operator()(i); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& 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::mem_manager_type mem_manager_type;
const static long NR = EXPr::NR*EXPr::NC;
const static long NC = EXPc::NR*EXPr::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>::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;
matrix_sub_range_exp (
const M& m_,
const EXPr& rows_,
const EXPc& cols_
) :
matrix_exp<matrix_sub_range_exp>(*this),
m(m_),
rows(rows_),
cols(cols_)
{
}
const typename M::type operator() (
long r,
long c
) const { return m(rows(r),cols(c)); }
const typename M::type operator() ( long i ) const
{ return matrix_exp<matrix_sub_range_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item) || rows.aliases(item) || cols.aliases(item); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& 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 typename memory_manager<char>::kernel_1a mem_manager_type;
const static long NR = 0;
const static long NC = 1;
const static long cost = 1;
};
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>::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;
matrix_std_vector_exp (
const M& m_
) :
matrix_exp<matrix_std_vector_exp>(*this),
m(m_)
{
}
const typename M::value_type operator() (
long r,
long
) const { return m[r]; }
const typename M::value_type operator() ( long i ) const
{ return m[i]; }
template <typename U, long iNR, long iNC, typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) 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 typename M::mem_manager_type mem_manager_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>::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;
matrix_array_exp (
const M& m_
) :
matrix_exp<matrix_array_exp>(*this),
m(m_)
{
}
const typename M::type operator() (
long r,
long
) const { return m[r]; }
const typename M::type operator() ( long i ) const
{ return m[i]; }
template <typename U, long iNR, long iNC, typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) 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 typename M::mem_manager_type mem_manager_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>::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;
matrix_array2d_exp (
const M& m_
) :
matrix_exp<matrix_array2d_exp>(*this),
m(m_)
{
}
const typename M::type operator() (
long r,
long c
) const { return m[r][c]; }
const typename M::type operator() ( long i ) const
{ return matrix_exp<matrix_array2d_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) 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::mem_manager_type mem_manager_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>::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;
matrix_sub_exp (
const M& m_,
const long& r__,
const long& c__,
const long& nr__,
const long& nc__
) :
matrix_exp<matrix_sub_exp>(*this),
m(m_),
r_(r__),
c_(c__),
nr_(nr__),
nc_(nc__)
{
}
const typename M::type operator() (
long r,
long c
) const { return m(r+r_,c+c_); }
const typename M::type operator() ( long i ) const
{ return matrix_exp<matrix_sub_exp>::operator()(i); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
long nr (
) const { return nr_; }
long nc (
) const { return nc_; }
private:
const M& m;
const long r_, c_, nr_, nc_;
};
// ----------------------------------------------------------------------------------------
class matrix_range_exp;
template <>
struct matrix_traits<matrix_range_exp>
{
typedef long type;
typedef memory_manager<char>::kernel_1a mem_manager_type;
const static long NR = 0;
const static long NC = 1;
const static long cost = 1;
};
class matrix_range_exp : public matrix_exp<matrix_range_exp>
{
public:
typedef matrix_traits<matrix_range_exp>::type type;
typedef matrix_traits<matrix_range_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_range_exp>::NR;
const static long NC = matrix_traits<matrix_range_exp>::NC;
const static long cost = matrix_traits<matrix_range_exp>::cost;
matrix_range_exp (
long start_,
long end_
) :
matrix_exp<matrix_range_exp>(*this)
{
start = start_;
if (start_ <= end_)
inc = 1;
else
inc = -1;
nr_ = std::abs(end_ - start_) + 1;
}
matrix_range_exp (
long start_,
long inc_,
long end_
) :
matrix_exp<matrix_range_exp>(*this)
{
start = start_;
nr_ = std::abs(end_ - start_)/inc_ + 1;
if (start_ <= end_)
inc = inc_;
else
inc = -inc_;
}
long operator() (
long r,
long c
) const { return start + r*inc; }
long operator() (
long r
) const { return start + r*inc; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
long nr (
) const { return nr_; }
long nc (
) const { return NC; }
long nr_;
long start;
long inc;
};
// ----------------------------------------------------------------------------------------
template <long start, long inc_, long end>
class matrix_range_static_exp;
template <long start, long inc_, long end>
struct matrix_traits<matrix_range_static_exp<start,inc_,end> >
{
typedef long type;
typedef memory_manager<char>::kernel_1a mem_manager_type;
const static long NR = tabs<(end - start)>::value/inc_ + 1;
const static long NC = 1;
const static long cost = 1;
};
template <long start, long inc_, long end>
class matrix_range_static_exp : public matrix_exp<matrix_range_static_exp<start,inc_,end> >
{
public:
typedef typename matrix_traits<matrix_range_static_exp>::type type;
typedef typename matrix_traits<matrix_range_static_exp>::mem_manager_type mem_manager_type;
const static long NR = matrix_traits<matrix_range_static_exp>::NR;
const static long NC = matrix_traits<matrix_range_static_exp>::NC;
const static long cost = matrix_traits<matrix_range_static_exp>::cost;
const static long inc = (start <= end)?inc_:-inc_;
matrix_range_static_exp (
) :
matrix_exp<matrix_range_static_exp>(*this)
{}
long operator() (
long r,
long c
) const { return start + r*inc; }
long operator() (
long r
) const { return start + r*inc; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
long nr (
) const { return NR; }
long nc (
) const { return NC; }
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_UTILITIES_
......@@ -17,45 +17,45 @@ namespace dlib
// ----------------------------------------------------------------------------------------
#define DLIB_MATRIX_SIMPLE_STD_FUNCTION(name) struct op_##name { \
#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; \
template <typename M> \
static type apply ( const M& m, long r, long c) \
{ return static_cast<type>(std::name(m(r,c))); } \
};}; \
template < typename EXP > \
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_##name> > name ( \
const matrix_unary_exp<EXP,op_##name> name ( \
const matrix_exp<EXP>& m) \
{ \
typedef matrix_unary_exp<matrix_exp<EXP>,op_##name> exp; \
return matrix_exp<exp>(exp(m)); \
return matrix_unary_exp<EXP,op_##name>(m.ref()); \
}
// ----------------------------------------------------------------------------------------
DLIB_MATRIX_SIMPLE_STD_FUNCTION(abs)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(sqrt)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(log)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(log10)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(exp)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(abs,3)
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)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(conj,1)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(ceil)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(floor)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(ceil,2)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(floor,20)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(sin)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(cos)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(tan)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(sinh)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(cosh)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(tanh)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(asin)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(acos)
DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
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)
// ----------------------------------------------------------------------------------------
......@@ -64,6 +64,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+7;
typedef typename EXP::type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -76,12 +77,11 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_sigmoid> > sigmoid (
const matrix_unary_exp<EXP,op_sigmoid> sigmoid (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_sigmoid> exp;
return matrix_exp<exp>(exp(m));
return matrix_unary_exp<EXP,op_sigmoid>(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -91,6 +91,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+1;
typedef typename EXP::type type;
template <typename M, typename T>
static type apply ( const M& m, const T& eps, long r, long c)
......@@ -107,28 +108,27 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_scalar_binary_exp<matrix_exp<EXP>,typename EXP::type,op_round_zeros> > round_zeros (
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<matrix_exp<EXP>,typename EXP::type, op_round_zeros> exp;
return matrix_exp<exp>(exp(m,10*std::numeric_limits<typename EXP::type>::epsilon()));
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_exp<matrix_scalar_binary_exp<matrix_exp<EXP>,typename EXP::type,op_round_zeros> > round_zeros (
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);
typedef matrix_scalar_binary_exp<matrix_exp<EXP>,typename EXP::type, op_round_zeros> exp;
return matrix_exp<exp>(exp(m,eps));
return matrix_scalar_binary_exp<EXP,typename EXP::type, op_round_zeros>(m.ref(),eps);
}
// ----------------------------------------------------------------------------------------
......@@ -138,6 +138,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+2;
typedef typename EXP::type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -151,12 +152,11 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_cubed> > cubed (
const matrix_unary_exp<EXP,op_cubed> cubed (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_cubed> exp;
return matrix_exp<exp>(exp(m));
return matrix_unary_exp<EXP,op_cubed>(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -166,6 +166,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+1;
typedef typename EXP::type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -179,12 +180,11 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_squared> > squared (
const matrix_unary_exp<EXP,op_squared> squared (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_squared> exp;
return matrix_exp<exp>(exp(m));
return matrix_unary_exp<EXP,op_squared>(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -194,6 +194,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+4;
typedef typename EXP::type type;
template <typename M, typename S>
static type apply ( const M& m, const S& s, long r, long c)
......@@ -205,7 +206,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
typename EXP,
typename S
>
const matrix_exp<matrix_scalar_binary_exp<matrix_exp<EXP>,typename EXP::type,op_pow> > pow (
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_pow> pow (
const matrix_exp<EXP>& m,
const S& s
)
......@@ -216,8 +217,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
is_same_type<typename EXP::type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true
));
typedef matrix_scalar_binary_exp<matrix_exp<EXP>,typename EXP::type,op_pow> exp;
return matrix_exp<exp>(exp(m,s));
return matrix_scalar_binary_exp<EXP,typename EXP::type,op_pow>(m.ref(),s);
}
// ----------------------------------------------------------------------------------------
......@@ -227,6 +227,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+2;
typedef typename EXP::type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -243,7 +244,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_reciprocal> > reciprocal (
const matrix_unary_exp<EXP,op_reciprocal> reciprocal (
const matrix_exp<EXP>& m
)
{
......@@ -253,8 +254,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
is_same_type<typename EXP::type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true
));
typedef matrix_unary_exp<matrix_exp<EXP>,op_reciprocal> exp;
return matrix_exp<exp>(exp(m));
return matrix_unary_exp<EXP,op_reciprocal>(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -264,6 +264,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+1;
typedef typename EXP::type type;
template <typename M>
static type apply ( const M& m, const type& s, long r, long c)
......@@ -276,7 +277,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_scalar_binary_exp<matrix_exp<EXP>,typename EXP::type,op_normalize> > normalize (
const matrix_scalar_binary_exp<EXP,typename EXP::type,op_normalize> normalize (
const matrix_exp<EXP>& m
)
{
......@@ -286,13 +287,13 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
is_same_type<typename EXP::type,double>::value == true ||
is_same_type<typename EXP::type,long double>::value == true
));
typedef matrix_scalar_binary_exp<matrix_exp<EXP>,typename EXP::type, op_normalize> exp;
typedef matrix_scalar_binary_exp<EXP,typename EXP::type, op_normalize> exp;
typename EXP::type temp = std::sqrt(sum(squared(m)));
if (temp != 0.0)
temp = 1.0/temp;
return matrix_exp<exp>(exp(m,temp));
return exp(m.ref(),temp);
}
// ----------------------------------------------------------------------------------------
......@@ -302,6 +303,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP, typename enabled = void>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+3;
typedef typename EXP::type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -314,6 +316,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
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;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -326,14 +329,14 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_round> > round (
const matrix_unary_exp<EXP,op_round> round (
const matrix_exp<EXP>& m
)
{
// you can only round matrices that contain built in scalar types like double, long, float, etc...
COMPILE_TIME_ASSERT(is_built_in_scalar_type<typename EXP::type>::value);
typedef matrix_unary_exp<matrix_exp<EXP>,op_round> exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_round> exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -343,6 +346,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
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;
template <typename M1, typename M2>
......@@ -355,7 +359,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
typename EXP1,
typename EXP2
>
const matrix_exp<matrix_binary_exp<matrix_exp<EXP1>,matrix_exp<EXP2>,op_complex_matrix> > complex_matrix (
const matrix_binary_exp<EXP1,EXP2,op_complex_matrix> complex_matrix (
const matrix_exp<EXP1>& real_part,
const matrix_exp<EXP2>& imag_part
)
......@@ -373,8 +377,8 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
<< "\n\timag_part.nr(): " << imag_part.nr()
<< "\n\timag_part.nc(): " << imag_part.nc()
);
typedef matrix_binary_exp<matrix_exp<EXP1>,matrix_exp<EXP2>,op_complex_matrix> exp;
return matrix_exp<exp>(exp(real_part,imag_part));
typedef matrix_binary_exp<EXP1,EXP2,op_complex_matrix> exp;
return exp(real_part.ref(),imag_part.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -384,6 +388,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost+2;
typedef typename EXP::type::value_type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -394,12 +399,12 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_norm> > norm (
const matrix_unary_exp<EXP,op_norm> norm (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_norm> exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_norm> exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -409,6 +414,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost;
typedef typename EXP::type::value_type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -419,12 +425,12 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_real> > real (
const matrix_unary_exp<EXP,op_real> real (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_real> exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_real> exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -434,6 +440,7 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost;
typedef typename EXP::type::value_type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -444,12 +451,12 @@ DLIB_MATRIX_SIMPLE_STD_FUNCTION(atan)
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_imag> > imag (
const matrix_unary_exp<EXP,op_imag> imag (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_imag> exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_imag> exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......
......@@ -14,6 +14,7 @@
#include <vector>
#include <algorithm>
#include "../std_allocator.h"
#include "matrix_expressions.h"
......@@ -97,6 +98,7 @@ namespace dlib
// ----------------------------------------------------------------------------------------
/* TODO remove this
template <
typename OP
>
......@@ -114,6 +116,7 @@ namespace dlib
typename OP
>
class matrix_binary_exp;
*/
struct has_destructive_aliasing
{
......@@ -129,6 +132,23 @@ namespace dlib
const M2& m2,
const matrix<U,iNR,iNC,MM,L>& item
) { return m1.aliases(item) || m2.aliases(item) ; }
template <typename M1, typename M2, typename M3, typename U, long iNR, long iNC, typename MM, typename L >
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const M3& m3,
const matrix<U,iNR,iNC,MM,L>& item
) { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item); }
template <typename M1, typename M2, typename M3, typename M4, typename U, long iNR, long iNC, typename MM, typename L >
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const M3& m3,
const M4& m4,
const matrix<U,iNR,iNC,MM,L>& item
) { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) || m4.aliases(item); }
};
struct has_nondestructive_aliasing
......@@ -145,6 +165,26 @@ namespace dlib
const M2& m2,
const matrix<U,iNR,iNC, MM, L>& item
) { return m1.destructively_aliases(item) || m2.destructively_aliases(item) ; }
template <typename M1, typename M2, typename M3, typename U, long iNR, long iNC, typename MM, typename L >
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const M3& m3,
const matrix<U,iNR,iNC, MM, L>& 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, long iNR, long iNC, typename MM, typename L >
static bool destructively_aliases (
const M1& m1,
const M2& m2,
const M3& m3,
const M4& m4,
const matrix<U,iNR,iNC, MM, L>& 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>
......@@ -163,6 +203,16 @@ namespace dlib
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(); }
};
// ----------------------------------------------------------------------------------------
......@@ -1180,773 +1230,32 @@ convergence:
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename OP
>
class matrix_zeroary_exp
{
public:
typedef typename OP::type type;
typedef matrix_zeroary_exp ref_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(r,c); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
long nr (
) const { return NR; }
long nc (
) const { return NC; }
const ref_type& ref(
) const { return *this; }
};
// ----------------------------------------------------------------------------------------
template <
typename S,
typename OP
>
class dynamic_matrix_scalar_unary_exp
{
/*!
REQUIREMENTS ON S
- must NOT be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
!*/
public:
typedef typename OP::type type;
typedef dynamic_matrix_scalar_unary_exp ref_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
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 typename OP::type operator() (
long r,
long c
) const { return OP::apply(s,r,c); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
const ref_type& ref(
) const { return *this; }
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
{
/*!
REQUIREMENTS ON S
- must NOT be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
!*/
public:
typedef typename OP::type type;
typedef matrix_scalar_unary_exp ref_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
matrix_scalar_unary_exp (
const S& s_
) :
s(s_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(s,r,c); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return NR; }
long nc (
) const { return NC; }
private:
const S s;
};
// ----------------------------------------------------------------------------------------
template <
typename M,
typename OP_
>
class matrix_unary_exp
{
/*!
REQUIREMENTS ON M
- must be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
!*/
typedef typename OP_::template op<M> OP;
public:
typedef typename OP::type type;
typedef matrix_unary_exp ref_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
matrix_unary_exp (
const M& m_
) :
m(m_)
{}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m,r,c); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return OP::destructively_aliases(m,item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return OP::nr(m); }
long nc (
) const { return OP::nc(m); }
private:
const M m;
};
// ----------------------------------------------------------------------------------------
template <
typename M
>
class matrix_std_vector_exp
{
/*!
REQUIREMENTS ON M
- must be a std::vector object (or
an object with a compatible interface).
!*/
public:
typedef typename M::value_type type;
typedef matrix_std_vector_exp ref_type;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
const static long NR = 0;
const static long NC = 1;
matrix_std_vector_exp (
const M& m_
) :
m(m_)
{
}
const typename M::value_type operator() (
long r,
long
) const { return m[r]; }
template <typename U, long iNR, long iNC, typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return m.size(); }
long nc (
) const { return 1; }
private:
const M& m;
};
// ----------------------------------------------------------------------------------------
template <
typename M
>
class matrix_vector_exp
{
/*!
REQUIREMENTS ON M
- must be a dlib::array object (or
an object with a compatible interface).
!*/
public:
typedef typename M::type type;
typedef matrix_vector_exp ref_type;
typedef typename M::mem_manager_type mem_manager_type;
const static long NR = 0;
const static long NC = 1;
matrix_vector_exp (
const M& m_
) :
m(m_)
{
}
const typename M::type operator() (
long r,
long
) const { return m[r]; }
template <typename U, long iNR, long iNC, typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return m.size(); }
long nc (
) const { return 1; }
private:
const M& m;
};
// ----------------------------------------------------------------------------------------
template <
typename M
>
class matrix_array_exp
{
/*!
REQUIREMENTS ON M
- must be a dlib::array2d object (or
an object with a compatible interface).
!*/
public:
typedef typename M::type type;
typedef matrix_array_exp ref_type;
typedef typename M::mem_manager_type mem_manager_type;
const static long NR = 0;
const static long NC = 0;
matrix_array_exp (
const M& m_
) :
m(m_)
{
}
const typename M::type operator() (
long r,
long c
) const { return m[r][c]; }
template <typename U, long iNR, long iNC, typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return m.nr(); }
long nc (
) const { return m.nc(); }
private:
const M& m;
};
// ----------------------------------------------------------------------------------------
template <
typename M
>
class matrix_sub_exp
{
/*!
REQUIREMENTS ON M
- must be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
!*/
public:
typedef typename M::type type;
typedef matrix_sub_exp ref_type;
typedef typename M::mem_manager_type mem_manager_type;
const static long NR = 0;
const static long NC = 0;
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 typename M::type operator() (
long r,
long c
) const { return m(r+r_,c+c_); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return nr_; }
long nc (
) const { return nc_; }
private:
const M m;
const long r_, c_, nr_, nc_;
};
// ----------------------------------------------------------------------------------------
template <
typename M,
typename S,
typename OP_
>
class matrix_scalar_binary_exp
{
/*!
REQUIREMENTS ON M
- must be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
!*/
typedef typename OP_::template op<M> OP;
public:
typedef typename OP::type type;
typedef matrix_scalar_binary_exp ref_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
matrix_scalar_binary_exp (
const M& m_,
const S& s_
) :
m(m_),
s(s_)
{
COMPILE_TIME_ASSERT(is_matrix<S>::value == false);
}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m,s,r,c); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return OP::destructively_aliases(m,item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return OP::nr(m); }
long nc (
) const { return OP::nc(m); }
private:
const M m;
const S s;
};
// ----------------------------------------------------------------------------------------
template <
typename M,
typename S,
typename OP_
>
class matrix_scalar_trinary_exp
{
/*!
REQUIREMENTS ON M
- must be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
!*/
typedef typename OP_::template op<M> OP;
public:
typedef typename OP::type type;
typedef matrix_scalar_trinary_exp ref_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
matrix_scalar_trinary_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 typename OP::type operator() (
long r,
long c
) const { return OP::apply(m,s1,s2,r,c); }
template <typename U, long iNR, long iNC, typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return OP::destructively_aliases(m,item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return OP::nr(m); }
long nc (
) const { return OP::nc(m); }
private:
const M m;
const S s1;
const S s2;
};
// ----------------------------------------------------------------------------------------
template <
typename M1,
typename M2,
typename OP_
>
class matrix_binary_exp
{
/*!
REQUIREMENTS ON M1 AND M2
- must be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
!*/
typedef typename OP_::template op<M1,M2> OP;
public:
typedef typename OP::type type;
typedef matrix_binary_exp ref_type;
typedef typename OP::mem_manager_type mem_manager_type;
const static long NR = OP::NR;
const static long NC = OP::NC;
matrix_binary_exp (
const M1& m1_,
const M2& m2_
) :
m1(m1_),
m2(m2_)
{}
const typename OP::type operator() (
long r,
long c
) const { return OP::apply(m1,m2,r,c); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m1.aliases(item) || m2.aliases(item); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return OP::destructively_aliases(m1,m2,item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return OP::nr(m1,m2); }
long nc (
) const { return OP::nc(m1,m2); }
private:
const M1 m1;
const M2 m2;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class matrix_range_exp
{
public:
typedef long type;
typedef matrix_range_exp ref_type;
typedef memory_manager<char>::kernel_1a mem_manager_type;
const static long NR = 0;
const static long NC = 1;
matrix_range_exp (
long start_,
long end_
)
{
start = start_;
if (start_ <= end_)
inc = 1;
else
inc = -1;
nr_ = std::abs(end_ - start_) + 1;
}
matrix_range_exp (
long start_,
long inc_,
long end_
)
{
start = start_;
nr_ = std::abs(end_ - start_)/inc_ + 1;
if (start_ <= end_)
inc = inc_;
else
inc = -inc_;
}
long operator() (
long r,
long c
) const { return start + r*inc; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
long nr (
) const { return nr_; }
long nc (
) const { return NC; }
const ref_type& ref(
) const { return *this; }
long nr_;
long start;
long inc;
};
// ----------------------------------------------------------------------------------------
template <long start, long inc_, long end>
class matrix_range_static_exp
{
public:
typedef long type;
typedef matrix_range_static_exp ref_type;
typedef memory_manager<char>::kernel_1a mem_manager_type;
const static long inc = (start <= end)?inc_:-inc_;
const static long NR = tabs<(end - start)>::value/inc_ + 1;
const static long NC = 1;
long operator() (
long r,
long c
) const { return start + r*inc; }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return false; }
long nr (
) const { return NR; }
long nc (
) const { return NC; }
const ref_type& ref(
) const { return *this; }
};
// ----------------------------------------------------------------------------------------
template <long start, long inc, long end>
const matrix_exp<matrix_range_static_exp<start,inc,end> > range (
const matrix_range_static_exp<start,inc,end> range (
)
{
COMPILE_TIME_ASSERT(inc > 0);
return matrix_exp<matrix_range_static_exp<start,inc,end> >(matrix_range_static_exp<start,inc,end>());
return matrix_range_static_exp<start,inc,end>();
}
template <long start, long end>
const matrix_exp<matrix_range_static_exp<start,1,end> > range (
const matrix_range_static_exp<start,1,end> range (
)
{
return matrix_exp<matrix_range_static_exp<start,1,end> >(matrix_range_static_exp<start,1,end>());
return matrix_range_static_exp<start,1,end>();
}
inline const matrix_exp<matrix_range_exp> range (
inline const matrix_range_exp range (
long start,
long end
)
{
return matrix_exp<matrix_range_exp>(matrix_range_exp(start,end));
return matrix_range_exp(start,end);
}
inline const matrix_exp<matrix_range_exp> range (
inline const matrix_range_exp range (
long start,
long inc,
long end
......@@ -1960,7 +1269,7 @@ convergence:
<< "\n\tend: " << end
);
return matrix_exp<matrix_range_exp>(matrix_range_exp(start,inc,end));
return matrix_range_exp(start,inc,end);
}
// ----------------------------------------------------------------------------------------
......@@ -1981,13 +1290,12 @@ convergence:
template <
typename array_type
>
const typename disable_if<is_matrix<array_type>,matrix_exp<matrix_array_exp<array_type> > >::type
const typename disable_if<is_matrix<array_type>,matrix_array2d_exp<array_type> >::type
array_to_matrix (
const array_type& array
)
{
typedef matrix_array_exp<array_type> exp;
return matrix_exp<exp>(exp(array));
return matrix_array2d_exp<array_type>(array);
}
// ----------------------------------------------------------------------------------------
......@@ -1995,13 +1303,13 @@ convergence:
template <
typename vector_type
>
const typename disable_if<is_matrix<vector_type>,matrix_exp<matrix_vector_exp<vector_type> > >::type
const typename disable_if<is_matrix<vector_type>,matrix_array_exp<vector_type> >::type
vector_to_matrix (
const vector_type& vector
)
{
typedef matrix_vector_exp<vector_type> exp;
return matrix_exp<exp>(exp(vector));
typedef matrix_array_exp<vector_type> exp;
return exp(vector);
}
// ----------------------------------------------------------------------------------------
......@@ -2012,6 +1320,10 @@ convergence:
const typename enable_if<is_matrix<vector_type>,vector_type>::type& vector_to_matrix (
const vector_type& vector
)
/*!
This overload catches the case where the argument to this function is
already a matrix.
!*/
{
return vector;
}
......@@ -2022,12 +1334,12 @@ convergence:
typename value_type,
typename alloc
>
const matrix_exp<matrix_std_vector_exp<std::vector<value_type,alloc> > > vector_to_matrix (
const matrix_std_vector_exp<std::vector<value_type,alloc> > vector_to_matrix (
const std::vector<value_type,alloc>& vector
)
{
typedef matrix_std_vector_exp<std::vector<value_type,alloc> > exp;
return matrix_exp<exp>(exp(vector));
return exp(vector);
}
// ----------------------------------------------------------------------------------------
......@@ -2036,12 +1348,12 @@ convergence:
typename value_type,
typename alloc
>
const matrix_exp<matrix_std_vector_exp<std_vector_c<value_type,alloc> > > vector_to_matrix (
const matrix_std_vector_exp<std_vector_c<value_type,alloc> > vector_to_matrix (
const std_vector_c<value_type,alloc>& vector
)
{
typedef matrix_std_vector_exp<std_vector_c<value_type,alloc> > exp;
return matrix_exp<exp>(exp(vector));
return exp(vector);
}
// ----------------------------------------------------------------------------------------
......@@ -2061,7 +1373,7 @@ convergence:
template <
typename EXP
>
const matrix_exp<matrix_sub_exp<matrix_exp<EXP> > > subm (
const matrix_sub_exp<EXP> subm (
const matrix_exp<EXP>& m,
long r,
long c,
......@@ -2080,8 +1392,8 @@ convergence:
<< "\n\tnc: " << nc
);
typedef matrix_sub_exp<matrix_exp<EXP> > exp;
return matrix_exp<exp>(exp(m,r,c,nr,nc));
typedef matrix_sub_exp<EXP> exp;
return exp(m.ref(),r,c,nr,nc);
}
// ----------------------------------------------------------------------------------------
......@@ -2089,7 +1401,7 @@ convergence:
template <
typename EXP
>
const matrix_exp<matrix_sub_exp<matrix_exp<EXP> > > subm (
const matrix_sub_exp<EXP> subm (
const matrix_exp<EXP>& m,
const rectangle& rect
)
......@@ -2105,80 +1417,18 @@ convergence:
<< "\n\trect.bottom(): " << rect.bottom()
);
typedef matrix_sub_exp<matrix_exp<EXP> > exp;
return matrix_exp<exp>(exp(m,rect.top(),rect.left(),rect.height(),rect.width()));
typedef matrix_sub_exp<EXP> exp;
return exp(m.ref(),rect.top(),rect.left(),rect.height(),rect.width());
}
// ----------------------------------------------------------------------------------------
template <
typename M,
typename EXPr,
typename EXPc
>
class matrix_sub_range_exp
{
/*!
REQUIREMENTS ON M, EXPr and EXPc
- must be a matrix_exp or matrix_ref object (or
an object with a compatible interface).
!*/
public:
typedef typename M::type type;
typedef matrix_sub_range_exp ref_type;
typedef typename M::mem_manager_type mem_manager_type;
const static long NR = EXPr::NR*EXPr::NC;
const static long NC = EXPc::NR*EXPr::NC;
matrix_sub_range_exp (
const M& m_,
const EXPr& rows_,
const EXPc& cols_
) :
m(m_),
rows(rows_),
cols(cols_)
{
}
const typename M::type operator() (
long r,
long c
) const { return m(rows(r),cols(c)); }
template <typename U, long iNR, long iNC, typename MM, typename L >
bool aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item) || rows.aliases(item) || cols.aliases(item); }
template <typename U, long iNR, long iNC , typename MM, typename L>
bool destructively_aliases (
const matrix<U,iNR,iNC,MM,L>& item
) const { return m.aliases(item) || rows.aliases(item) || cols.aliases(item); }
const ref_type& ref(
) const { return *this; }
long nr (
) const { return rows.size(); }
long nc (
) const { return cols.size(); }
private:
const M m;
const EXPr rows;
const EXPc cols;
};
template <
typename EXP,
typename EXPr,
typename EXPc
>
const matrix_exp<matrix_sub_range_exp<matrix_exp<EXP>,matrix_exp<EXPr>,matrix_exp<EXPc> > > subm (
const matrix_sub_range_exp<EXP,EXPr,EXPc> subm (
const matrix_exp<EXP>& m,
const matrix_exp<EXPr>& rows,
const matrix_exp<EXPc>& cols
......@@ -2204,8 +1454,8 @@ convergence:
<< "\n\tcols.nc(): " << cols.nc()
);
typedef matrix_sub_range_exp<matrix_exp<EXP>,matrix_exp<EXPr>,matrix_exp<EXPc> > exp;
return matrix_exp<exp>(exp(m,rows,cols));
typedef matrix_sub_range_exp<EXP,EXPr,EXPc> exp;
return exp(m.ref(),rows.ref(),cols.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -2215,6 +1465,7 @@ convergence:
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;
......@@ -2233,7 +1484,7 @@ convergence:
template <
typename EXP
>
const matrix_exp<matrix_scalar_binary_exp<matrix_exp<EXP>,long,op_rowm> > rowm (
const matrix_scalar_binary_exp<EXP,long,op_rowm> rowm (
const matrix_exp<EXP>& m,
long row
)
......@@ -2246,8 +1497,8 @@ convergence:
<< "\n\trow: " << row
);
typedef matrix_scalar_binary_exp<matrix_exp<EXP>,long,op_rowm> exp;
return matrix_exp<exp>(exp(m,row));
typedef matrix_scalar_binary_exp<EXP,long,op_rowm> exp;
return exp(m.ref(),row);
}
// ----------------------------------------------------------------------------------------
......@@ -2257,6 +1508,7 @@ convergence:
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::mem_manager_type mem_manager_type;
const static long NR = EXP2::NC*EXP2::NR;
......@@ -2277,7 +1529,7 @@ convergence:
typename EXP1,
typename EXP2
>
const matrix_exp<matrix_binary_exp<matrix_exp<EXP1>,matrix_exp<EXP2>,op_rowm_range> > rowm (
const matrix_binary_exp<EXP1,EXP2,op_rowm_range> rowm (
const matrix_exp<EXP1>& m,
const matrix_exp<EXP2>& rows
)
......@@ -2296,8 +1548,8 @@ convergence:
<< "\n\trows.nc(): " << rows.nc()
);
typedef matrix_binary_exp<matrix_exp<EXP1>,matrix_exp<EXP2>,op_rowm_range> exp;
return matrix_exp<exp>(exp(m,rows));
typedef matrix_binary_exp<EXP1,EXP2,op_rowm_range> exp;
return exp(m.ref(),rows.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -2307,6 +1559,7 @@ convergence:
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;
......@@ -2325,7 +1578,7 @@ convergence:
template <
typename EXP
>
const matrix_exp<matrix_scalar_binary_exp<matrix_exp<EXP>,long,op_colm> > colm (
const matrix_scalar_binary_exp<EXP,long,op_colm> colm (
const matrix_exp<EXP>& m,
long col
)
......@@ -2338,8 +1591,8 @@ convergence:
<< "\n\tcol: " << col
);
typedef matrix_scalar_binary_exp<matrix_exp<EXP>,long,op_colm> exp;
return matrix_exp<exp>(exp(m,col));
typedef matrix_scalar_binary_exp<EXP,long,op_colm> exp;
return exp(m.ref(),col);
}
// ----------------------------------------------------------------------------------------
......@@ -2353,6 +1606,7 @@ convergence:
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 type apply ( const M1& m1, const M2& cols , long r, long c)
......@@ -2369,7 +1623,7 @@ convergence:
typename EXP1,
typename EXP2
>
const matrix_exp<matrix_binary_exp<matrix_exp<EXP1>,matrix_exp<EXP2>,op_colm_range> > colm (
const matrix_binary_exp<EXP1,EXP2,op_colm_range> colm (
const matrix_exp<EXP1>& m,
const matrix_exp<EXP2>& cols
)
......@@ -2388,8 +1642,8 @@ convergence:
<< "\n\tcols.nc(): " << cols.nc()
);
typedef matrix_binary_exp<matrix_exp<EXP1>,matrix_exp<EXP2>,op_colm_range> exp;
return matrix_exp<exp>(exp(m,cols));
typedef matrix_binary_exp<EXP1,EXP2,op_colm_range> exp;
return exp(m.ref(),cols.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -2585,7 +1839,7 @@ convergence:
};
template <typename T, long NR, long NC, typename mm, typename l, typename EXPr, typename EXPc>
assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_exp<EXPr>,matrix_exp<EXPc> > set_subm (
assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,EXPc > set_subm (
matrix<T,NR,NC,mm,l>& m,
const matrix_exp<EXPr>& rows,
const matrix_exp<EXPc>& cols
......@@ -2607,13 +1861,13 @@ convergence:
<< "\n\tcols.nc(): " << cols.nc()
);
return assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_exp<EXPr>,matrix_exp<EXPc> >(m,rows,cols);
return assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,EXPc >(m,rows.ref(),cols.ref());
}
// ----------------------------------------------------------------------------------------
template <typename T, long NR, long NC, typename mm, typename l, typename EXPr>
assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_exp<EXPr>,matrix_exp<matrix_range_exp> > set_rowm (
assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,matrix_range_exp > set_rowm (
matrix<T,NR,NC,mm,l>& m,
const matrix_exp<EXPr>& rows
)
......@@ -2629,13 +1883,13 @@ convergence:
<< "\n\trows.nc(): " << rows.nc()
);
return assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_exp<EXPr>,matrix_exp<matrix_range_exp> >(m,rows,range(0,m.nc()-1));
return assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,matrix_range_exp >(m,rows.ref(),range(0,m.nc()-1));
}
// ----------------------------------------------------------------------------------------
template <typename T, long NR, long NC, typename mm, typename l, typename EXPc>
assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_exp<matrix_range_exp>,matrix_exp<EXPc> > set_colm (
assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_range_exp,EXPc > set_colm (
matrix<T,NR,NC,mm,l>& m,
const matrix_exp<EXPc>& cols
)
......@@ -2651,7 +1905,7 @@ convergence:
<< "\n\tcols.nc(): " << cols.nc()
);
return assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_exp<matrix_range_exp>,matrix_exp<EXPc> >(m,range(0,m.nr()-1),cols);
return assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_range_exp,EXPc >(m,range(0,m.nr()-1),cols.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -2836,6 +2090,7 @@ convergence:
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;
......@@ -2854,12 +2109,12 @@ convergence:
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_trans> > trans (
const matrix_unary_exp<EXP,op_trans> trans (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_trans> exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_trans> exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -2870,6 +2125,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+2;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1);
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1);
typedef typename EXP::type type;
......@@ -2905,6 +2161,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+2;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1);
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1);
typedef typename EXP::type type;
......@@ -2940,7 +2197,7 @@ convergence:
long C,
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_removerc<R,C> > > removerc (
const matrix_unary_exp<EXP,op_removerc<R,C> > removerc (
const matrix_exp<EXP>& m
)
{
......@@ -2956,14 +2213,14 @@ convergence:
<< "\n\tR: " << R
<< "\n\tC: " << C
);
typedef matrix_unary_exp<matrix_exp<EXP>,op_removerc<R,C> > exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_removerc<R,C> > exp;
return exp(m.ref());
}
template <
typename EXP
>
const matrix_exp<matrix_scalar_trinary_exp<matrix_exp<EXP>,long,op_removerc2> > removerc (
const matrix_scalar_ternary_exp<EXP,long,op_removerc2> removerc (
const matrix_exp<EXP>& m,
long R,
long C
......@@ -2977,8 +2234,8 @@ convergence:
<< "\n\tR: " << R
<< "\n\tC: " << C
);
typedef matrix_scalar_trinary_exp<matrix_exp<EXP>,long,op_removerc2 > exp;
return matrix_exp<exp>(exp(m,R,C));
typedef matrix_scalar_ternary_exp<EXP,long,op_removerc2 > exp;
return exp(m.ref(),R,C);
}
// ----------------------------------------------------------------------------------------
......@@ -2989,6 +2246,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = EXP::NR;
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1);
typedef typename EXP::type type;
......@@ -3018,6 +2276,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = EXP::NR;
const static long NC = (EXP::NC==0) ? 0 : (EXP::NC - 1);
typedef typename EXP::type type;
......@@ -3046,7 +2305,7 @@ convergence:
long C,
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_remove_col<C> > > remove_col (
const matrix_unary_exp<EXP,op_remove_col<C> > remove_col (
const matrix_exp<EXP>& m
)
{
......@@ -3060,14 +2319,14 @@ convergence:
<< "\n\tm.nc(): " << m.nc()
<< "\n\tC: " << C
);
typedef matrix_unary_exp<matrix_exp<EXP>,op_remove_col<C> > exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_remove_col<C> > exp;
return exp(m.ref());
}
template <
typename EXP
>
const matrix_exp<matrix_scalar_binary_exp<matrix_exp<EXP>,long,op_remove_col2 > > remove_col (
const matrix_scalar_binary_exp<EXP,long,op_remove_col2> remove_col (
const matrix_exp<EXP>& m,
long C
)
......@@ -3079,8 +2338,8 @@ convergence:
<< "\n\tm.nc(): " << m.nc()
<< "\n\tC: " << C
);
typedef matrix_scalar_binary_exp<matrix_exp<EXP>,long,op_remove_col2 > exp;
return matrix_exp<exp>(exp(m,C));
typedef matrix_scalar_binary_exp<EXP,long,op_remove_col2> exp;
return exp(m.ref(),C);
}
// ----------------------------------------------------------------------------------------
......@@ -3091,6 +2350,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1);
const static long NC = EXP::NC;
typedef typename EXP::type type;
......@@ -3120,6 +2380,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long NR = (EXP::NR==0) ? 0 : (EXP::NR - 1);
const static long NC = EXP::NC;
typedef typename EXP::type type;
......@@ -3148,7 +2409,7 @@ convergence:
long R,
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_remove_row<R> > > remove_row (
const matrix_unary_exp<EXP,op_remove_row<R> > remove_row (
const matrix_exp<EXP>& m
)
{
......@@ -3162,14 +2423,14 @@ convergence:
<< "\n\tm.nc(): " << m.nc()
<< "\n\tR: " << R
);
typedef matrix_unary_exp<matrix_exp<EXP>,op_remove_row<R> > exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_remove_row<R> > exp;
return exp(m.ref());
}
template <
typename EXP
>
const matrix_exp<matrix_scalar_binary_exp<matrix_exp<EXP>,long,op_remove_row2> > remove_row (
const matrix_scalar_binary_exp<EXP,long,op_remove_row2> remove_row (
const matrix_exp<EXP>& m,
long R
)
......@@ -3181,8 +2442,8 @@ convergence:
<< "\n\tm.nc(): " << m.nc()
<< "\n\tR: " << R
);
typedef matrix_scalar_binary_exp<matrix_exp<EXP>,long,op_remove_row2 > exp;
return matrix_exp<exp>(exp(m,R));
typedef matrix_scalar_binary_exp<EXP,long,op_remove_row2 > exp;
return exp(m.ref(),R);
}
// ----------------------------------------------------------------------------------------
......@@ -3192,6 +2453,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost+1;
const static long N = EXP::NC*EXP::NR;
const static long NR = N;
const static long NC = N;
......@@ -3216,7 +2478,7 @@ convergence:
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_diagm> > diagm (
const matrix_unary_exp<EXP,op_diagm> diagm (
const matrix_exp<EXP>& m
)
{
......@@ -3228,8 +2490,8 @@ convergence:
<< "\n\tm.nr(): " << m.nr()
<< "\n\tm.nc(): " << m.nc()
);
typedef matrix_unary_exp<matrix_exp<EXP>,op_diagm> exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_diagm> exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -3239,6 +2501,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing
{
const static long cost = EXP::cost;
const static long NR = (EXP::NC&&EXP::NR)? (tmin<EXP::NR,EXP::NC>::value) : (0);
const static long NC = 1;
typedef typename EXP::type type;
......@@ -3257,12 +2520,12 @@ convergence:
template <
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_diag> > diag (
const matrix_unary_exp<EXP,op_diag> diag (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_diag> exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_diag> exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -3273,6 +2536,7 @@ convergence:
template <typename EXP>
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost;
typedef target_type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -3284,12 +2548,12 @@ convergence:
typename target_type,
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_cast<target_type> > > matrix_cast (
const matrix_unary_exp<EXP,op_cast<target_type> > matrix_cast (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_cast<target_type> > exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_cast<target_type> > exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -4120,6 +3384,7 @@ convergence:
>
struct op_uniform_matrix_3 : has_nondestructive_aliasing
{
const static long cost = 1;
const static long NR = 0;
const static long NC = 0;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
......@@ -4131,7 +3396,7 @@ convergence:
template <
typename T
>
const matrix_exp<dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > > uniform_matrix (
const dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > uniform_matrix (
long nr,
long nc,
const T& val
......@@ -4144,7 +3409,7 @@ convergence:
<< "\n\tnc: " << nc
);
typedef dynamic_matrix_scalar_unary_exp<T,op_uniform_matrix_3<T> > exp;
return matrix_exp<exp>(exp(nr,nc,val));
return exp(nr,nc,val);
}
// ----------------------------------------------------------------------------------------
......@@ -4156,6 +3421,7 @@ convergence:
>
struct op_uniform_matrix_2 : has_nondestructive_aliasing
{
const static long cost = 1;
const static long NR = NR_;
const static long NC = NC_;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
......@@ -4169,14 +3435,14 @@ convergence:
long NR,
long NC
>
const matrix_exp<matrix_scalar_unary_exp<T,op_uniform_matrix_2<T,NR,NC> > > uniform_matrix (
const matrix_scalar_unary_exp<T,op_uniform_matrix_2<T,NR,NC> > uniform_matrix (
const T& val
)
{
COMPILE_TIME_ASSERT(NR > 0 && NC > 0);
typedef matrix_scalar_unary_exp<T,op_uniform_matrix_2<T,NR,NC> > exp;
return matrix_exp<exp>(exp(val));
return exp(val);
}
// ----------------------------------------------------------------------------------------
......@@ -4189,6 +3455,7 @@ convergence:
>
struct op_uniform_matrix : has_nondestructive_aliasing
{
const static long cost = 1;
const static long NR = NR_;
const static long NC = NC_;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
......@@ -4203,12 +3470,12 @@ convergence:
long NC,
T val
>
const matrix_exp<matrix_zeroary_exp<op_uniform_matrix<T,NR,NC,val> > > uniform_matrix (
const matrix_zeroary_exp<op_uniform_matrix<T,NR,NC,val> > uniform_matrix (
)
{
COMPILE_TIME_ASSERT(NR > 0 && NC > 0);
typedef matrix_zeroary_exp<op_uniform_matrix<T,NR,NC,val> > exp;
return matrix_exp<exp>(exp());
return exp();
}
// ----------------------------------------------------------------------------------------
......@@ -4218,6 +3485,7 @@ convergence:
>
struct op_identity_matrix_2 : has_nondestructive_aliasing
{
const static long cost = 1;
const static long NR = 0;
const static long NC = 0;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
......@@ -4229,7 +3497,7 @@ convergence:
template <
typename T
>
const matrix_exp<dynamic_matrix_scalar_unary_exp<T,op_identity_matrix_2<T> > > identity_matrix (
const dynamic_matrix_scalar_unary_exp<T,op_identity_matrix_2<T> > identity_matrix (
const long& size
)
{
......@@ -4241,7 +3509,7 @@ convergence:
typedef dynamic_matrix_scalar_unary_exp<T,op_identity_matrix_2<T> > exp;
// the scalar value of the dynamic_matrix_scalar_unary_exp just isn't
// used by this operator
return matrix_exp<exp>(exp(size,size,0));
return exp(size,size,0);
}
// ----------------------------------------------------------------------------------------
......@@ -4252,6 +3520,7 @@ convergence:
>
struct op_identity_matrix : has_nondestructive_aliasing
{
const static long cost = 1;
const static long NR = N;
const static long NC = N;
typedef typename memory_manager<char>::kernel_1a mem_manager_type;
......@@ -4269,13 +3538,13 @@ convergence:
typename T,
long N
>
const matrix_exp<matrix_zeroary_exp<op_identity_matrix<T,N> > > identity_matrix (
const matrix_zeroary_exp<op_identity_matrix<T,N> > identity_matrix (
)
{
COMPILE_TIME_ASSERT(N > 0);
typedef matrix_zeroary_exp<op_identity_matrix<T,N> > exp;
return matrix_exp<exp>(exp());
return exp();
}
// ----------------------------------------------------------------------------------------
......@@ -4286,6 +3555,7 @@ convergence:
template <typename EXP>
struct op : has_destructive_aliasing, preserves_dimensions<EXP>
{
const static long cost = EXP::cost + 1;
typedef typename EXP::type type;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -4298,7 +3568,7 @@ convergence:
long C,
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_rotate<R,C> > > rotate (
const matrix_unary_exp<EXP,op_rotate<R,C> > rotate (
const matrix_exp<EXP>& m
)
{
......@@ -4314,8 +3584,8 @@ convergence:
<< "\n\tR: " << R
<< "\n\tC: " << C
);
typedef matrix_unary_exp<matrix_exp<EXP>,op_rotate<R,C> > exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_rotate<R,C> > exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -4326,6 +3596,7 @@ convergence:
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2>
{
typedef typename EXP1::type type;
const static long cost = EXP1::cost + EXP2::cost + 1;
template <typename M1, typename M2>
static type apply ( const M1& m1, const M2& m2 , long r, long c)
......@@ -4337,7 +3608,7 @@ convergence:
typename EXP1,
typename EXP2
>
inline const matrix_exp<matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> > pointwise_multiply (
inline const matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> pointwise_multiply (
const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b
)
......@@ -4355,15 +3626,31 @@ convergence:
<< "\n\tb.nc(): " << b.nc()
);
typedef matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> exp;
return matrix_exp<exp>(exp(a.ref(),b.ref()));
return exp(a.ref(),b.ref());
}
// ----------------------------------------------------------------------------------------
struct op_pointwise_multiply3
{
template <typename EXP1, typename EXP2, typename EXP3>
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2,EXP3>
{
typedef typename EXP1::type type;
const static long cost = EXP1::cost + EXP2::cost + EXP3::cost + 2;
template <typename M1, typename M2, typename M3>
static type apply ( const M1& m1, const M2& m2, const M3& m3 , long r, long c)
{ return m1(r,c)*m2(r,c)*m3(r,c); }
};
};
template <
typename EXP1,
typename EXP2,
typename EXP3
>
inline const matrix_exp<matrix_binary_exp<matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply>,EXP3,op_pointwise_multiply> >
inline const matrix_ternary_exp<EXP1,EXP2,EXP3,op_pointwise_multiply3>
pointwise_multiply (
const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b,
......@@ -4371,6 +3658,7 @@ convergence:
)
{
COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true));
COMPILE_TIME_ASSERT((is_same_type<typename EXP2::type,typename EXP3::type>::value == true));
COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0);
COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NR == 0 || EXP2::NC == 0);
COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0);
......@@ -4388,23 +3676,34 @@ convergence:
<< "\n\tc.nr(): " << c.nr()
<< "\n\tc.nc(): " << c.nc()
);
typedef matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> exp;
typedef matrix_binary_exp<exp , EXP3, op_pointwise_multiply> exp2;
typedef matrix_ternary_exp<EXP1,EXP2,EXP3,op_pointwise_multiply3> exp;
return matrix_exp<exp2>(exp2(exp(a.ref(),b.ref()),c.ref()));
return exp(a.ref(),b.ref(),c.ref());
}
// ----------------------------------------------------------------------------------------
struct op_pointwise_multiply4
{
template <typename EXP1, typename EXP2, typename EXP3, typename EXP4>
struct op : public has_nondestructive_aliasing, public preserves_dimensions<EXP1,EXP2,EXP3,EXP4>
{
typedef typename EXP1::type type;
const static long cost = EXP1::cost + EXP2::cost + EXP3::cost + EXP4::cost + 3;
template <typename M1, typename M2, typename M3, typename M4>
static type apply ( const M1& m1, const M2& m2, const M3& m3, const M4& m4 , long r, long c)
{ return m1(r,c)*m2(r,c)*m3(r,c)*m4(r,c); }
};
};
template <
typename EXP1,
typename EXP2,
typename EXP3,
typename EXP4
>
inline const matrix_exp<
matrix_binary_exp<matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> ,
matrix_binary_exp<EXP3,EXP4,op_pointwise_multiply>,
op_pointwise_multiply> >
pointwise_multiply (
inline const matrix_fourary_exp<EXP1,EXP2,EXP3,EXP4,op_pointwise_multiply4> pointwise_multiply (
const matrix_exp<EXP1>& a,
const matrix_exp<EXP2>& b,
const matrix_exp<EXP3>& c,
......@@ -4412,6 +3711,8 @@ convergence:
)
{
COMPILE_TIME_ASSERT((is_same_type<typename EXP1::type,typename EXP2::type>::value == true));
COMPILE_TIME_ASSERT((is_same_type<typename EXP2::type,typename EXP3::type>::value == true));
COMPILE_TIME_ASSERT((is_same_type<typename EXP3::type,typename EXP4::type>::value == true));
COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0);
COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0 );
COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0);
......@@ -4435,11 +3736,9 @@ convergence:
<< "\n\td.nr(): " << d.nr()
<< "\n\td.nc(): " << d.nc()
);
typedef matrix_binary_exp<EXP1,EXP2,op_pointwise_multiply> exp1;
typedef matrix_binary_exp<EXP3,EXP4,op_pointwise_multiply> exp2;
typedef matrix_binary_exp< exp1 , exp2, op_pointwise_multiply> exp3;
return matrix_exp<exp3>(exp3(exp1(a.ref(),b.ref()),exp2(c.ref(),d.ref())));
typedef matrix_fourary_exp<EXP1,EXP2,EXP3,EXP4,op_pointwise_multiply4> exp;
return exp(a.ref(),b.ref(),c.ref(),d.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -4624,6 +3923,7 @@ convergence:
struct op : has_nondestructive_aliasing, preserves_dimensions<EXP>
{
typedef typename EXP::type type;
const static long cost = EXP::cost + 1;
template <typename M>
static type apply ( const M& m, long r, long c)
......@@ -4644,12 +3944,12 @@ convergence:
long u,
typename EXP
>
const matrix_exp<matrix_unary_exp<matrix_exp<EXP>,op_clamp<l,u> > > clamp (
const matrix_unary_exp<EXP,op_clamp<l,u> > clamp (
const matrix_exp<EXP>& m
)
{
typedef matrix_unary_exp<matrix_exp<EXP>,op_clamp<l,u> > exp;
return matrix_exp<exp>(exp(m));
typedef matrix_unary_exp<EXP,op_clamp<l,u> > exp;
return exp(m.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -4688,6 +3988,7 @@ convergence:
template <typename EXP1, typename EXP2>
struct op : has_nondestructive_aliasing
{
const static long cost = EXP1::cost + EXP2::cost + 1;
typedef typename EXP1::type type;
typedef typename EXP1::mem_manager_type mem_manager_type;
const static long NR = EXP1::NR;
......@@ -4708,7 +4009,7 @@ convergence:
typename EXP1,
typename EXP2
>
const matrix_exp<matrix_binary_exp<matrix_exp<EXP1>,matrix_exp<EXP2>,op_scale_columns> > scale_columns (
const matrix_binary_exp<EXP1,EXP2,op_scale_columns> scale_columns (
const matrix_exp<EXP1>& m,
const matrix_exp<EXP2>& v
)
......@@ -4725,8 +4026,8 @@ convergence:
<< "\n\tv.nr(): " << v.nr()
<< "\n\tv.nc(): " << v.nc()
);
typedef matrix_binary_exp<matrix_exp<EXP1>,matrix_exp<EXP2>,op_scale_columns> exp;
return matrix_exp<exp>(exp(m,v));
typedef matrix_binary_exp<EXP1,EXP2,op_scale_columns> exp;
return exp(m.ref(),v.ref());
}
// ----------------------------------------------------------------------------------------
......@@ -4842,6 +4143,7 @@ convergence:
template <typename EXP1, typename EXP2>
struct op : public has_destructive_aliasing
{
const static long cost = EXP1::cost + EXP2::cost + 1;
const static long NR = EXP1::NR*EXP2::NR;
const static long NC = EXP1::NC*EXP2::NC;
typedef typename EXP1::type type;
......
......@@ -300,7 +300,13 @@ namespace
DLIB_CASSERT((round(m2*m1) == identity_matrix<double,4>()),"");
DLIB_CASSERT((round(tmp(m2*m1)) == identity_matrix<double,4>()),"");
DLIB_CASSERT(round(m2*10000) == round(inv(m1)*10000),"");
DLIB_CASSERT(round(m2*10000) == round(inv(m1)*10000),
round(m2*10000) - round(inv(m1)*10000)
<< "\n\n" << round(m2*10000)
<< "\n\n" << round(inv(m1)*10000)
<< "\n\n" << m2
<< "\n\n" << inv(m1)
);
DLIB_CASSERT(m1 == abs(-1*m1),"");
DLIB_CASSERT(abs(m2) == abs(-1*m2),"");
......
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