1342 lines
39 KiB
C++
1342 lines
39 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_DATA_LAYOUT_
|
|
#define DLIB_MATRIx_DATA_LAYOUT_
|
|
|
|
#include "../algs.h"
|
|
#include "matrix_fwd.h"
|
|
#include "matrix_data_layout_abstract.h"
|
|
#ifdef MATLAB_MEX_FILE
|
|
#include <mex.h>
|
|
#endif
|
|
|
|
// GCC 4.8 gives false alarms about some matrix operations going out of bounds. Disable
|
|
// these false warnings.
|
|
#if defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4))
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Warray-bounds"
|
|
#endif
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
);
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
);
|
|
|
|
T& operator() (
|
|
size_t i
|
|
);
|
|
|
|
const T& operator() (
|
|
size_t i
|
|
) const;
|
|
|
|
void swap(
|
|
layout& item
|
|
);
|
|
|
|
long nr (
|
|
) const;
|
|
|
|
long nc (
|
|
) const;
|
|
|
|
void set_size (
|
|
size_t nr_,
|
|
size_t nc_
|
|
);
|
|
};
|
|
};
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
struct row_major_layout
|
|
{
|
|
// if a matrix is bigger than this many bytes then don't put it on the stack
|
|
const static size_t max_stack_based_size = 256;
|
|
|
|
// 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 <= max_stack_based_size) && (num_rows != 0 && num_cols != 0),
|
|
// when the sizes are all non zero and big
|
|
(num_rows*num_cols*get_sizeof_helper<T>::val > max_stack_based_size) && (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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return *(data+r*num_cols + c); }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return *(data+r*num_cols + c); }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t ,
|
|
size_t
|
|
)
|
|
{
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[r*num_cols + c]; }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[r*num_cols + c]; }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t ,
|
|
size_t
|
|
)
|
|
{
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[r*num_cols + c]; }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[r*num_cols + c]; }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t nr,
|
|
size_t nc
|
|
)
|
|
{
|
|
if (data)
|
|
{
|
|
pool.deallocate_array(data);
|
|
}
|
|
data = pool.allocate_array(nr*nc);
|
|
nr_ = nr;
|
|
}
|
|
|
|
std::unique_ptr<T[]> steal_memory()
|
|
{
|
|
auto ret = pool.extract_array(data);
|
|
data = nullptr;
|
|
nr_ = 0;
|
|
return ret;
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[r*nc_ + c]; }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[r*nc_ + c]; }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t nr,
|
|
size_t nc
|
|
)
|
|
{
|
|
if (data)
|
|
{
|
|
pool.deallocate_array(data);
|
|
}
|
|
data = pool.allocate_array(nr*nc);
|
|
nc_ = nc;
|
|
}
|
|
|
|
std::unique_ptr<T[]> steal_memory()
|
|
{
|
|
auto ret = pool.extract_array(data);
|
|
data = nullptr;
|
|
nc_ = 0;
|
|
return ret;
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[r*nc_ + c]; }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[r*nc_ + c]; }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t nr,
|
|
size_t nc
|
|
)
|
|
{
|
|
if (data)
|
|
{
|
|
pool.deallocate_array(data);
|
|
}
|
|
data = pool.allocate_array(nr*nc);
|
|
nr_ = nr;
|
|
nc_ = nc;
|
|
}
|
|
|
|
std::unique_ptr<T[]> steal_memory()
|
|
{
|
|
auto ret = pool.extract_array(data);
|
|
data = nullptr;
|
|
nr_ = 0;
|
|
nc_ = 0;
|
|
return ret;
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
private:
|
|
T* data;
|
|
long nr_;
|
|
long nc_;
|
|
typename mem_manager::template rebind<T>::other pool;
|
|
};
|
|
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
struct column_major_layout
|
|
{
|
|
// if a matrix is bigger than this many bytes then don't put it on the stack
|
|
const static size_t max_stack_based_size = 256;
|
|
|
|
|
|
// 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 <= max_stack_based_size) && (num_rows != 0 && num_cols != 0),
|
|
// when the sizes are all non zero and big
|
|
(num_rows*num_cols*get_sizeof_helper<T>::val > max_stack_based_size) && (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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return *(data+c*num_rows + r); }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return *(data+c*num_rows + r); }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t,
|
|
size_t
|
|
)
|
|
{
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
private:
|
|
T data[num_cols*num_rows];
|
|
};
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[c*num_rows + r]; }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[c*num_rows + r]; }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t ,
|
|
size_t
|
|
)
|
|
{
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[c*nr_ + r]; }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[c*nr_ + r]; }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t nr,
|
|
size_t nc
|
|
)
|
|
{
|
|
if (data)
|
|
{
|
|
pool.deallocate_array(data);
|
|
}
|
|
data = pool.allocate_array(nr*nc);
|
|
nr_ = nr;
|
|
}
|
|
|
|
std::unique_ptr<T[]> steal_memory()
|
|
{
|
|
auto ret = pool.extract_array(data);
|
|
data = nullptr;
|
|
nr_ = 0;
|
|
return ret;
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[c*num_rows + r]; }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[c*num_rows + r]; }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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 (
|
|
size_t nr,
|
|
size_t nc
|
|
)
|
|
{
|
|
if (data)
|
|
{
|
|
pool.deallocate_array(data);
|
|
}
|
|
data = pool.allocate_array(nr*nc);
|
|
nc_ = nc;
|
|
}
|
|
|
|
std::unique_ptr<T[]> steal_memory()
|
|
{
|
|
auto ret = pool.extract_array(data);
|
|
data = nullptr;
|
|
nc_ = 0;
|
|
return ret;
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
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() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[c*nr_ + r]; }
|
|
|
|
const T& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[c*nr_ + r]; }
|
|
|
|
T& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const T& operator() (
|
|
size_t 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);
|
|
}
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
|
|
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
|
|
void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
|
|
bool _private_is_owned_by_matlab() const { return false; }
|
|
#endif
|
|
|
|
long nr (
|
|
) const { return nr_; }
|
|
|
|
long nc (
|
|
) const { return nc_; }
|
|
|
|
void set_size (
|
|
size_t nr,
|
|
size_t nc
|
|
)
|
|
{
|
|
if (data)
|
|
{
|
|
pool.deallocate_array(data);
|
|
}
|
|
data = pool.allocate_array(nr*nc);
|
|
nr_ = nr;
|
|
nc_ = nc;
|
|
}
|
|
|
|
std::unique_ptr<T[]> steal_memory()
|
|
{
|
|
auto ret = pool.extract_array(data);
|
|
data = nullptr;
|
|
nr_ = 0;
|
|
nc_ = 0;
|
|
return ret;
|
|
}
|
|
|
|
private:
|
|
T* data;
|
|
long nr_;
|
|
long nc_;
|
|
typename mem_manager::template rebind<T>::other pool;
|
|
};
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
template <
|
|
long num_rows,
|
|
long num_cols
|
|
>
|
|
class layout<double,num_rows,num_cols,default_memory_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), owned_by_matlab(false),set_by_private_set_mxArray(false),mem(0) { }
|
|
|
|
~layout ()
|
|
{
|
|
if (owned_by_matlab)
|
|
{
|
|
if (!set_by_private_set_mxArray && mem)
|
|
{
|
|
mxDestroyArray(mem);
|
|
mem = 0;
|
|
data = 0;
|
|
}
|
|
}
|
|
else if (data)
|
|
{
|
|
delete [] data;
|
|
data = 0;
|
|
}
|
|
}
|
|
|
|
double& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[c*nr_ + r]; }
|
|
|
|
const double& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[c*nr_ + r]; }
|
|
|
|
double& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const double& operator() (
|
|
size_t i
|
|
) const { return data[i]; }
|
|
|
|
void _private_set_mxArray (
|
|
mxArray* mem_
|
|
)
|
|
{
|
|
DLIB_CASSERT(mem == 0 && data == 0,"You can't call this function on an already allocated matrix.");
|
|
// We don't own the pointer, so make note of that so we won't try to free
|
|
// it.
|
|
set_by_private_set_mxArray = true;
|
|
owned_by_matlab = true;
|
|
mem = mem_;
|
|
data = mxGetPr(mem);
|
|
nr_ = mxGetM(mem);
|
|
nc_ = mxGetN(mem);
|
|
}
|
|
|
|
mxArray* _private_release_mxArray()
|
|
{
|
|
DLIB_CASSERT(owned_by_matlab,"");
|
|
mxArray* temp = mem;
|
|
mem = 0;
|
|
set_by_private_set_mxArray = false;
|
|
data = 0;
|
|
nr_ = 0;
|
|
nc_ = 0;
|
|
return temp;
|
|
}
|
|
|
|
void _private_mark_owned_by_matlab()
|
|
{
|
|
DLIB_CASSERT(mem == 0 && data == 0,"You can't say a matrix should be owned by matlab after it's been allocated.");
|
|
owned_by_matlab = true;
|
|
}
|
|
bool _private_is_owned_by_matlab() const
|
|
{
|
|
return owned_by_matlab;
|
|
}
|
|
|
|
void swap(
|
|
layout& item
|
|
)
|
|
{
|
|
std::swap(item.owned_by_matlab,owned_by_matlab);
|
|
std::swap(item.set_by_private_set_mxArray,set_by_private_set_mxArray);
|
|
std::swap(item.mem,mem);
|
|
std::swap(item.data,data);
|
|
std::swap(item.nc_,nc_);
|
|
std::swap(item.nr_,nr_);
|
|
}
|
|
|
|
long nr (
|
|
) const { return nr_; }
|
|
|
|
long nc (
|
|
) const { return nc_; }
|
|
|
|
void set_size (
|
|
size_t nr,
|
|
size_t nc
|
|
)
|
|
{
|
|
if (owned_by_matlab)
|
|
{
|
|
if (!set_by_private_set_mxArray && mem)
|
|
{
|
|
mxDestroyArray(mem);
|
|
mem = 0;
|
|
data = 0;
|
|
}
|
|
set_by_private_set_mxArray = false;
|
|
|
|
mem = mxCreateDoubleMatrix(nr, nc, mxREAL);
|
|
if (mem == 0)
|
|
throw std::bad_alloc();
|
|
data = mxGetPr(mem);
|
|
}
|
|
else
|
|
{
|
|
if (data)
|
|
delete [] data;
|
|
data = new double[nr*nc];
|
|
}
|
|
nr_ = nr;
|
|
nc_ = nc;
|
|
}
|
|
|
|
std::unique_ptr<double[]> steal_memory()
|
|
{
|
|
DLIB_CASSERT(!owned_by_matlab, "You can't steal the memory from a matrix if it's owned by MATLAB.");
|
|
std::unique_ptr<double[]> ret(data);
|
|
data = nullptr;
|
|
nr_ = 0;
|
|
nc_ = 0;
|
|
return ret;
|
|
}
|
|
|
|
private:
|
|
double* data;
|
|
long nr_;
|
|
long nc_;
|
|
bool owned_by_matlab;
|
|
bool set_by_private_set_mxArray;
|
|
mxArray* mem;
|
|
};
|
|
|
|
template <
|
|
long num_rows,
|
|
long num_cols
|
|
>
|
|
class layout<float,num_rows,num_cols,default_memory_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), owned_by_matlab(false),set_by_private_set_mxArray(false),mem(0) { }
|
|
|
|
~layout ()
|
|
{
|
|
if (owned_by_matlab)
|
|
{
|
|
if (!set_by_private_set_mxArray && mem)
|
|
{
|
|
mxDestroyArray(mem);
|
|
mem = 0;
|
|
data = 0;
|
|
}
|
|
}
|
|
else if (data)
|
|
{
|
|
delete [] data;
|
|
data = 0;
|
|
}
|
|
}
|
|
|
|
float& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) { return data[c*nr_ + r]; }
|
|
|
|
const float& operator() (
|
|
size_t r,
|
|
size_t c
|
|
) const { return data[c*nr_ + r]; }
|
|
|
|
float& operator() (
|
|
size_t i
|
|
) { return data[i]; }
|
|
|
|
const float& operator() (
|
|
size_t i
|
|
) const { return data[i]; }
|
|
|
|
void _private_set_mxArray (
|
|
mxArray* mem_
|
|
)
|
|
{
|
|
DLIB_CASSERT(mem == 0 && data == 0,"You can't call this function on an already allocated matrix.");
|
|
// We don't own the pointer, so make note of that so we won't try to free
|
|
// it.
|
|
set_by_private_set_mxArray = true;
|
|
owned_by_matlab = true;
|
|
mem = mem_;
|
|
data = (float*)mxGetData(mem);
|
|
nr_ = mxGetM(mem);
|
|
nc_ = mxGetN(mem);
|
|
}
|
|
|
|
mxArray* _private_release_mxArray()
|
|
{
|
|
DLIB_CASSERT(owned_by_matlab,"");
|
|
mxArray* temp = mem;
|
|
mem = 0;
|
|
set_by_private_set_mxArray = false;
|
|
data = 0;
|
|
nr_ = 0;
|
|
nc_ = 0;
|
|
return temp;
|
|
}
|
|
|
|
void _private_mark_owned_by_matlab()
|
|
{
|
|
DLIB_CASSERT(mem == 0 && data == 0,"You can't say a matrix should be owned by matlab after it's been allocated.");
|
|
owned_by_matlab = true;
|
|
}
|
|
bool _private_is_owned_by_matlab() const
|
|
{
|
|
return owned_by_matlab;
|
|
}
|
|
|
|
void swap(
|
|
layout& item
|
|
)
|
|
{
|
|
std::swap(item.owned_by_matlab,owned_by_matlab);
|
|
std::swap(item.set_by_private_set_mxArray,set_by_private_set_mxArray);
|
|
std::swap(item.mem,mem);
|
|
std::swap(item.data,data);
|
|
std::swap(item.nc_,nc_);
|
|
std::swap(item.nr_,nr_);
|
|
}
|
|
|
|
long nr (
|
|
) const { return nr_; }
|
|
|
|
long nc (
|
|
) const { return nc_; }
|
|
|
|
void set_size (
|
|
size_t nr,
|
|
size_t nc
|
|
)
|
|
{
|
|
if (owned_by_matlab)
|
|
{
|
|
if (!set_by_private_set_mxArray && mem)
|
|
{
|
|
mxDestroyArray(mem);
|
|
mem = 0;
|
|
data = 0;
|
|
}
|
|
set_by_private_set_mxArray = false;
|
|
|
|
mem = mxCreateNumericMatrix(nr, nc, mxSINGLE_CLASS, mxREAL);
|
|
if (mem == 0)
|
|
throw std::bad_alloc();
|
|
data = (float*)mxGetData(mem);
|
|
}
|
|
else
|
|
{
|
|
if (data)
|
|
delete [] data;
|
|
data = new float[nr*nc];
|
|
}
|
|
nr_ = nr;
|
|
nc_ = nc;
|
|
}
|
|
|
|
std::unique_ptr<float[]> steal_memory()
|
|
{
|
|
DLIB_CASSERT(!owned_by_matlab, "You can't steal the memory from a matrix if it's owned by MATLAB.");
|
|
std::unique_ptr<float[]> ret(data);
|
|
data = nullptr;
|
|
nr_ = 0;
|
|
nc_ = 0;
|
|
return ret;
|
|
}
|
|
|
|
private:
|
|
float* data;
|
|
long nr_;
|
|
long nc_;
|
|
bool owned_by_matlab;
|
|
bool set_by_private_set_mxArray;
|
|
mxArray* mem;
|
|
};
|
|
#endif
|
|
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#if defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4))
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
#endif // DLIB_MATRIx_DATA_LAYOUT_
|
|
|