// Copyright (C) 2008-2016 National ICT Australia (NICTA)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// -------------------------------------------------------------------
//
// Written by Conrad Sanderson - http://conradsanderson.id.au
// Written by Ryan Curtin
//! \addtogroup Mat
//! @{
template<typename eT>
inline
Mat<eT>::~Mat()
{
arma_extra_debug_sigprint_this(this);
if( (mem_state == 0) && (n_elem > arma_config::mat_prealloc) )
{
memory::release( access::rw(mem) );
}
if(arma_config::debug == true)
{
// try to expose buggy user code that accesses deleted objects
access::rw(mem) = 0;
}
arma_type_check(( is_supported_elem_type<eT>::value == false ));
}
template<typename eT>
inline
Mat<eT>::Mat()
: n_rows(0)
, n_cols(0)
, n_elem(0)
, vec_state(0)
, mem_state(0)
, mem()
{
arma_extra_debug_sigprint_this(this);
}
//! construct the matrix to have user specified dimensions
template<typename eT>
inline
Mat<eT>::Mat(const uword in_n_rows, const uword in_n_cols)
: n_rows(in_n_rows)
, n_cols(in_n_cols)
, n_elem(in_n_rows*in_n_cols)
, vec_state(0)
, mem_state(0)
, mem()
{
arma_extra_debug_sigprint_this(this);
init_cold();
}
template<typename eT>
inline
Mat<eT>::Mat(const SizeMat& s)
: n_rows(s.n_rows)
, n_cols(s.n_cols)
, n_elem(s.n_rows*s.n_cols)
, vec_state(0)
, mem_state(0)
, mem()
{
arma_extra_debug_sigprint_this(this);
init_cold();
}
//! construct the matrix to have user specified dimensions and fill with specified pattern
template<typename eT>
template<typename fill_type>
inline
Mat<eT>::Mat(const uword in_n_rows, const uword in_n_cols, const fill::fill_class<fill_type>& f)
: n_rows(in_n_rows)
, n_cols(in_n_cols)
, n_elem(in_n_rows*in_n_cols)
, vec_state(0)
, mem_state(0)
, mem()
{
arma_extra_debug_sigprint_this(this);
init_cold();
(*this).fill(f);
}
template<typename eT>
template<typename fill_type>
inline
Mat<eT>::Mat(const SizeMat& s, const fill::fill_class<fill_type>& f)
: n_rows(s.n_rows)
, n_cols(s.n_cols)
, n_elem(s.n_rows*s.n_cols)
, vec_state(0)
, mem_state(0)
, mem()
{
arma_extra_debug_sigprint_this(this);
init_cold();
(*this).fill(f);
}
//! constructor used by Row and Col classes
template<typename eT>
inline
Mat<eT>::Mat(const arma_vec_indicator&, const uhword in_vec_state)
: n_rows( (in_vec_state == 2) ? 1 : 0 )
, n_cols( (in_vec_state == 1) ? 1 : 0 )
, n_elem(0)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
{
arma_extra_debug_sigprint_this(this);
}
//! constructor used by Row and Col classes
template<typename eT>
inline
Mat<eT>::Mat(const arma_vec_indicator&, const uword in_n_rows, const uword in_n_cols, const uhword in_vec_state)
: n_rows(in_n_rows)
, n_cols(in_n_cols)
, n_elem(in_n_rows*in_n_cols)
, vec_state(in_vec_state)
, mem_state(0)
, mem()
{
arma_extra_debug_sigprint_this(this);
init_cold();
}
template<typename eT>
inline
Mat<eT>::Mat(const arma_fixed_indicator&, const uword in_n_rows, const uword in_n_cols, const uhword in_vec_state, const eT* in_mem)
: n_rows (in_n_rows)
, n_cols (in_n_cols)
, n_elem (in_n_rows*in_n_cols)
, vec_state (in_vec_state)
, mem_state (3)
, mem (in_mem)
{
arma_extra_debug_sigprint_this(this);
}
template<typename eT>
inline
void
Mat<eT>::init_cold()
{
arma_extra_debug_sigprint( arma_str::format("n_rows = %d, n_cols = %d") % n_rows % n_cols );
// ensure that n_elem can hold the result of (n_rows * n_cols)
#if (defined(ARMA_USE_CXX11) || defined(ARMA_64BIT_WORD))
const char* error_message = "Mat::init(): requested size is too large";
#else
const char* error_message = "Mat::init(): requested size is too large; suggest to compile in C++11 mode or enable ARMA_64BIT_WORD";
#endif
arma_debug_check
(
(
( (n_rows > ARMA_MAX_UHWORD) || (n_cols > ARMA_MAX_UHWORD) )
? ( (double(n_rows) * double(n_cols)) > double(ARMA_MAX_UWORD) )
: false
),
error_message
);
if(n_elem <= arma_config::mat_prealloc)
{
if(n_elem == 0)
{
access::rw(mem) = NULL;
}
else
{
arma_extra_debug_print("Mat::init(): using local memory");
access::rw(mem) = mem_local;
}
}
else
{
arma_extra_debug_print("Mat::init(): acquiring memory");
access::rw(mem) = memory::acquire<eT>(n_elem);
}
}
template<typename eT>
inline
void
Mat<eT>::init_warm(uword in_n_rows, uword in_n_cols)
{
arma_extra_debug_sigprint( arma_str::format("in_n_rows = %d, in_n_cols = %d") % in_n_rows % in_n_cols );
if( (n_rows == in_n_rows) && (n_cols == in_n_cols) ) { return; }
bool err_state = false;
char* err_msg = 0;
const uhword t_vec_state = vec_state;
const uhword t_mem_state = mem_state;
arma_debug_set_error( err_state, err_msg, (t_mem_state == 3), "Mat::init(): size is fixed and hence cannot be changed" );
if(t_vec_state > 0)
{
if( (in_n_rows == 0) && (in_n_cols == 0) )
{
if(t_vec_state == 1) { in_n_cols = 1; }
if(t_vec_state == 2) { in_n_rows = 1; }
}
else
{
if(t_vec_state == 1) { arma_debug_set_error( err_state, err_msg, (in_n_cols != 1), "Mat::init(): requested size is not compatible with column vector layout" ); }
if(t_vec_state == 2) { arma_debug_set_error( err_state, err_msg, (in_n_rows != 1), "Mat::init(): requested size is not compatible with row vector layout" ); }
}
}
// ensure that n_elem can hold the result of (n_rows * n_cols)
#if (defined(ARMA_USE_CXX11) || defined(ARMA_64BIT_WORD))
const char* error_message = "Mat::init(): requested size is too large";
#else
const char* error_message = "Mat::init(): requested size is too large; suggest to compile in C++11 mode or enable ARMA_64BIT_WORD";
#endif
arma_debug_set_error
(
err_state,
err_msg,
(
( (in_n_rows > ARMA_MAX_UHWORD) || (in_n_cols > ARMA_MAX_UHWORD) )
? ( (double(in_n_rows) * double(in_n_cols)) > double(ARMA_MAX_UWORD) )
: false
),
error_message
);
arma_debug_check(err_state, err_msg);
const uword old_n_elem = n_elem;
const uword new_n_elem = in_n_rows * in_n_cols;
if(old_n_elem == new_n_elem)
{
arma_extra_debug_print("Mat::init(): reusing memory");
access::rw(n_rows) = in_n_rows;
access::rw(n_cols) = in_n_cols;
}
else // condition: old_n_elem != new_n_elem
{
arma_debug_check( (t_mem_state == 2), "Mat::init(): mismatch between size of auxiliary memory and requested size" );
if(new_n_elem < old_n_elem) // reuse existing memory if possible
{
if( (t_mem_state == 0) && (new_n_elem <= arma_config::mat_prealloc) )
{
if(old_n_elem > arma_config::mat_prealloc)
{
arma_extra_debug_print("Mat::init(): releasing memory");
memory::release( access::rw(mem) );
}
if(new_n_elem == 0)
{
access::rw(mem) = NULL;
}
else
{
arma_extra_debug_print("Mat::init(): using local memory");
access::rw(mem) = mem_local;
}
}
else
{
arma_extra_debug_print("Mat::init(): reusing memory");
}
}
else // condition: new_n_elem > old_n_elem
{
if( (t_mem_state == 0) && (old_n_elem > arma_config::mat_prealloc) )
{
arma_extra_debug_print("Mat::init(): releasing memory");
memory::release( access::rw(mem) );
}
if(new_n_elem <= arma_config::mat_prealloc)
{
arma_extra_debug_print("Mat::init(): using local memory");
access::rw(mem) = mem_loc