// 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_