Commit d55f589e authored by Davis King's avatar Davis King
Browse files

Changed the matrix so that it isn't forced to use the one matrix_data object. Now

it has a template argument that lets you supply any kind of matrix layout object
you want.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402704
parent dc85ffd1
This diff is collapsed.
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "../serialize.h" #include "../serialize.h"
#include "../memory_manager.h" #include "../memory_manager.h"
#include "matrix_data_layout_abstract.h"
namespace dlib namespace dlib
{ {
...@@ -15,7 +16,8 @@ namespace dlib ...@@ -15,7 +16,8 @@ namespace dlib
typename T, typename T,
long num_rows, long num_rows,
long num_cols, long num_cols,
typename mem_manager typename mem_manager,
typename layout
> >
class matrix; class matrix;
...@@ -25,7 +27,8 @@ namespace dlib ...@@ -25,7 +27,8 @@ namespace dlib
typename T, typename T,
long num_rows, long num_rows,
long num_cols, long num_cols,
typename mem_manager typename mem_manager,
typename layout
> >
class matrix_ref class matrix_ref
{ {
...@@ -38,11 +41,12 @@ namespace dlib ...@@ -38,11 +41,12 @@ namespace dlib
typedef T type; typedef T type;
typedef matrix_ref ref_type; typedef matrix_ref ref_type;
typedef mem_manager mem_manager_type; typedef mem_manager mem_manager_type;
typedef layout layout_type;
const static long NR = num_rows; const static long NR = num_rows;
const static long NC = num_cols; const static long NC = num_cols;
matrix_ref ( matrix_ref (
const matrix<T,num_rows,num_cols,mem_manager>& m const matrix<T,num_rows,num_cols,mem_manager,layout>& m
); );
/*! /*!
ensures ensures
...@@ -92,18 +96,18 @@ namespace dlib ...@@ -92,18 +96,18 @@ namespace dlib
- returns nr()*nc() - returns nr()*nc()
!*/ !*/
template <typename U, long iNR, long iNC, typename mm> template <typename U, long iNR, long iNC, typename mm, typename l>
bool destructively_aliases ( bool destructively_aliases (
const matrix<U,iNR,iNC,mm>& item const matrix<U,iNR,iNC,mm,l>& item
) const; ) const;
/*! /*!
ensures ensures
- returns false - returns false
!*/ !*/
template <typename U, long iNR, long iNC, typename mm> template <typename U, long iNR, long iNC, typename mm, typename l>
bool aliases ( bool aliases (
const matrix<U,iNR,iNC,mm>& item const matrix<U,iNR,iNC,mm,l>& item
) const; ) const;
/*! /*!
ensures ensures
...@@ -234,9 +238,9 @@ namespace dlib ...@@ -234,9 +238,9 @@ namespace dlib
- returns nr()*nc() - returns nr()*nc()
!*/ !*/
template <typename U, long iNR, long iNC , typename mm> template <typename U, long iNR, long iNC , typename mm, typename l>
bool aliases ( bool aliases (
const matrix<U,iNR,iNC,mm>& item const matrix<U,iNR,iNC,mm,l>& item
) const; ) const;
/*! /*!
ensures ensures
...@@ -247,9 +251,9 @@ namespace dlib ...@@ -247,9 +251,9 @@ namespace dlib
- returns false - returns false
!*/ !*/
template <typename U, long iNR, long iNC, typename mm > template <typename U, long iNR, long iNC, typename mm, typename l>
bool destructively_aliases ( bool destructively_aliases (
const matrix<U,iNR,iNC,mm>& item const matrix<U,iNR,iNC,mm,l>& item
) const; ) const;
/*! /*!
ensures ensures
...@@ -404,9 +408,10 @@ namespace dlib ...@@ -404,9 +408,10 @@ namespace dlib
typename T, typename T,
long num_rows = 0, long num_rows = 0,
long num_cols = 0, long num_cols = 0,
typename mem_manager = memory_manager<char>::kernel_1a typename mem_manager = memory_manager<char>::kernel_1a,
typename layout = default_matrix_layout
> >
class matrix : public matrix_exp<matrix_ref<T,num_rows,num_cols,mem_manager> > class matrix : public matrix_exp<matrix_ref<T,num_rows,num_cols,mem_manager,layout> >
{ {
/*! /*!
REQUIREMENTS ON num_rows and num_cols REQUIREMENTS ON num_rows and num_cols
...@@ -418,6 +423,10 @@ namespace dlib ...@@ -418,6 +423,10 @@ namespace dlib
must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
mem_manager::type can be set to anything. mem_manager::type can be set to anything.
REQUIREMENTS ON layout
must be one of the layout objects defined in matrix/matrix_data_layout_abstract.h or an
object with a compatible interface.
INITIAL VALUE INITIAL VALUE
- if (num_rows > 0) then - if (num_rows > 0) then
- nr() == num_rows - nr() == num_rows
...@@ -445,16 +454,18 @@ namespace dlib ...@@ -445,16 +454,18 @@ namespace dlib
be detected at compile time. It also allows the compiler to perform loop be detected at compile time. It also allows the compiler to perform loop
unrolling which can result in substantially faster code. unrolling which can result in substantially faster code.
Also note that the elements of this matrix are contiguous in memory and Also note that the elements of this matrix are laid out in memory by the layout
stored in row major order. Additionally, all memory allocations are object supplied as a template argument to this class. The default_matrix_layout
performed using the memory manager object supplied as a template argument sets elements down contiguously in memory and in row major order. Additionally,
to this class. all memory allocations are performed using the memory manager object supplied as
a template argument to this class.
!*/ !*/
public: public:
typedef T type; typedef T type;
typedef matrix_ref<T,num_rows,num_cols,mem_manager> ref_type; typedef matrix_ref<T,num_rows,num_cols,mem_manager,layout> ref_type;
typedef mem_manager mem_manager_type; typedef mem_manager mem_manager_type;
typedef layout layout_type;
const static long NR = num_rows; const static long NR = num_rows;
const static long NC = num_cols; const static long NC = num_cols;
...@@ -754,11 +765,12 @@ namespace dlib ...@@ -754,11 +765,12 @@ namespace dlib
typename T, typename T,
long NR, long NR,
long NC, long NC,
typename mm typename mm,
typename l
> >
void swap( void swap(
matrix<T,NR,NC,mm>& a, matrix<T,NR,NC,mm,l>& a,
matrix<T,NR,NC,mm>& b matrix<T,NR,NC,mm,l>& b
) { a.swap(b); } ) { a.swap(b); }
/*! /*!
Provides a global swap function Provides a global swap function
...@@ -768,10 +780,11 @@ namespace dlib ...@@ -768,10 +780,11 @@ namespace dlib
typename T, typename T,
long NR, long NR,
long NC, long NC,
typename mm typename mm,
typename l
> >
void serialize ( void serialize (
const matrix<T,NR,NC,mm>& item, const matrix<T,NR,NC,mm,l>& item,
std::ostream& out std::ostream& out
); );
/*! /*!
...@@ -782,10 +795,11 @@ namespace dlib ...@@ -782,10 +795,11 @@ namespace dlib
typename T, typename T,
long NR, long NR,
long NC, long NC,
typename mm typename mm,
typename l
> >
void deserialize ( void deserialize (
matrix<T,NR,NC,mm>& item, matrix<T,NR,NC,mm,l>& item,
std::istream& in std::istream& in
); );
/*! /*!
......
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATRIx_DATA_LAYOUT_
#define DLIB_MATRIx_DATA_LAYOUT_
#include "../algs.h"
#include "matrix_fwd.h"
#include "matrix_data_layout_abstract.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
/*!
A matrix layout object is any object that contains a templated class called "layout"
with an interface identical to one below:
(Note that all the template arguments are just the template arguments from the dlib::matrix
object and the member functions are defined identically to the ones with the same
signatures inside the matrix object.)
struct matrix_layout
{
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager
>
class layout
{
public:
T& operator() (
long r,
long c
);
const T& operator() (
long r,
long c
);
T& operator() (
long i
);
const T& operator() (
long i
) const;
void swap(
layout& item
);
long nr (
) const;
long nc (
) const;
void set_size (
long nr_,
long nc_
);
};
};
!*/
// ----------------------------------------------------------------------------------------
struct default_matrix_layout
{
// this is a hack to avoid a compile time error in visual studio 8. I would just
// use sizeof(T) and be done with it but that won't compile. The idea here
// is to avoid using the stack allocation of the layout object if it
// is going to contain another matrix and also avoid asking for the sizeof()
// the contained matrix.
template <typename T>
struct get_sizeof_helper
{
const static std::size_t val = sizeof(T);
};
template <typename T, long NR, long NC, typename mm, typename l>
struct get_sizeof_helper<matrix<T,NR,NC,mm,l> >
{
const static std::size_t val = 1000000;
};
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager,
int val = static_switch <
// when the sizes are all non zero and small
(num_rows*num_cols*get_sizeof_helper<T>::val <= 64) && (num_rows != 0 && num_cols != 0),
// when the sizes are all non zero and big
(num_rows*num_cols*get_sizeof_helper<T>::val >= 65) && (num_rows != 0 && num_cols != 0),
num_rows == 0 && num_cols != 0,
num_rows != 0 && num_cols == 0,
num_rows == 0 && num_cols == 0
>::value
>
class layout ;
/*!
WHAT THIS OBJECT REPRESENTS
This object represents the actual allocation of space for a matrix.
Small matrices allocate all their data on the stack and bigger ones
use a memory_manager to get their memory.
!*/
// ------------------------------------------------------------------------------------
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager
>
class layout<T,num_rows,num_cols,mem_manager,1> : noncopyable // when the sizes are all non zero and small
{
public:
const static long NR = num_rows;
const static long NC = num_cols;
layout() {}
T& operator() (
long r,
long c
) { return data[r][c]; }
const T& operator() (
long r,
long c
) const { return data[r][c]; }
T& operator() (
long i
) { return *(*data + i); }
const T& operator() (
long i
) const { return *(*data + i); }
void swap(
layout& item
)
{
for (long r = 0; r < num_rows; ++r)
{
for (long c = 0; c < num_cols; ++c)
{
exchange((*this)(r,c),item(r,c));
}
}
}
long nr (
) const { return num_rows; }
long nc (
) const { return num_cols; }
void set_size (
long nr,
long nc
)
{
}
private:
T data[num_rows][num_cols];
};
// ------------------------------------------------------------------------------------
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager
>
class layout<T,num_rows,num_cols,mem_manager,2> : noncopyable // when the sizes are all non zero and big
{
public:
const static long NR = num_rows;
const static long NC = num_cols;
layout (
) { data = pool.allocate_array(num_rows*num_cols); }
~layout ()
{ pool.deallocate_array(data); }
T& operator() (
long r,
long c
) { return data[r*num_cols + c]; }
const T& operator() (
long r,
long c
) const { return data[r*num_cols + c]; }
T& operator() (
long i
) { return data[i]; }
const T& operator() (
long i
) const { return data[i]; }
void swap(
layout& item
)
{
std::swap(item.data,data);
pool.swap(item.pool);
}
long nr (
) const { return num_rows; }
long nc (
) const { return num_cols; }
void set_size (
long nr,
long nc
)
{
}
private:
T* data;
typename mem_manager::template rebind<T>::other pool;
};
// ------------------------------------------------------------------------------------
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager
>
class layout<T,num_rows,num_cols,mem_manager,3> : noncopyable // when num_rows == 0 && num_cols != 0,
{
public:
const static long NR = num_rows;
const static long NC = num_cols;
layout (
):data(0), nr_(0) { }
~layout ()
{
if (data)
pool.deallocate_array(data);
}
T& operator() (
long r,
long c
) { return data[r*num_cols + c]; }
const T& operator() (
long r,
long c
) const { return data[r*num_cols + c]; }
T& operator() (
long i
) { return data[i]; }
const T& operator() (
long i
) const { return data[i]; }
void swap(
layout& item
)
{
std::swap(item.data,data);
std::swap(item.nr_,nr_);
pool.swap(item.pool);
}
long nr (
) const { return nr_; }
long nc (
) const { return num_cols; }
void set_size (
long nr,
long nc
)
{
if (data)
{
pool.deallocate_array(data);
}
data = pool.allocate_array(nr*nc);
nr_ = nr;
}
private:
T* data;
long nr_;
typename mem_manager::template rebind<T>::other pool;
};
// ------------------------------------------------------------------------------------
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager
>
class layout<T,num_rows,num_cols,mem_manager,4> : noncopyable // when num_rows != 0 && num_cols == 0
{
public:
const static long NR = num_rows;
const static long NC = num_cols;
layout (
):data(0), nc_(0) { }
~layout ()
{
if (data)
{
pool.deallocate_array(data);
}
}
T& operator() (
long r,
long c
) { return data[r*nc_ + c]; }
const T& operator() (
long r,
long c
) const { return data[r*nc_ + c]; }
T& operator() (
long i
) { return data[i]; }
const T& operator() (
long i
) const { return data[i]; }
void swap(
layout& item
)
{
std::swap(item.data,data);
std::swap(item.nc_,nc_);
pool.swap(item.pool);
}
long nr (
) const { return num_rows; }
long nc (
) const { return nc_; }
void set_size (
long nr,
long nc
)
{
if (data)
{
pool.deallocate_array(data);
}
data = pool.allocate_array(nr*nc);
nc_ = nc;
}
private:
T* data;
long nc_;
typename mem_manager::template rebind<T>::other pool;
};
// ------------------------------------------------------------------------------------
template <
typename T,
long num_rows,
long num_cols,
typename mem_manager
>
class layout<T,num_rows,num_cols,mem_manager,5> : noncopyable // when num_rows == 0 && num_cols == 0
{
public:
const static long NR = num_rows;
const static long NC = num_cols;
layout (
):data(0), nr_(0), nc_(0) { }
~layout ()
{
if (data)
{
pool.deallocate_array(data);
}
}
T& operator() (
long r,
long c
) { return data[r*nc_ + c]; }
const T& operator() (
long r,
long c
) const { return data[r*nc_ + c]; }
T& operator() (
long i
) { return data[i]; }
const T& operator() (
long i
) const { return data[i]; }
void swap(
layout& item
)
{
std::swap(item.data,data);
std::swap(item.nc_,nc_);
std::swap(item.nr_,nr_);
pool.swap(item.pool);
}
long nr (
) const { return nr_; }
long nc (
) const { return nc_; }
void set_size (
long nr,
long nc
)
{
if (data)
{
pool.deallocate_array(data);
}
data = pool.allocate_array(nr*nc);
nr_ = nr;
nc_ = nc;
}
private:
T* data;
long nr_;
long nc_;
typename mem_manager::template rebind<T>::other pool;
};
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_DATA_LAYOUT_
// Copyright (C) 2008 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_
#ifdef DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_
#include "../algs.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
struct default_matrix_layout
{
/*!
This is the default matrix layout. Any matrix object that uses this
layout will be laid out in memory in row major order. Additionally,
all elements are contiguous (e.g. there isn't any padding at the ends of
rows or anything like that)
!*/
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_
// Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATRIx_FWD
#define DLIB_MATRIx_FWD
#include "../memory_manager.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
struct default_matrix_layout;
// ----------------------------------------------------------------------------------------
template <
typename T,
long num_rows = 0,
long num_cols = 0,
typename mem_manager = memory_manager<char>::kernel_1a,
typename layout = default_matrix_layout
>
class matrix;
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_FWD
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment