276 lines
8.5 KiB
C++
276 lines
8.5 KiB
C++
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_MATRIx_EXP_h_
|
|
#define DLIB_MATRIx_EXP_h_
|
|
|
|
#include "../algs.h"
|
|
#include "../is_kind.h"
|
|
#include "matrix_fwd.h"
|
|
#include "matrix_exp_abstract.h"
|
|
#include <iterator>
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
// We want to return the compile time constant if our NR and NC dimensions
|
|
// aren't zero but if they are then we want to call ref_.nx() and return
|
|
// the correct values.
|
|
template < typename exp_type, long NR >
|
|
struct get_nr_helper
|
|
{
|
|
static inline long get(const exp_type&) { return NR; }
|
|
};
|
|
|
|
template < typename exp_type >
|
|
struct get_nr_helper<exp_type,0>
|
|
{
|
|
static inline long get(const exp_type& m) { return m.nr(); }
|
|
};
|
|
|
|
template < typename exp_type, long NC >
|
|
struct get_nc_helper
|
|
{
|
|
static inline long get(const exp_type&) { return NC; }
|
|
};
|
|
|
|
template < typename exp_type >
|
|
struct get_nc_helper<exp_type,0>
|
|
{
|
|
static inline long get(const exp_type& m) { return m.nc(); }
|
|
};
|
|
|
|
template <typename EXP>
|
|
struct matrix_traits
|
|
{
|
|
typedef typename EXP::type type;
|
|
typedef typename EXP::const_ret_type const_ret_type;
|
|
typedef typename EXP::mem_manager_type mem_manager_type;
|
|
typedef typename EXP::layout_type layout_type;
|
|
const static long NR = EXP::NR;
|
|
const static long NC = EXP::NC;
|
|
const static long cost = EXP::cost;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <typename EXP> class matrix_exp;
|
|
template <typename EXP>
|
|
class matrix_exp_iterator
|
|
{
|
|
friend class matrix_exp<EXP>;
|
|
matrix_exp_iterator(const EXP& m_, long r_, long c_)
|
|
{
|
|
r = r_;
|
|
c = c_;
|
|
nc = m_.nc();
|
|
m = &m_;
|
|
}
|
|
|
|
public:
|
|
|
|
matrix_exp_iterator() : r(0), c(0), nc(0), m(0) {}
|
|
|
|
using type = typename matrix_traits<EXP>::type;
|
|
using const_ret_type = typename matrix_traits<EXP>::const_ret_type;
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using value_type = type;
|
|
using difference_type = std::ptrdiff_t;
|
|
using pointer = value_type*;
|
|
using reference = value_type&;
|
|
|
|
|
|
bool operator == ( const matrix_exp_iterator& itr) const
|
|
{ return r == itr.r && c == itr.c; }
|
|
|
|
bool operator != ( const matrix_exp_iterator& itr) const
|
|
{ return !(*this == itr); }
|
|
|
|
matrix_exp_iterator& operator++()
|
|
{
|
|
++c;
|
|
if (c==nc)
|
|
{
|
|
c = 0;
|
|
++r;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
matrix_exp_iterator operator++(int)
|
|
{
|
|
matrix_exp_iterator temp(*this);
|
|
++(*this);
|
|
return temp;
|
|
}
|
|
|
|
const_ret_type operator* () const { return (*m)(r,c); }
|
|
|
|
private:
|
|
long r, c;
|
|
long nc;
|
|
const EXP* m;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename EXP
|
|
>
|
|
class matrix_exp
|
|
{
|
|
/*!
|
|
REQUIREMENTS ON EXP
|
|
EXP should be something convertible to a matrix_exp. That is,
|
|
it should inherit from matrix_exp
|
|
!*/
|
|
|
|
public:
|
|
typedef typename matrix_traits<EXP>::type type;
|
|
typedef type value_type;
|
|
typedef typename matrix_traits<EXP>::const_ret_type const_ret_type;
|
|
typedef typename matrix_traits<EXP>::mem_manager_type mem_manager_type;
|
|
typedef typename matrix_traits<EXP>::layout_type layout_type;
|
|
const static long NR = matrix_traits<EXP>::NR;
|
|
const static long NC = matrix_traits<EXP>::NC;
|
|
const static long cost = matrix_traits<EXP>::cost;
|
|
|
|
typedef matrix<type,NR,NC,mem_manager_type,layout_type> matrix_type;
|
|
typedef EXP exp_type;
|
|
typedef matrix_exp_iterator<EXP> iterator;
|
|
typedef matrix_exp_iterator<EXP> const_iterator;
|
|
|
|
inline const_ret_type operator() (
|
|
long r,
|
|
long c
|
|
) const
|
|
{
|
|
DLIB_ASSERT(r < nr() && c < nc() && r >= 0 && c >= 0,
|
|
"\tconst type matrix_exp::operator(r,c)"
|
|
<< "\n\tYou must give a valid row and column"
|
|
<< "\n\tr: " << r
|
|
<< "\n\tc: " << c
|
|
<< "\n\tnr(): " << nr()
|
|
<< "\n\tnc(): " << nc()
|
|
<< "\n\tthis: " << this
|
|
);
|
|
return ref()(r,c);
|
|
}
|
|
|
|
const_ret_type operator() (
|
|
long i
|
|
) const
|
|
{
|
|
COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0);
|
|
DLIB_ASSERT(nc() == 1 || nr() == 1,
|
|
"\tconst type matrix_exp::operator(i)"
|
|
<< "\n\tYou can only use this operator on column or row vectors"
|
|
<< "\n\ti: " << i
|
|
<< "\n\tnr(): " << nr()
|
|
<< "\n\tnc(): " << nc()
|
|
<< "\n\tthis: " << this
|
|
);
|
|
DLIB_ASSERT( ((nc() == 1 && i < nr()) || (nr() == 1 && i < nc())) && i >= 0,
|
|
"\tconst type matrix_exp::operator(i)"
|
|
<< "\n\tYou must give a valid row/column number"
|
|
<< "\n\ti: " << i
|
|
<< "\n\tnr(): " << nr()
|
|
<< "\n\tnc(): " << nc()
|
|
<< "\n\tthis: " << this
|
|
);
|
|
if (nc() == 1)
|
|
return ref()(i,0);
|
|
else
|
|
return ref()(0,i);
|
|
}
|
|
|
|
long size (
|
|
) const { return nr()*nc(); }
|
|
|
|
long nr (
|
|
) const { return get_nr_helper<exp_type,NR>::get(ref()); }
|
|
|
|
long nc (
|
|
) const { return get_nc_helper<exp_type,NC>::get(ref()); }
|
|
|
|
template <typename U>
|
|
bool aliases (
|
|
const matrix_exp<U>& item
|
|
) const { return ref().aliases(item); }
|
|
|
|
template <typename U>
|
|
bool destructively_aliases (
|
|
const matrix_exp<U>& item
|
|
) const { return ref().destructively_aliases(item); }
|
|
|
|
inline const exp_type& ref (
|
|
) const { return *static_cast<const exp_type*>(this); }
|
|
|
|
inline operator const type (
|
|
) const
|
|
{
|
|
COMPILE_TIME_ASSERT(NC == 1 || NC == 0);
|
|
COMPILE_TIME_ASSERT(NR == 1 || NR == 0);
|
|
DLIB_ASSERT(nr() == 1 && nc() == 1,
|
|
"\tmatrix_exp::operator const type() const"
|
|
<< "\n\tYou can only use this operator on a 1x1 matrix"
|
|
<< "\n\tnr(): " << nr()
|
|
<< "\n\tnc(): " << nc()
|
|
<< "\n\tthis: " << this
|
|
);
|
|
|
|
// Put the expression contained in this matrix_exp into
|
|
// a temporary 1x1 matrix so that the expression will encounter
|
|
// all the overloads of matrix_assign() and have the chance to
|
|
// go through any applicable optimizations.
|
|
matrix<type,1,1,mem_manager_type,layout_type> temp(ref());
|
|
return temp(0);
|
|
}
|
|
|
|
const_iterator begin() const { return matrix_exp_iterator<EXP>(ref(),0,0); }
|
|
const_iterator end() const { return matrix_exp_iterator<EXP>(ref(),nr(),0); }
|
|
|
|
protected:
|
|
matrix_exp() {}
|
|
matrix_exp(const matrix_exp& ) {}
|
|
|
|
private:
|
|
|
|
matrix_exp& operator= (const matrix_exp&);
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
// something is a matrix if it is convertible to a matrix_exp object
|
|
template <typename T>
|
|
struct is_matrix<T, typename enable_if<is_convertible<T, const matrix_exp<typename T::exp_type>& > >::type >
|
|
{ static const bool value = true; };
|
|
/*
|
|
is_matrix<T>::value == 1 if T is a matrix type else 0
|
|
*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename EXP
|
|
>
|
|
class matrix_diag_exp : public matrix_exp<EXP>
|
|
{
|
|
/*!
|
|
This is a matrix expression type used to represent diagonal matrices.
|
|
That is, square matrices with all off diagonal elements equal to 0.
|
|
!*/
|
|
|
|
protected:
|
|
matrix_diag_exp() {}
|
|
matrix_diag_exp(const matrix_diag_exp& item ):matrix_exp<EXP>(item) {}
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_MATRIx_EXP_h_
|
|
|