From eda5bc26f44ee9a6f83dcf8c91f17296d7fc509d Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Mon, 12 Feb 2024 14:52:43 +0100 Subject: Move into version control --- src/armadillo/include/armadillo_bits/Mat_meat.hpp | 10169 ++++++++++++++++++++ 1 file changed, 10169 insertions(+) create mode 100644 src/armadillo/include/armadillo_bits/Mat_meat.hpp (limited to 'src/armadillo/include/armadillo_bits/Mat_meat.hpp') diff --git a/src/armadillo/include/armadillo_bits/Mat_meat.hpp b/src/armadillo/include/armadillo_bits/Mat_meat.hpp new file mode 100644 index 0000000..cb92ffd --- /dev/null +++ b/src/armadillo/include/armadillo_bits/Mat_meat.hpp @@ -0,0 +1,10169 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au) +// Copyright 2008-2016 National ICT Australia (NICTA) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------ + + +//! \addtogroup Mat +//! @{ + + +template +inline +Mat::~Mat() + { + arma_extra_debug_sigprint_this(this); + + if(n_alloc > 0) + { + arma_extra_debug_print("Mat::destructor: releasing memory"); + memory::release( access::rw(mem) ); + } + + // try to expose buggy user code that accesses deleted objects + if(arma_config::debug) { access::rw(mem) = nullptr; } + + arma_type_check(( is_supported_elem_type::value == false )); + } + + + +template +inline +Mat::Mat() + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + } + + + +//! construct the matrix to have user specified dimensions +template +inline +Mat::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) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + if(arma_config::zero_init) + { + arma_extra_debug_print("Mat::constructor: zeroing memory"); + arrayops::fill_zeros(memptr(), n_elem); + } + } + + + +template +inline +Mat::Mat(const SizeMat& s) + : n_rows(s.n_rows) + , n_cols(s.n_cols) + , n_elem(s.n_rows*s.n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + if(arma_config::zero_init) + { + arma_extra_debug_print("Mat::constructor: zeroing memory"); + arrayops::fill_zeros(memptr(), n_elem); + } + } + + + +//! internal use only +template +template +inline +Mat::Mat(const uword in_n_rows, const uword in_n_cols, const arma_initmode_indicator&) + : n_rows(in_n_rows) + , n_cols(in_n_cols) + , n_elem(in_n_rows*in_n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + if(do_zeros) + { + arma_extra_debug_print("Mat::constructor: zeroing memory"); + arrayops::fill_zeros(memptr(), n_elem); + } + } + + + +//! internal use only +template +template +inline +Mat::Mat(const SizeMat& s, const arma_initmode_indicator&) + : n_rows(s.n_rows) + , n_cols(s.n_cols) + , n_elem(s.n_rows*s.n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + if(do_zeros) + { + arma_extra_debug_print("Mat::constructor: zeroing memory"); + arrayops::fill_zeros(memptr(), n_elem); + } + } + + + +//! construct the matrix to have user specified dimensions and fill with specified pattern +template +template +inline +Mat::Mat(const uword in_n_rows, const uword in_n_cols, const fill::fill_class& f) + : n_rows(in_n_rows) + , n_cols(in_n_cols) + , n_elem(in_n_rows*in_n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + (*this).fill(f); + } + + + +template +template +inline +Mat::Mat(const SizeMat& s, const fill::fill_class& f) + : n_rows(s.n_rows) + , n_cols(s.n_cols) + , n_elem(s.n_rows*s.n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + (*this).fill(f); + } + + + +//! construct the matrix to have user specified dimensions and fill with specified value +template +inline +Mat::Mat(const uword in_n_rows, const uword in_n_cols, const fill::scalar_holder f) + : n_rows(in_n_rows) + , n_cols(in_n_cols) + , n_elem(in_n_rows*in_n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + (*this).fill(f.scalar); + } + + + +template +inline +Mat::Mat(const SizeMat& s, const fill::scalar_holder f) + : n_rows(s.n_rows) + , n_cols(s.n_cols) + , n_elem(s.n_rows*s.n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + (*this).fill(f.scalar); + } + + + +//! constructor used by Row and Col classes +template +inline +Mat::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) + , n_alloc(0) + , vec_state(in_vec_state) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + } + + + +//! constructor used by Row and Col classes +template +inline +Mat::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) + , n_alloc() + , vec_state(in_vec_state) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + } + + + +template +inline +Mat::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) + , n_alloc (0) + , vec_state (in_vec_state) + , mem_state (3) + , mem (in_mem) + { + arma_extra_debug_sigprint_this(this); + } + + + +template +inline +void +Mat::init_cold() + { + arma_extra_debug_sigprint( arma_str::format("n_rows = %u, n_cols = %u") % n_rows % n_cols ); + + // ensure that n_elem can hold the result of (n_rows * n_cols) + + #if 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 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) { arma_extra_debug_print("Mat::init(): using local memory"); } + + access::rw(mem) = (n_elem == 0) ? nullptr : mem_local; + access::rw(n_alloc) = 0; + } + else + { + arma_extra_debug_print("Mat::init(): acquiring memory"); + + access::rw(mem) = memory::acquire(n_elem); + access::rw(n_alloc) = n_elem; + } + } + + + +template +inline +void +Mat::init_warm(uword in_n_rows, uword in_n_cols) + { + arma_extra_debug_sigprint( arma_str::format("in_n_rows = %u, in_n_cols = %u") % 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 = nullptr; + + const uhword t_vec_state = vec_state; + const uhword t_mem_state = mem_state; + + const char* error_message_1 = "Mat::init(): size is fixed and hence cannot be changed"; + const char* error_message_2 = "Mat::init(): requested size is not compatible with column vector layout"; + const char* error_message_3 = "Mat::init(): requested size is not compatible with row vector layout"; + + arma_debug_set_error( err_state, err_msg, (t_mem_state == 3), error_message_1 ); + + 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), error_message_2 ); } + if(t_vec_state == 2) { arma_debug_set_error( err_state, err_msg, (in_n_rows != 1), error_message_3 ); } + } + } + + // ensure that n_elem can hold the result of (n_rows * n_cols) + + #if defined(ARMA_64BIT_WORD) + const char* error_message_4 = "Mat::init(): requested size is too large"; + #else + const char* error_message_4 = "Mat::init(): requested size is too large; suggest to 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_4 + ); + + 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; + return; + } + + arma_debug_check( (t_mem_state == 2), "Mat::init(): mismatch between size of auxiliary memory and requested size" ); + + if(new_n_elem <= arma_config::mat_prealloc) + { + if(n_alloc > 0) + { + arma_extra_debug_print("Mat::init(): releasing memory"); + memory::release( access::rw(mem) ); + } + + if(new_n_elem > 0) { arma_extra_debug_print("Mat::init(): using local memory"); } + + access::rw(mem) = (new_n_elem == 0) ? nullptr : mem_local; + access::rw(n_alloc) = 0; + } + else // condition: new_n_elem > arma_config::mat_prealloc + { + if(new_n_elem > n_alloc) + { + if(n_alloc > 0) + { + arma_extra_debug_print("Mat::init(): releasing memory"); + memory::release( access::rw(mem) ); + + // in case memory::acquire() throws an exception + access::rw(mem) = nullptr; + access::rw(n_rows) = 0; + access::rw(n_cols) = 0; + access::rw(n_elem) = 0; + access::rw(n_alloc) = 0; + } + + arma_extra_debug_print("Mat::init(): acquiring memory"); + access::rw(mem) = memory::acquire(new_n_elem); + access::rw(n_alloc) = new_n_elem; + } + else // condition: new_n_elem <= n_alloc + { + arma_extra_debug_print("Mat::init(): reusing memory"); + } + } + + access::rw(n_rows) = in_n_rows; + access::rw(n_cols) = in_n_cols; + access::rw(n_elem) = new_n_elem; + access::rw(mem_state) = 0; + } + + + +//! create the matrix from a textual description +template +inline +Mat::Mat(const char* text) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init( std::string(text) ); + } + + + +//! create the matrix from a textual description +template +inline +Mat& +Mat::operator=(const char* text) + { + arma_extra_debug_sigprint(); + + init( std::string(text) ); + + return *this; + } + + + +//! create the matrix from a textual description +template +inline +Mat::Mat(const std::string& text) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init(text); + } + + + +//! create the matrix from a textual description +template +inline +Mat& +Mat::operator=(const std::string& text) + { + arma_extra_debug_sigprint(); + + init(text); + + return *this; + } + + + +//! internal function to create the matrix from a textual description +template +inline +void +Mat::init(const std::string& text_orig) + { + arma_extra_debug_sigprint(); + + const bool replace_commas = (is_cx::yes) ? false : ( text_orig.find(',') != std::string::npos ); + + std::string text_mod; + + if(replace_commas) { text_mod = text_orig; std::replace(text_mod.begin(), text_mod.end(), ',', ' '); } + + const std::string& text = (replace_commas) ? text_mod : text_orig; + + // + // work out the size + + uword t_n_rows = 0; + uword t_n_cols = 0; + + bool has_semicolon = false; + bool has_token = false; + + std::string token; + + std::string::size_type line_start = 0; + std::string::size_type line_end = 0; + std::string::size_type line_len = 0; + + std::stringstream line_stream; + + while( line_start < text.length() ) + { + line_end = text.find(';', line_start); + + if(line_end == std::string::npos) + { + has_semicolon = false; + line_end = text.length()-1; + line_len = line_end - line_start + 1; + } + else + { + has_semicolon = true; + line_len = line_end - line_start; // omit the ';' character + } + + line_stream.clear(); + line_stream.str( text.substr(line_start,line_len) ); + + has_token = false; + + uword line_n_cols = 0; + + while(line_stream >> token) { has_token = true; ++line_n_cols; } + + if(t_n_rows == 0) + { + t_n_cols = line_n_cols; + } + else + { + if(has_semicolon || has_token) { arma_check( (line_n_cols != t_n_cols), "Mat::init(): inconsistent number of columns in given string"); } + } + + ++t_n_rows; + + line_start = line_end+1; + } + + // if the last line was empty, ignore it + if( (has_semicolon == false) && (has_token == false) && (t_n_rows >= 1) ) { --t_n_rows; } + + Mat& x = (*this); + x.set_size(t_n_rows, t_n_cols); + + if(x.is_empty()) { return; } + + line_start = 0; + line_end = 0; + line_len = 0; + + uword urow = 0; + + while( line_start < text.length() ) + { + line_end = text.find(';', line_start); + + if(line_end == std::string::npos) + { + line_end = text.length()-1; + line_len = line_end - line_start + 1; + } + else + { + line_len = line_end - line_start; // omit the ';' character + } + + line_stream.clear(); + line_stream.str( text.substr(line_start,line_len) ); + + uword ucol = 0; + while(line_stream >> token) + { + diskio::convert_token( x.at(urow,ucol), token ); + ++ucol; + } + + ++urow; + line_start = line_end+1; + } + } + + + +//! create the matrix from std::vector +template +inline +Mat::Mat(const std::vector& x) + : n_rows(uword(x.size())) + , n_cols(1) + , n_elem(uword(x.size())) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + if(n_elem > 0) { arrayops::copy( memptr(), &(x[0]), n_elem ); } + } + + + +//! create the matrix from std::vector +template +inline +Mat& +Mat::operator=(const std::vector& x) + { + arma_extra_debug_sigprint(); + + init_warm(uword(x.size()), 1); + + if(x.size() > 0) { arrayops::copy( memptr(), &(x[0]), uword(x.size()) ); } + + return *this; + } + + + +template +inline +Mat::Mat(const std::initializer_list& list) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init(list); + } + + + +template +inline +Mat& +Mat::operator=(const std::initializer_list& list) + { + arma_extra_debug_sigprint(); + + init(list); + + return *this; + } + + + +template +inline +Mat::Mat(const std::initializer_list< std::initializer_list >& list) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init(list); + } + + + +template +inline +Mat& +Mat::operator=(const std::initializer_list< std::initializer_list >& list) + { + arma_extra_debug_sigprint(); + + init(list); + + return *this; + } + + + +template +inline +Mat::Mat(Mat&& X) + : n_rows (X.n_rows ) + , n_cols (X.n_cols ) + , n_elem (X.n_elem ) + , n_alloc (X.n_alloc) + , vec_state(0 ) + , mem_state(0 ) + , mem ( ) + { + arma_extra_debug_sigprint(arma_str::format("this = %x X = %x") % this % &X); + + if( (X.n_alloc > arma_config::mat_prealloc) || (X.mem_state == 1) || (X.mem_state == 2) ) + { + access::rw(mem_state) = X.mem_state; + access::rw(mem) = X.mem; + + access::rw(X.n_rows) = 0; + access::rw(X.n_cols) = 0; + access::rw(X.n_elem) = 0; + access::rw(X.n_alloc) = 0; + access::rw(X.mem_state) = 0; + access::rw(X.mem) = nullptr; + } + else // condition: (X.n_alloc <= arma_config::mat_prealloc) || (X.mem_state == 0) || (X.mem_state == 3) + { + init_cold(); + + arrayops::copy( memptr(), X.mem, X.n_elem ); + + if( (X.mem_state == 0) && (X.n_alloc <= arma_config::mat_prealloc) ) + { + access::rw(X.n_rows) = 0; + access::rw(X.n_cols) = 0; + access::rw(X.n_elem) = 0; + access::rw(X.mem) = nullptr; + } + } + } + + + +template +inline +Mat& +Mat::operator=(Mat&& X) + { + arma_extra_debug_sigprint(arma_str::format("this = %x X = %x") % this % &X); + + (*this).steal_mem(X, true); + + return *this; + } + + + +//! Set the matrix to be equal to the specified scalar. +//! NOTE: the size of the matrix will be 1x1 +template +inline +Mat& +Mat::operator=(const eT val) + { + arma_extra_debug_sigprint(); + + init_warm(1,1); + + access::rw(mem[0]) = val; + + return *this; + } + + + +//! In-place addition of a scalar to all elements of the matrix +template +inline +Mat& +Mat::operator+=(const eT val) + { + arma_extra_debug_sigprint(); + + arrayops::inplace_plus( memptr(), val, n_elem ); + + return *this; + } + + + +//! In-place subtraction of a scalar from all elements of the matrix +template +inline +Mat& +Mat::operator-=(const eT val) + { + arma_extra_debug_sigprint(); + + arrayops::inplace_minus( memptr(), val, n_elem ); + + return *this; + } + + + +//! In-place multiplication of all elements of the matrix with a scalar +template +inline +Mat& +Mat::operator*=(const eT val) + { + arma_extra_debug_sigprint(); + + arrayops::inplace_mul( memptr(), val, n_elem ); + + return *this; + } + + + +//! In-place division of all elements of the matrix with a scalar +template +inline +Mat& +Mat::operator/=(const eT val) + { + arma_extra_debug_sigprint(); + + arrayops::inplace_div( memptr(), val, n_elem ); + + return *this; + } + + + +//! construct a matrix from a given matrix +template +inline +Mat::Mat(const Mat& in_mat) + : n_rows(in_mat.n_rows) + , n_cols(in_mat.n_cols) + , n_elem(in_mat.n_elem) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint(arma_str::format("this = %x in_mat = %x") % this % &in_mat); + + init_cold(); + + arrayops::copy( memptr(), in_mat.mem, in_mat.n_elem ); + } + + + +//! construct a matrix from a given matrix +template +inline +Mat& +Mat::operator=(const Mat& in_mat) + { + arma_extra_debug_sigprint(arma_str::format("this = %x in_mat = %x") % this % &in_mat); + + if(this != &in_mat) + { + init_warm(in_mat.n_rows, in_mat.n_cols); + + arrayops::copy( memptr(), in_mat.mem, in_mat.n_elem ); + } + + return *this; + } + + + +template +inline +void +Mat::init(const std::initializer_list& list) + { + arma_extra_debug_sigprint(); + + const uword N = uword(list.size()); + + set_size(1, N); + + if(N > 0) { arrayops::copy( memptr(), list.begin(), N ); } + } + + + +template +inline +void +Mat::init(const std::initializer_list< std::initializer_list >& list) + { + arma_extra_debug_sigprint(); + + uword x_n_rows = uword(list.size()); + uword x_n_cols = 0; + + auto it = list.begin(); + auto it_end = list.end(); + + for(; it != it_end; ++it) { x_n_cols = (std::max)(x_n_cols, uword((*it).size())); } + + Mat& t = (*this); + + if(t.mem_state == 3) + { + arma_debug_check( ((x_n_rows != t.n_rows) || (x_n_cols != t.n_cols)), "Mat::init(): size mismatch between fixed size matrix and initialiser list" ); + } + else + { + t.set_size(x_n_rows, x_n_cols); + } + + uword row_num = 0; + + auto row_it = list.begin(); + auto row_it_end = list.end(); + + for(; row_it != row_it_end; ++row_it) + { + uword col_num = 0; + + auto col_it = (*row_it).begin(); + auto col_it_end = (*row_it).end(); + + for(; col_it != col_it_end; ++col_it) + { + t.at(row_num, col_num) = (*col_it); + ++col_num; + } + + for(uword c=col_num; c < x_n_cols; ++c) + { + t.at(row_num, c) = eT(0); + } + + ++row_num; + } + } + + + +//! for constructing a complex matrix out of two non-complex matrices +template +template +inline +void +Mat::init + ( + const Base::pod_type, T1>& X, + const Base::pod_type, T2>& Y + ) + { + arma_extra_debug_sigprint(); + + typedef typename T1::elem_type T; + + arma_type_check(( is_cx::no )); //!< compile-time abort if eT is not std::complex + arma_type_check(( is_cx< T>::yes )); //!< compile-time abort if T is std::complex + + arma_type_check(( is_same_type< std::complex, eT >::no )); //!< compile-time abort if types are not compatible + + const Proxy PX(X.get_ref()); + const Proxy PY(Y.get_ref()); + + arma_debug_assert_same_size(PX, PY, "Mat()"); + + const uword local_n_rows = PX.get_n_rows(); + const uword local_n_cols = PX.get_n_cols(); + + init_warm(local_n_rows, local_n_cols); + + eT* out_mem = (*this).memptr(); + + const bool use_at = ( Proxy::use_at || Proxy::use_at ); + + if(use_at == false) + { + typedef typename Proxy::ea_type ea_type1; + typedef typename Proxy::ea_type ea_type2; + + const uword N = n_elem; + + ea_type1 A = PX.get_ea(); + ea_type2 B = PY.get_ea(); + + for(uword ii=0; ii < N; ++ii) + { + out_mem[ii] = std::complex(A[ii], B[ii]); + } + } + else + { + for(uword ucol=0; ucol < local_n_cols; ++ucol) + for(uword urow=0; urow < local_n_rows; ++urow) + { + *out_mem = std::complex(PX.at(urow,ucol), PY.at(urow,ucol)); + out_mem++; + } + } + } + + + +//! swap the contents of this matrix, denoted as matrix A, with given matrix B +template +inline +void +Mat::swap(Mat& B) + { + Mat& A = (*this); + + arma_extra_debug_sigprint(arma_str::format("A = %x B = %x") % &A % &B); + + bool layout_ok = false; + + if(A.vec_state == B.vec_state) + { + layout_ok = true; + } + else + { + const uhword A_vec_state = A.vec_state; + const uhword B_vec_state = B.vec_state; + + const bool A_absorbs_B = (A_vec_state == 0) || ( (A_vec_state == 1) && (B.n_cols == 1) ) || ( (A_vec_state == 2) && (B.n_rows == 1) ); + const bool B_absorbs_A = (B_vec_state == 0) || ( (B_vec_state == 1) && (A.n_cols == 1) ) || ( (B_vec_state == 2) && (A.n_rows == 1) ); + + layout_ok = A_absorbs_B && B_absorbs_A; + } + + const uhword A_mem_state = A.mem_state; + const uhword B_mem_state = B.mem_state; + + if( (A_mem_state == 0) && (B_mem_state == 0) && layout_ok ) + { + const uword A_n_elem = A.n_elem; + const uword B_n_elem = B.n_elem; + + const bool A_use_local_mem = (A.n_alloc <= arma_config::mat_prealloc); + const bool B_use_local_mem = (B.n_alloc <= arma_config::mat_prealloc); + + if( (A_use_local_mem == false) && (B_use_local_mem == false) ) + { + std::swap( access::rw(A.mem), access::rw(B.mem) ); + } + else + if( (A_use_local_mem == true) && (B_use_local_mem == true) ) + { + eT* A_mem_local = &(A.mem_local[0]); + eT* B_mem_local = &(B.mem_local[0]); + + access::rw(A.mem) = A_mem_local; + access::rw(B.mem) = B_mem_local; + + const uword N = (std::max)(A_n_elem, B_n_elem); + + for(uword ii=0; ii < N; ++ii) { std::swap( A_mem_local[ii], B_mem_local[ii] ); } + } + else + if( (A_use_local_mem == true) && (B_use_local_mem == false) ) + { + eT* A_mem_local = &(A.mem_local[0]); + eT* B_mem_local = &(B.mem_local[0]); + + arrayops::copy(B_mem_local, A_mem_local, A_n_elem); + + access::rw(A.mem) = B.mem; + access::rw(B.mem) = B_mem_local; + } + else + if( (A_use_local_mem == false) && (B_use_local_mem == true) ) + { + eT* A_mem_local = &(A.mem_local[0]); + eT* B_mem_local = &(B.mem_local[0]); + + arrayops::copy(A_mem_local, B_mem_local, B_n_elem); + + access::rw(B.mem) = A.mem; + access::rw(A.mem) = A_mem_local; + } + + std::swap( access::rw(A.n_rows), access::rw(B.n_rows) ); + std::swap( access::rw(A.n_cols), access::rw(B.n_cols) ); + std::swap( access::rw(A.n_elem), access::rw(B.n_elem) ); + std::swap( access::rw(A.n_alloc), access::rw(B.n_alloc) ); + } + else + if( (A_mem_state <= 2) && (B_mem_state <= 2) && (A.n_elem == B.n_elem) && layout_ok ) + { + std::swap( access::rw(A.n_rows), access::rw(B.n_rows) ); + std::swap( access::rw(A.n_cols), access::rw(B.n_cols) ); + + const uword N = A.n_elem; + + eT* A_mem = A.memptr(); + eT* B_mem = B.memptr(); + + for(uword ii=0; ii < N; ++ii) { std::swap(A_mem[ii], B_mem[ii]); } + } + else + if( (A.n_rows == B.n_rows) && (A.n_cols == B.n_cols) ) + { + const uword N = A.n_elem; + + eT* A_mem = A.memptr(); + eT* B_mem = B.memptr(); + + for(uword ii=0; ii < N; ++ii) { std::swap(A_mem[ii], B_mem[ii]); } + } + else + { + // generic swap to handle remaining cases + + if(A.n_elem <= B.n_elem) + { + Mat C = A; + + A.steal_mem(B); + B.steal_mem(C); + } + else + { + Mat C = B; + + B.steal_mem(A); + A.steal_mem(C); + } + } + } + + + +//! try to steal the memory from a given matrix; +//! if memory can't be stolen, copy the given matrix +template +inline +void +Mat::steal_mem(Mat& x) + { + arma_extra_debug_sigprint(); + + (*this).steal_mem(x, false); + } + + + +template +inline +void +Mat::steal_mem(Mat& x, const bool is_move) + { + arma_extra_debug_sigprint(); + + if(this == &x) { return; } + + const uword x_n_rows = x.n_rows; + const uword x_n_cols = x.n_cols; + const uword x_n_elem = x.n_elem; + const uword x_n_alloc = x.n_alloc; + const uhword x_vec_state = x.vec_state; + const uhword x_mem_state = x.mem_state; + + const uhword t_vec_state = vec_state; + const uhword t_mem_state = mem_state; + + const bool layout_ok = (t_vec_state == x_vec_state) || ((t_vec_state == 1) && (x_n_cols == 1)) || ((t_vec_state == 2) && (x_n_rows == 1)); + + if( layout_ok && (t_mem_state <= 1) && ( (x_n_alloc > arma_config::mat_prealloc) || (x_mem_state == 1) || (is_move && (x_mem_state == 2)) ) ) + { + arma_extra_debug_print("Mat::steal_mem(): stealing memory"); + + reset(); + + access::rw(n_rows) = x_n_rows; + access::rw(n_cols) = x_n_cols; + access::rw(n_elem) = x_n_elem; + access::rw(n_alloc) = x_n_alloc; + access::rw(mem_state) = x_mem_state; + access::rw(mem) = x.mem; + + access::rw(x.n_rows) = (x_vec_state == 2) ? 1 : 0; + access::rw(x.n_cols) = (x_vec_state == 1) ? 1 : 0; + access::rw(x.n_elem) = 0; + access::rw(x.n_alloc) = 0; + access::rw(x.mem_state) = 0; + access::rw(x.mem) = nullptr; + } + else + { + arma_extra_debug_print("Mat::steal_mem(): copying memory"); + + (*this).operator=(x); + + if( (is_move) && (x_mem_state == 0) && (x_n_alloc <= arma_config::mat_prealloc) ) + { + access::rw(x.n_rows) = (x_vec_state == 2) ? 1 : 0; + access::rw(x.n_cols) = (x_vec_state == 1) ? 1 : 0; + access::rw(x.n_elem) = 0; + access::rw(x.mem) = nullptr; + } + } + } + + + +template +inline +void +Mat::steal_mem_col(Mat& x, const uword max_n_rows) + { + arma_extra_debug_sigprint(); + + const uword x_n_elem = x.n_elem; + const uword x_n_alloc = x.n_alloc; + const uhword x_mem_state = x.mem_state; + + const uhword t_vec_state = vec_state; + const uhword t_mem_state = mem_state; + + const uword alt_n_rows = (std::min)(x.n_rows, max_n_rows); + + if((x_n_elem == 0) || (alt_n_rows == 0)) + { + (*this).set_size(0,1); + + return; + } + + if( (this != &x) && (t_vec_state <= 1) && (t_mem_state <= 1) && (x_mem_state <= 1) ) + { + if( (x_mem_state == 0) && ((x_n_alloc <= arma_config::mat_prealloc) || (alt_n_rows <= arma_config::mat_prealloc)) ) + { + (*this).set_size(alt_n_rows, uword(1)); + + arrayops::copy( (*this).memptr(), x.memptr(), alt_n_rows ); + } + else + { + reset(); + + access::rw(n_rows) = alt_n_rows; + access::rw(n_cols) = 1; + access::rw(n_elem) = alt_n_rows; + access::rw(n_alloc) = x_n_alloc; + access::rw(mem_state) = x_mem_state; + access::rw(mem) = x.mem; + + access::rw(x.n_rows) = 0; + access::rw(x.n_cols) = 0; + access::rw(x.n_elem) = 0; + access::rw(x.n_alloc) = 0; + access::rw(x.mem_state) = 0; + access::rw(x.mem) = nullptr; + } + } + else + { + Mat tmp(alt_n_rows, 1, arma_nozeros_indicator()); + + arrayops::copy( tmp.memptr(), x.memptr(), alt_n_rows ); + + steal_mem(tmp); + } + } + + + +//! construct a matrix from a given auxiliary array of eTs. +//! if copy_aux_mem is true, new memory is allocated and the array is copied. +//! if copy_aux_mem is false, the auxiliary array is used directly (without allocating memory and copying). +//! the default is to copy the array. + +template +inline +Mat::Mat(eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols, const bool copy_aux_mem, const bool strict) + : n_rows ( aux_n_rows ) + , n_cols ( aux_n_cols ) + , n_elem ( aux_n_rows*aux_n_cols ) + , n_alloc ( 0 ) + , vec_state( 0 ) + , mem_state( copy_aux_mem ? 0 : ( strict ? 2 : 1 ) ) + , mem ( copy_aux_mem ? nullptr : aux_mem ) + { + arma_extra_debug_sigprint_this(this); + + if(copy_aux_mem) + { + init_cold(); + + arrayops::copy( memptr(), aux_mem, n_elem ); + } + } + + + +//! construct a matrix from a given auxiliary read-only array of eTs. +//! the array is copied. +template +inline +Mat::Mat(const eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols) + : n_rows(aux_n_rows) + , n_cols(aux_n_cols) + , n_elem(aux_n_rows*aux_n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + arrayops::copy( memptr(), aux_mem, n_elem ); + } + + + +//! DANGEROUS! Construct a temporary matrix, using auxiliary memory. +//! This constructor is NOT intended for usage by user code. +//! Its sole purpose is to be used by the Cube class. + +template +inline +Mat::Mat(const char junk, const eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols) + : n_rows (aux_n_rows ) + , n_cols (aux_n_cols ) + , n_elem (aux_n_rows*aux_n_cols) + , n_alloc (0 ) + , vec_state(0 ) + , mem_state(3 ) + , mem (aux_mem ) + { + arma_extra_debug_sigprint_this(this); + + arma_ignore(junk); + } + + + +//! in-place matrix addition +template +inline +Mat& +Mat::operator+=(const Mat& m) + { + arma_extra_debug_sigprint(); + + arma_debug_assert_same_size(*this, m, "addition"); + + arrayops::inplace_plus( memptr(), m.memptr(), n_elem ); + + return *this; + } + + + +//! in-place matrix subtraction +template +inline +Mat& +Mat::operator-=(const Mat& m) + { + arma_extra_debug_sigprint(); + + arma_debug_assert_same_size(*this, m, "subtraction"); + + arrayops::inplace_minus( memptr(), m.memptr(), n_elem ); + + return *this; + } + + + +//! in-place matrix multiplication +template +inline +Mat& +Mat::operator*=(const Mat& m) + { + arma_extra_debug_sigprint(); + + glue_times::apply_inplace(*this, m); + + return *this; + } + + + +//! in-place element-wise matrix multiplication +template +inline +Mat& +Mat::operator%=(const Mat& m) + { + arma_extra_debug_sigprint(); + + arma_debug_assert_same_size(*this, m, "element-wise multiplication"); + + arrayops::inplace_mul( memptr(), m.memptr(), n_elem ); + + return *this; + } + + + +//! in-place element-wise matrix division +template +inline +Mat& +Mat::operator/=(const Mat& m) + { + arma_extra_debug_sigprint(); + + arma_debug_assert_same_size(*this, m, "element-wise division"); + + arrayops::inplace_div( memptr(), m.memptr(), n_elem ); + + return *this; + } + + + +template +template +inline +Mat::Mat(const BaseCube& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + (*this).operator=(X); + } + + + +template +template +inline +Mat& +Mat::operator=(const BaseCube& X) + { + arma_extra_debug_sigprint(); + + Mat& out = *this; + + const unwrap_cube tmp(X.get_ref()); + const Cube& in = tmp.M; + + arma_debug_assert_cube_as_mat(out, in, "copy into matrix", false); + + const uword in_n_rows = in.n_rows; + const uword in_n_cols = in.n_cols; + const uword in_n_slices = in.n_slices; + + const uword out_vec_state = out.vec_state; + + if(in_n_slices == 1) + { + out.set_size(in_n_rows, in_n_cols); + + for(uword ucol=0; ucol < in_n_cols; ++ucol) + { + arrayops::copy( out.colptr(ucol), in.slice_colptr(0, ucol), in_n_rows ); + } + } + else + { + if(out_vec_state == 0) + { + if(in_n_cols == 1) + { + out.set_size(in_n_rows, in_n_slices); + + for(uword i=0; i < in_n_slices; ++i) + { + arrayops::copy( out.colptr(i), in.slice_colptr(i, 0), in_n_rows ); + } + } + else + if(in_n_rows == 1) + { + out.set_size(in_n_cols, in_n_slices); + + for(uword slice=0; slice < in_n_slices; ++slice) + { + eT* out_colptr = out.colptr(slice); + + uword i,j; + for(i=0, j=1; j < in_n_cols; i+=2, j+=2) + { + const eT tmp_i = in.at(0, i, slice); + const eT tmp_j = in.at(0, j, slice); + + out_colptr[i] = tmp_i; + out_colptr[j] = tmp_j; + } + + if(i < in_n_cols) + { + out_colptr[i] = in.at(0, i, slice); + } + } + } + } + else + { + out.set_size(in_n_slices); + + eT* out_mem = out.memptr(); + + for(uword i=0; i +template +inline +Mat& +Mat::operator+=(const BaseCube& X) + { + arma_extra_debug_sigprint(); + + Mat& out = *this; + + const unwrap_cube tmp(X.get_ref()); + const Cube& in = tmp.M; + + arma_debug_assert_cube_as_mat(out, in, "addition", true); + + const uword in_n_rows = in.n_rows; + const uword in_n_cols = in.n_cols; + const uword in_n_slices = in.n_slices; + + const uword out_n_rows = out.n_rows; + const uword out_n_cols = out.n_cols; + const uword out_vec_state = out.vec_state; + + if(in_n_slices == 1) + { + for(uword ucol=0; ucol < in_n_cols; ++ucol) + { + arrayops::inplace_plus( out.colptr(ucol), in.slice_colptr(0, ucol), in_n_rows ); + } + } + else + { + if(out_vec_state == 0) + { + if( (in_n_rows == out_n_rows) && (in_n_cols == 1) && (in_n_slices == out_n_cols) ) + { + for(uword i=0; i < in_n_slices; ++i) + { + arrayops::inplace_plus( out.colptr(i), in.slice_colptr(i, 0), in_n_rows ); + } + } + else + if( (in_n_rows == 1) && (in_n_cols == out_n_rows) && (in_n_slices == out_n_cols) ) + { + for(uword slice=0; slice < in_n_slices; ++slice) + { + eT* out_colptr = out.colptr(slice); + + uword i,j; + for(i=0, j=1; j < in_n_cols; i+=2, j+=2) + { + const eT tmp_i = in.at(0, i, slice); + const eT tmp_j = in.at(0, j, slice); + + out_colptr[i] += tmp_i; + out_colptr[j] += tmp_j; + } + + if(i < in_n_cols) + { + out_colptr[i] += in.at(0, i, slice); + } + } + } + } + else + { + eT* out_mem = out.memptr(); + + for(uword i=0; i +template +inline +Mat& +Mat::operator-=(const BaseCube& X) + { + arma_extra_debug_sigprint(); + + Mat& out = *this; + + const unwrap_cube tmp(X.get_ref()); + const Cube& in = tmp.M; + + arma_debug_assert_cube_as_mat(out, in, "subtraction", true); + + const uword in_n_rows = in.n_rows; + const uword in_n_cols = in.n_cols; + const uword in_n_slices = in.n_slices; + + const uword out_n_rows = out.n_rows; + const uword out_n_cols = out.n_cols; + const uword out_vec_state = out.vec_state; + + if(in_n_slices == 1) + { + for(uword ucol=0; ucol < in_n_cols; ++ucol) + { + arrayops::inplace_minus( out.colptr(ucol), in.slice_colptr(0, ucol), in_n_rows ); + } + } + else + { + if(out_vec_state == 0) + { + if( (in_n_rows == out_n_rows) && (in_n_cols == 1) && (in_n_slices == out_n_cols) ) + { + for(uword i=0; i < in_n_slices; ++i) + { + arrayops::inplace_minus( out.colptr(i), in.slice_colptr(i, 0), in_n_rows ); + } + } + else + if( (in_n_rows == 1) && (in_n_cols == out_n_rows) && (in_n_slices == out_n_cols) ) + { + for(uword slice=0; slice < in_n_slices; ++slice) + { + eT* out_colptr = out.colptr(slice); + + uword i,j; + for(i=0, j=1; j < in_n_cols; i+=2, j+=2) + { + const eT tmp_i = in.at(0, i, slice); + const eT tmp_j = in.at(0, j, slice); + + out_colptr[i] -= tmp_i; + out_colptr[j] -= tmp_j; + } + + if(i < in_n_cols) + { + out_colptr[i] -= in.at(0, i, slice); + } + } + } + } + else + { + eT* out_mem = out.memptr(); + + for(uword i=0; i +template +inline +Mat& +Mat::operator*=(const BaseCube& X) + { + arma_extra_debug_sigprint(); + + const Mat B(X); + + (*this).operator*=(B); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const BaseCube& X) + { + arma_extra_debug_sigprint(); + + Mat& out = *this; + + const unwrap_cube tmp(X.get_ref()); + const Cube& in = tmp.M; + + arma_debug_assert_cube_as_mat(out, in, "element-wise multiplication", true); + + const uword in_n_rows = in.n_rows; + const uword in_n_cols = in.n_cols; + const uword in_n_slices = in.n_slices; + + const uword out_n_rows = out.n_rows; + const uword out_n_cols = out.n_cols; + const uword out_vec_state = out.vec_state; + + if(in_n_slices == 1) + { + for(uword ucol=0; ucol < in_n_cols; ++ucol) + { + arrayops::inplace_mul( out.colptr(ucol), in.slice_colptr(0, ucol), in_n_rows ); + } + } + else + { + if(out_vec_state == 0) + { + if( (in_n_rows == out_n_rows) && (in_n_cols == 1) && (in_n_slices == out_n_cols) ) + { + for(uword i=0; i < in_n_slices; ++i) + { + arrayops::inplace_mul( out.colptr(i), in.slice_colptr(i, 0), in_n_rows ); + } + } + else + if( (in_n_rows == 1) && (in_n_cols == out_n_rows) && (in_n_slices == out_n_cols) ) + { + for(uword slice=0; slice < in_n_slices; ++slice) + { + eT* out_colptr = out.colptr(slice); + + uword i,j; + for(i=0, j=1; j < in_n_cols; i+=2, j+=2) + { + const eT tmp_i = in.at(0, i, slice); + const eT tmp_j = in.at(0, j, slice); + + out_colptr[i] *= tmp_i; + out_colptr[j] *= tmp_j; + } + + if(i < in_n_cols) + { + out_colptr[i] *= in.at(0, i, slice); + } + } + } + } + else + { + eT* out_mem = out.memptr(); + + for(uword i=0; i +template +inline +Mat& +Mat::operator/=(const BaseCube& X) + { + arma_extra_debug_sigprint(); + + Mat& out = *this; + + const unwrap_cube tmp(X.get_ref()); + const Cube& in = tmp.M; + + arma_debug_assert_cube_as_mat(out, in, "element-wise division", true); + + const uword in_n_rows = in.n_rows; + const uword in_n_cols = in.n_cols; + const uword in_n_slices = in.n_slices; + + const uword out_n_rows = out.n_rows; + const uword out_n_cols = out.n_cols; + const uword out_vec_state = out.vec_state; + + if(in_n_slices == 1) + { + for(uword ucol=0; ucol < in_n_cols; ++ucol) + { + arrayops::inplace_div( out.colptr(ucol), in.slice_colptr(0, ucol), in_n_rows ); + } + } + else + { + if(out_vec_state == 0) + { + if( (in_n_rows == out_n_rows) && (in_n_cols == 1) && (in_n_slices == out_n_cols) ) + { + for(uword i=0; i < in_n_slices; ++i) + { + arrayops::inplace_div( out.colptr(i), in.slice_colptr(i, 0), in_n_rows ); + } + } + else + if( (in_n_rows == 1) && (in_n_cols == out_n_rows) && (in_n_slices == out_n_cols) ) + { + for(uword slice=0; slice < in_n_slices; ++slice) + { + eT* out_colptr = out.colptr(slice); + + uword i,j; + for(i=0, j=1; j < in_n_cols; i+=2, j+=2) + { + const eT tmp_i = in.at(0, i, slice); + const eT tmp_j = in.at(0, j, slice); + + out_colptr[i] /= tmp_i; + out_colptr[j] /= tmp_j; + } + + if(i < in_n_cols) + { + out_colptr[i] /= in.at(0, i, slice); + } + } + } + } + else + { + eT* out_mem = out.memptr(); + + for(uword i=0; i +template +inline +Mat::Mat + ( + const Base::pod_type,T1>& A, + const Base::pod_type,T2>& B + ) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init(A,B); + } + + + +template +inline +Mat::Mat(const subview& X, const bool use_colmem) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(X.n_elem) + , n_alloc(0) + , vec_state(0) + , mem_state(use_colmem ? 3 : 0) + , mem (use_colmem ? X.colptr(0) : nullptr) + { + arma_extra_debug_sigprint_this(this); + + if(use_colmem) + { + arma_extra_debug_print("Mat::Mat(): using existing memory in a submatrix"); + } + else + { + init_cold(); + + subview::extract(*this, X); + } + } + + + +//! construct a matrix from subview (eg. construct a matrix from a delayed submatrix operation) +template +inline +Mat::Mat(const subview& X) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(X.n_elem) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + subview::extract(*this, X); + } + + + +//! construct a matrix from subview (eg. construct a matrix from a delayed submatrix operation) +template +inline +Mat& +Mat::operator=(const subview& X) + { + arma_extra_debug_sigprint(); + + const bool alias = (this == &(X.m)); + + if(alias == false) + { + init_warm(X.n_rows, X.n_cols); + + subview::extract(*this, X); + } + else + { + Mat tmp(X); + + steal_mem(tmp); + } + + return *this; + } + + +//! in-place matrix addition (using a submatrix on the right-hand-side) +template +inline +Mat& +Mat::operator+=(const subview& X) + { + arma_extra_debug_sigprint(); + + subview::plus_inplace(*this, X); + + return *this; + } + + +//! in-place matrix subtraction (using a submatrix on the right-hand-side) +template +inline +Mat& +Mat::operator-=(const subview& X) + { + arma_extra_debug_sigprint(); + + subview::minus_inplace(*this, X); + + return *this; + } + + + +//! in-place matrix mutiplication (using a submatrix on the right-hand-side) +template +inline +Mat& +Mat::operator*=(const subview& X) + { + arma_extra_debug_sigprint(); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +//! in-place element-wise matrix mutiplication (using a submatrix on the right-hand-side) +template +inline +Mat& +Mat::operator%=(const subview& X) + { + arma_extra_debug_sigprint(); + + subview::schur_inplace(*this, X); + + return *this; + } + + + +//! in-place element-wise matrix division (using a submatrix on the right-hand-side) +template +inline +Mat& +Mat::operator/=(const subview& X) + { + arma_extra_debug_sigprint(); + + subview::div_inplace(*this, X); + + return *this; + } + + + +template +inline +Mat::Mat(const subview_row_strans& X) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(X.n_elem) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + X.extract(*this); + } + + + +template +inline +Mat::Mat(const subview_row_htrans& X) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(X.n_elem) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + X.extract(*this); + } + + + +template +inline +Mat::Mat(const xvec_htrans& X) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(X.n_elem) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + X.extract(*this); + } + + + +template +template +inline +Mat::Mat(const xtrans_mat& X) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(X.n_elem) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + X.extract(*this); + } + + + +//! construct a matrix from a subview_cube instance +template +inline +Mat::Mat(const subview_cube& x) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + this->operator=(x); + } + + + +//! construct a matrix from a subview_cube instance +template +inline +Mat& +Mat::operator=(const subview_cube& X) + { + arma_extra_debug_sigprint(); + + subview_cube::extract(*this, X); + + return *this; + } + + + +//! in-place matrix addition (using a single-slice subcube on the right-hand-side) +template +inline +Mat& +Mat::operator+=(const subview_cube& X) + { + arma_extra_debug_sigprint(); + + subview_cube::plus_inplace(*this, X); + + return *this; + } + + + +//! in-place matrix subtraction (using a single-slice subcube on the right-hand-side) +template +inline +Mat& +Mat::operator-=(const subview_cube& X) + { + arma_extra_debug_sigprint(); + + subview_cube::minus_inplace(*this, X); + + return *this; + } + + + +//! in-place matrix mutiplication (using a single-slice subcube on the right-hand-side) +template +inline +Mat& +Mat::operator*=(const subview_cube& X) + { + arma_extra_debug_sigprint(); + + const Mat tmp(X); + + glue_times::apply_inplace(*this, tmp); + + return *this; + } + + + +//! in-place element-wise matrix mutiplication (using a single-slice subcube on the right-hand-side) +template +inline +Mat& +Mat::operator%=(const subview_cube& X) + { + arma_extra_debug_sigprint(); + + subview_cube::schur_inplace(*this, X); + + return *this; + } + + + +//! in-place element-wise matrix division (using a single-slice subcube on the right-hand-side) +template +inline +Mat& +Mat::operator/=(const subview_cube& X) + { + arma_extra_debug_sigprint(); + + subview_cube::div_inplace(*this, X); + + return *this; + } + + + +//! construct a matrix from diagview (eg. construct a matrix from a delayed diag operation) +template +inline +Mat::Mat(const diagview& X) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(X.n_elem) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + diagview::extract(*this, X); + } + + + +//! construct a matrix from diagview (eg. construct a matrix from a delayed diag operation) +template +inline +Mat& +Mat::operator=(const diagview& X) + { + arma_extra_debug_sigprint(); + + const bool alias = (this == &(X.m)); + + if(alias == false) + { + init_warm(X.n_rows, X.n_cols); + + diagview::extract(*this, X); + } + else + { + Mat tmp(X); + + steal_mem(tmp); + } + + return *this; + } + + + +//! in-place matrix addition (using a diagview on the right-hand-side) +template +inline +Mat& +Mat::operator+=(const diagview& X) + { + arma_extra_debug_sigprint(); + + diagview::plus_inplace(*this, X); + + return *this; + } + + + +//! in-place matrix subtraction (using a diagview on the right-hand-side) +template +inline +Mat& +Mat::operator-=(const diagview& X) + { + arma_extra_debug_sigprint(); + + diagview::minus_inplace(*this, X); + + return *this; + } + + + +//! in-place matrix mutiplication (using a diagview on the right-hand-side) +template +inline +Mat& +Mat::operator*=(const diagview& X) + { + arma_extra_debug_sigprint(); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +//! in-place element-wise matrix mutiplication (using a diagview on the right-hand-side) +template +inline +Mat& +Mat::operator%=(const diagview& X) + { + arma_extra_debug_sigprint(); + + diagview::schur_inplace(*this, X); + + return *this; + } + + + +//! in-place element-wise matrix division (using a diagview on the right-hand-side) +template +inline +Mat& +Mat::operator/=(const diagview& X) + { + arma_extra_debug_sigprint(); + + diagview::div_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat::Mat(const subview_elem1& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + this->operator=(X); + } + + + +template +template +inline +Mat& +Mat::operator=(const subview_elem1& X) + { + arma_extra_debug_sigprint(); + + subview_elem1::extract(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const subview_elem1& X) + { + arma_extra_debug_sigprint(); + + subview_elem1::plus_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator-=(const subview_elem1& X) + { + arma_extra_debug_sigprint(); + + subview_elem1::minus_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator*=(const subview_elem1& X) + { + arma_extra_debug_sigprint(); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const subview_elem1& X) + { + arma_extra_debug_sigprint(); + + subview_elem1::schur_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator/=(const subview_elem1& X) + { + arma_extra_debug_sigprint(); + + subview_elem1::div_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat::Mat(const subview_elem2& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + this->operator=(X); + } + + + +template +template +inline +Mat& +Mat::operator=(const subview_elem2& X) + { + arma_extra_debug_sigprint(); + + subview_elem2::extract(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const subview_elem2& X) + { + arma_extra_debug_sigprint(); + + subview_elem2::plus_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator-=(const subview_elem2& X) + { + arma_extra_debug_sigprint(); + + subview_elem2::minus_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator*=(const subview_elem2& X) + { + arma_extra_debug_sigprint(); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const subview_elem2& X) + { + arma_extra_debug_sigprint(); + + subview_elem2::schur_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator/=(const subview_elem2& X) + { + arma_extra_debug_sigprint(); + + subview_elem2::div_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat::Mat(const SpBase& m) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + (*this).operator=(m); + } + + + +template +template +inline +Mat& +Mat::operator=(const SpBase& m) + { + arma_extra_debug_sigprint(); + + const unwrap_spmat U(m.get_ref()); + const SpMat& x = U.M; + + const uword x_n_cols = x.n_cols; + + (*this).zeros(x.n_rows, x_n_cols); + + if(x.n_nonzero == 0) { return *this; } + + const eT* x_values = x.values; + const uword* x_row_indices = x.row_indices; + const uword* x_col_ptrs = x.col_ptrs; + + for(uword x_col = 0; x_col < x_n_cols; ++x_col) + { + const uword start = x_col_ptrs[x_col ]; + const uword end = x_col_ptrs[x_col + 1]; + + for(uword i = start; i < end; ++i) + { + const uword x_row = x_row_indices[i]; + const eT x_val = x_values[i]; + + at(x_row, x_col) = x_val; + } + } + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const SpBase& m) + { + arma_extra_debug_sigprint(); + + const SpProxy p(m.get_ref()); + + arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "addition"); + + typename SpProxy::const_iterator_type it = p.begin(); + typename SpProxy::const_iterator_type it_end = p.end(); + + for(; it != it_end; ++it) { at(it.row(), it.col()) += (*it); } + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator-=(const SpBase& m) + { + arma_extra_debug_sigprint(); + + const SpProxy p(m.get_ref()); + + arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "subtraction"); + + typename SpProxy::const_iterator_type it = p.begin(); + typename SpProxy::const_iterator_type it_end = p.end(); + + for(; it != it_end; ++it) { at(it.row(), it.col()) -= (*it); } + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator*=(const SpBase& m) + { + arma_extra_debug_sigprint(); + + Mat z = (*this) * m.get_ref(); + + steal_mem(z); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const SpBase& m) + { + arma_extra_debug_sigprint(); + + const SpProxy p(m.get_ref()); + + arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise multiplication"); + + typename SpProxy::const_iterator_type it = p.begin(); + typename SpProxy::const_iterator_type it_end = p.end(); + + // We have to zero everything that isn't being used. + arrayops::fill_zeros(memptr(), (it.col() * n_rows) + it.row()); + + while(it != it_end) + { + const uword cur_loc = (it.col() * n_rows) + it.row(); + + access::rw(mem[cur_loc]) *= (*it); + + ++it; + + const uword next_loc = (it == it_end) + ? (p.get_n_cols() * n_rows) + : (it.col() * n_rows) + it.row(); + + arrayops::fill_zeros(memptr() + cur_loc + 1, (next_loc - cur_loc - 1)); + } + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator/=(const SpBase& m) + { + arma_extra_debug_sigprint(); + + // NOTE: use of this function is not advised; it is implemented only for completeness + + const SpProxy p(m.get_ref()); + + arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise division"); + + for(uword c = 0; c < n_cols; ++c) + for(uword r = 0; r < n_rows; ++r) + { + at(r, c) /= p.at(r, c); + } + + return *this; + } + + + +template +inline +Mat::Mat(const SpSubview& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + (*this).operator=(X); + } + + + +template +inline +Mat& +Mat::operator=(const SpSubview& X) + { + arma_extra_debug_sigprint(); + + (*this).zeros(X.n_rows, X.n_cols); + + if(X.n_nonzero == 0) { return *this; } + + if(X.n_rows == X.m.n_rows) + { + X.m.sync(); + + const uword sv_col_start = X.aux_col1; + const uword sv_col_end = X.aux_col1 + X.n_cols - 1; + + const eT* m_values = X.m.values; + const uword* m_row_indices = X.m.row_indices; + const uword* m_col_ptrs = X.m.col_ptrs; + + for(uword m_col = sv_col_start; m_col <= sv_col_end; ++m_col) + { + const uword m_col_adjusted = m_col - sv_col_start; + + const uword start = m_col_ptrs[m_col ]; + const uword end = m_col_ptrs[m_col + 1]; + + for(uword ii = start; ii < end; ++ii) + { + const uword m_row = m_row_indices[ii]; + const eT m_val = m_values[ii]; + + at(m_row, m_col_adjusted) = m_val; + } + } + } + else + { + typename SpSubview::const_iterator it = X.begin(); + typename SpSubview::const_iterator it_end = X.end(); + + for(; it != it_end; ++it) { at(it.row(), it.col()) = (*it); } + } + + return *this; + } + + + +template +inline +Mat::Mat(const spdiagview& X) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(X.n_elem) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + init_cold(); + + spdiagview::extract(*this, X); + } + + + +template +inline +Mat& +Mat::operator=(const spdiagview& X) + { + arma_extra_debug_sigprint(); + + init_warm(X.n_rows, X.n_cols); + + spdiagview::extract(*this, X); + + return *this; + } + + + +template +inline +Mat& +Mat::operator+=(const spdiagview& X) + { + arma_extra_debug_sigprint(); + + const Mat tmp(X); + + (*this).operator+=(tmp); + + return *this; + } + + + +template +inline +Mat& +Mat::operator-=(const spdiagview& X) + { + arma_extra_debug_sigprint(); + + const Mat tmp(X); + + (*this).operator-=(tmp); + + return *this; + } + + + +template +inline +Mat& +Mat::operator*=(const spdiagview& X) + { + arma_extra_debug_sigprint(); + + const Mat tmp(X); + + (*this).operator*=(tmp); + + return *this; + } + + + +template +inline +Mat& +Mat::operator%=(const spdiagview& X) + { + arma_extra_debug_sigprint(); + + const Mat tmp(X); + + (*this).operator%=(tmp); + + return *this; + } + + + +template +inline +Mat& +Mat::operator/=(const spdiagview& X) + { + arma_extra_debug_sigprint(); + + const Mat tmp(X); + + (*this).operator/=(tmp); + + return *this; + } + + + +template +inline +mat_injector< Mat > +Mat::operator<<(const eT val) + { + return mat_injector< Mat >(*this, val); + } + + + +template +inline +mat_injector< Mat > +Mat::operator<<(const injector_end_of_row<>& x) + { + return mat_injector< Mat >(*this, x); + } + + + +//! creation of subview (row vector) +template +arma_inline +subview_row +Mat::row(const uword row_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( row_num >= n_rows, "Mat::row(): index out of bounds" ); + + return subview_row(*this, row_num); + } + + + +//! creation of subview (row vector) +template +arma_inline +const subview_row +Mat::row(const uword row_num) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( row_num >= n_rows, "Mat::row(): index out of bounds" ); + + return subview_row(*this, row_num); + } + + + +template +inline +subview_row +Mat::operator()(const uword row_num, const span& col_span) + { + arma_extra_debug_sigprint(); + + const bool col_all = col_span.whole; + + const uword local_n_cols = n_cols; + + const uword in_col1 = col_all ? 0 : col_span.a; + const uword in_col2 = col_span.b; + const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; + + arma_debug_check_bounds + ( + (row_num >= n_rows) + || + ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) + , + "Mat::operator(): indices out of bounds or incorrectly used" + ); + + return subview_row(*this, row_num, in_col1, submat_n_cols); + } + + + +template +inline +const subview_row +Mat::operator()(const uword row_num, const span& col_span) const + { + arma_extra_debug_sigprint(); + + const bool col_all = col_span.whole; + + const uword local_n_cols = n_cols; + + const uword in_col1 = col_all ? 0 : col_span.a; + const uword in_col2 = col_span.b; + const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; + + arma_debug_check_bounds + ( + (row_num >= n_rows) + || + ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) + , + "Mat::operator(): indices out of bounds or incorrectly used" + ); + + return subview_row(*this, row_num, in_col1, submat_n_cols); + } + + + +//! creation of subview (column vector) +template +arma_inline +subview_col +Mat::col(const uword col_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( col_num >= n_cols, "Mat::col(): index out of bounds" ); + + return subview_col(*this, col_num); + } + + + +//! creation of subview (column vector) +template +arma_inline +const subview_col +Mat::col(const uword col_num) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( col_num >= n_cols, "Mat::col(): index out of bounds" ); + + return subview_col(*this, col_num); + } + + + +template +inline +subview_col +Mat::operator()(const span& row_span, const uword col_num) + { + arma_extra_debug_sigprint(); + + const bool row_all = row_span.whole; + + const uword local_n_rows = n_rows; + + const uword in_row1 = row_all ? 0 : row_span.a; + const uword in_row2 = row_span.b; + const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; + + arma_debug_check_bounds + ( + (col_num >= n_cols) + || + ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) + , + "Mat::operator(): indices out of bounds or incorrectly used" + ); + + return subview_col(*this, col_num, in_row1, submat_n_rows); + } + + + +template +inline +const subview_col +Mat::operator()(const span& row_span, const uword col_num) const + { + arma_extra_debug_sigprint(); + + const bool row_all = row_span.whole; + + const uword local_n_rows = n_rows; + + const uword in_row1 = row_all ? 0 : row_span.a; + const uword in_row2 = row_span.b; + const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; + + arma_debug_check_bounds + ( + (col_num >= n_cols) + || + ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) + , + "Mat::operator(): indices out of bounds or incorrectly used" + ); + + return subview_col(*this, col_num, in_row1, submat_n_rows); + } + + + +//! create a Col object which uses memory from an existing matrix object. +//! this approach is currently not alias safe +//! and does not take into account that the parent matrix object could be deleted. +//! if deleted memory is accessed by the created Col object, +//! it will cause memory corruption and/or a crash +template +inline +Col +Mat::unsafe_col(const uword col_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( col_num >= n_cols, "Mat::unsafe_col(): index out of bounds" ); + + return Col(colptr(col_num), n_rows, false, true); + } + + + +//! create a Col object which uses memory from an existing matrix object. +//! this approach is currently not alias safe +//! and does not take into account that the parent matrix object could be deleted. +//! if deleted memory is accessed by the created Col object, +//! it will cause memory corruption and/or a crash +template +inline +const Col +Mat::unsafe_col(const uword col_num) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( col_num >= n_cols, "Mat::unsafe_col(): index out of bounds" ); + + typedef const Col out_type; + + return out_type(const_cast(colptr(col_num)), n_rows, false, true); + } + + + +//! creation of subview (submatrix comprised of specified row vectors) +template +arma_inline +subview +Mat::rows(const uword in_row1, const uword in_row2) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds + ( + (in_row1 > in_row2) || (in_row2 >= n_rows), + "Mat::rows(): indices out of bounds or incorrectly used" + ); + + const uword subview_n_rows = in_row2 - in_row1 + 1; + + return subview(*this, in_row1, 0, subview_n_rows, n_cols ); + } + + + +//! creation of subview (submatrix comprised of specified row vectors) +template +arma_inline +const subview +Mat::rows(const uword in_row1, const uword in_row2) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds + ( + (in_row1 > in_row2) || (in_row2 >= n_rows), + "Mat::rows(): indices out of bounds or incorrectly used" + ); + + const uword subview_n_rows = in_row2 - in_row1 + 1; + + return subview(*this, in_row1, 0, subview_n_rows, n_cols ); + } + + + +//! creation of subview (submatrix comprised of specified column vectors) +template +arma_inline +subview_cols +Mat::cols(const uword in_col1, const uword in_col2) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds + ( + (in_col1 > in_col2) || (in_col2 >= n_cols), + "Mat::cols(): indices out of bounds or incorrectly used" + ); + + const uword subview_n_cols = in_col2 - in_col1 + 1; + + return subview_cols(*this, in_col1, subview_n_cols); + } + + + +//! creation of subview (submatrix comprised of specified column vectors) +template +arma_inline +const subview_cols +Mat::cols(const uword in_col1, const uword in_col2) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds + ( + (in_col1 > in_col2) || (in_col2 >= n_cols), + "Mat::cols(): indices out of bounds or incorrectly used" + ); + + const uword subview_n_cols = in_col2 - in_col1 + 1; + + return subview_cols(*this, in_col1, subview_n_cols); + } + + + +//! creation of subview (submatrix comprised of specified row vectors) +template +inline +subview +Mat::rows(const span& row_span) + { + arma_extra_debug_sigprint(); + + const bool row_all = row_span.whole; + + const uword local_n_rows = n_rows; + + const uword in_row1 = row_all ? 0 : row_span.a; + const uword in_row2 = row_span.b; + const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; + + arma_debug_check_bounds + ( + ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) + , + "Mat::rows(): indices out of bounds or incorrectly used" + ); + + return subview(*this, in_row1, 0, submat_n_rows, n_cols); + } + + + +//! creation of subview (submatrix comprised of specified row vectors) +template +inline +const subview +Mat::rows(const span& row_span) const + { + arma_extra_debug_sigprint(); + + const bool row_all = row_span.whole; + + const uword local_n_rows = n_rows; + + const uword in_row1 = row_all ? 0 : row_span.a; + const uword in_row2 = row_span.b; + const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; + + arma_debug_check_bounds + ( + ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) + , + "Mat::rows(): indices out of bounds or incorrectly used" + ); + + return subview(*this, in_row1, 0, submat_n_rows, n_cols); + } + + + +//! creation of subview (submatrix comprised of specified column vectors) +template +arma_inline +subview_cols +Mat::cols(const span& col_span) + { + arma_extra_debug_sigprint(); + + const bool col_all = col_span.whole; + + const uword local_n_cols = n_cols; + + const uword in_col1 = col_all ? 0 : col_span.a; + const uword in_col2 = col_span.b; + const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; + + arma_debug_check_bounds + ( + ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) + , + "Mat::cols(): indices out of bounds or incorrectly used" + ); + + return subview_cols(*this, in_col1, submat_n_cols); + } + + + +//! creation of subview (submatrix comprised of specified column vectors) +template +arma_inline +const subview_cols +Mat::cols(const span& col_span) const + { + arma_extra_debug_sigprint(); + + const bool col_all = col_span.whole; + + const uword local_n_cols = n_cols; + + const uword in_col1 = col_all ? 0 : col_span.a; + const uword in_col2 = col_span.b; + const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; + + arma_debug_check_bounds + ( + ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) + , + "Mat::cols(): indices out of bounds or incorrectly used" + ); + + return subview_cols(*this, in_col1, submat_n_cols); + } + + + +//! creation of subview (submatrix) +template +arma_inline +subview +Mat::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds + ( + (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols), + "Mat::submat(): indices out of bounds or incorrectly used" + ); + + const uword subview_n_rows = in_row2 - in_row1 + 1; + const uword subview_n_cols = in_col2 - in_col1 + 1; + + return subview(*this, in_row1, in_col1, subview_n_rows, subview_n_cols); + } + + + +//! creation of subview (generic submatrix) +template +arma_inline +const subview +Mat::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds + ( + (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols), + "Mat::submat(): indices out of bounds or incorrectly used" + ); + + const uword subview_n_rows = in_row2 - in_row1 + 1; + const uword subview_n_cols = in_col2 - in_col1 + 1; + + return subview(*this, in_row1, in_col1, subview_n_rows, subview_n_cols); + } + + + +//! creation of subview (submatrix) +template +arma_inline +subview +Mat::submat(const uword in_row1, const uword in_col1, const SizeMat& s) + { + arma_extra_debug_sigprint(); + + const uword l_n_rows = n_rows; + const uword l_n_cols = n_cols; + + const uword s_n_rows = s.n_rows; + const uword s_n_cols = s.n_cols; + + arma_debug_check_bounds + ( + ((in_row1 >= l_n_rows) || (in_col1 >= l_n_cols) || ((in_row1 + s_n_rows) > l_n_rows) || ((in_col1 + s_n_cols) > l_n_cols)), + "Mat::submat(): indices or size out of bounds" + ); + + return subview(*this, in_row1, in_col1, s_n_rows, s_n_cols); + } + + + +//! creation of subview (submatrix) +template +arma_inline +const subview +Mat::submat(const uword in_row1, const uword in_col1, const SizeMat& s) const + { + arma_extra_debug_sigprint(); + + const uword l_n_rows = n_rows; + const uword l_n_cols = n_cols; + + const uword s_n_rows = s.n_rows; + const uword s_n_cols = s.n_cols; + + arma_debug_check_bounds + ( + ((in_row1 >= l_n_rows) || (in_col1 >= l_n_cols) || ((in_row1 + s_n_rows) > l_n_rows) || ((in_col1 + s_n_cols) > l_n_cols)), + "Mat::submat(): indices or size out of bounds" + ); + + return subview(*this, in_row1, in_col1, s_n_rows, s_n_cols); + } + + + +//! creation of subview (submatrix) +template +inline +subview +Mat::submat(const span& row_span, const span& col_span) + { + arma_extra_debug_sigprint(); + + const bool row_all = row_span.whole; + const bool col_all = col_span.whole; + + const uword local_n_rows = n_rows; + const uword local_n_cols = n_cols; + + const uword in_row1 = row_all ? 0 : row_span.a; + const uword in_row2 = row_span.b; + const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; + + const uword in_col1 = col_all ? 0 : col_span.a; + const uword in_col2 = col_span.b; + const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; + + arma_debug_check_bounds + ( + ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) + || + ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) + , + "Mat::submat(): indices out of bounds or incorrectly used" + ); + + return subview(*this, in_row1, in_col1, submat_n_rows, submat_n_cols); + } + + + +//! creation of subview (generic submatrix) +template +inline +const subview +Mat::submat(const span& row_span, const span& col_span) const + { + arma_extra_debug_sigprint(); + + const bool row_all = row_span.whole; + const bool col_all = col_span.whole; + + const uword local_n_rows = n_rows; + const uword local_n_cols = n_cols; + + const uword in_row1 = row_all ? 0 : row_span.a; + const uword in_row2 = row_span.b; + const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; + + const uword in_col1 = col_all ? 0 : col_span.a; + const uword in_col2 = col_span.b; + const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; + + arma_debug_check_bounds + ( + ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) + || + ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) + , + "Mat::submat(): indices out of bounds or incorrectly used" + ); + + return subview(*this, in_row1, in_col1, submat_n_rows, submat_n_cols); + } + + + +template +inline +subview +Mat::operator()(const span& row_span, const span& col_span) + { + arma_extra_debug_sigprint(); + + return (*this).submat(row_span, col_span); + } + + + +template +inline +const subview +Mat::operator()(const span& row_span, const span& col_span) const + { + arma_extra_debug_sigprint(); + + return (*this).submat(row_span, col_span); + } + + + +template +inline +subview +Mat::operator()(const uword in_row1, const uword in_col1, const SizeMat& s) + { + arma_extra_debug_sigprint(); + + return (*this).submat(in_row1, in_col1, s); + } + + + +template +inline +const subview +Mat::operator()(const uword in_row1, const uword in_col1, const SizeMat& s) const + { + arma_extra_debug_sigprint(); + + return (*this).submat(in_row1, in_col1, s); + } + + + +template +inline +subview +Mat::head_rows(const uword N) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (N > n_rows), "Mat::head_rows(): size out of bounds" ); + + return subview(*this, 0, 0, N, n_cols); + } + + + +template +inline +const subview +Mat::head_rows(const uword N) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (N > n_rows), "Mat::head_rows(): size out of bounds" ); + + return subview(*this, 0, 0, N, n_cols); + } + + + +template +inline +subview +Mat::tail_rows(const uword N) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (N > n_rows), "Mat::tail_rows(): size out of bounds" ); + + const uword start_row = n_rows - N; + + return subview(*this, start_row, 0, N, n_cols); + } + + + +template +inline +const subview +Mat::tail_rows(const uword N) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (N > n_rows), "Mat::tail_rows(): size out of bounds" ); + + const uword start_row = n_rows - N; + + return subview(*this, start_row, 0, N, n_cols); + } + + + +template +inline +subview_cols +Mat::head_cols(const uword N) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (N > n_cols), "Mat::head_cols(): size out of bounds" ); + + return subview_cols(*this, 0, N); + } + + + +template +inline +const subview_cols +Mat::head_cols(const uword N) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (N > n_cols), "Mat::head_cols(): size out of bounds" ); + + return subview_cols(*this, 0, N); + } + + + +template +inline +subview_cols +Mat::tail_cols(const uword N) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (N > n_cols), "Mat::tail_cols(): size out of bounds" ); + + const uword start_col = n_cols - N; + + return subview_cols(*this, start_col, N); + } + + + +template +inline +const subview_cols +Mat::tail_cols(const uword N) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (N > n_cols), "Mat::tail_cols(): size out of bounds" ); + + const uword start_col = n_cols - N; + + return subview_cols(*this, start_col, N); + } + + + +template +template +arma_inline +subview_elem1 +Mat::elem(const Base& a) + { + arma_extra_debug_sigprint(); + + return subview_elem1(*this, a); + } + + + +template +template +arma_inline +const subview_elem1 +Mat::elem(const Base& a) const + { + arma_extra_debug_sigprint(); + + return subview_elem1(*this, a); + } + + + +template +template +arma_inline +subview_elem1 +Mat::operator()(const Base& a) + { + arma_extra_debug_sigprint(); + + return subview_elem1(*this, a); + } + + + +template +template +arma_inline +const subview_elem1 +Mat::operator()(const Base& a) const + { + arma_extra_debug_sigprint(); + + return subview_elem1(*this, a); + } + + + +template +template +arma_inline +subview_elem2 +Mat::elem(const Base& ri, const Base& ci) + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ri, ci, false, false); + } + + + +template +template +arma_inline +const subview_elem2 +Mat::elem(const Base& ri, const Base& ci) const + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ri, ci, false, false); + } + + + +template +template +arma_inline +subview_elem2 +Mat::submat(const Base& ri, const Base& ci) + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ri, ci, false, false); + } + + + +template +template +arma_inline +const subview_elem2 +Mat::submat(const Base& ri, const Base& ci) const + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ri, ci, false, false); + } + + + +template +template +arma_inline +subview_elem2 +Mat::operator()(const Base& ri, const Base& ci) + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ri, ci, false, false); + } + + + +template +template +arma_inline +const subview_elem2 +Mat::operator()(const Base& ri, const Base& ci) const + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ri, ci, false, false); + } + + + +template +template +arma_inline +subview_elem2 +Mat::rows(const Base& ri) + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ri, ri, false, true); + } + + + +template +template +arma_inline +const subview_elem2 +Mat::rows(const Base& ri) const + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ri, ri, false, true); + } + + + +template +template +arma_inline +subview_elem2 +Mat::cols(const Base& ci) + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ci, ci, true, false); + } + + + +template +template +arma_inline +const subview_elem2 +Mat::cols(const Base& ci) const + { + arma_extra_debug_sigprint(); + + return subview_elem2(*this, ci, ci, true, false); + } + + + +template +arma_inline +subview_each1< Mat, 0 > +Mat::each_col() + { + arma_extra_debug_sigprint(); + + return subview_each1< Mat, 0>(*this); + } + + + +template +arma_inline +subview_each1< Mat, 1 > +Mat::each_row() + { + arma_extra_debug_sigprint(); + + return subview_each1< Mat, 1>(*this); + } + + + +template +arma_inline +const subview_each1< Mat, 0 > +Mat::each_col() const + { + arma_extra_debug_sigprint(); + + return subview_each1< Mat, 0>(*this); + } + + + +template +arma_inline +const subview_each1< Mat, 1 > +Mat::each_row() const + { + arma_extra_debug_sigprint(); + + return subview_each1< Mat, 1>(*this); + } + + + +template +template +inline +subview_each2< Mat, 0, T1 > +Mat::each_col(const Base& indices) + { + arma_extra_debug_sigprint(); + + return subview_each2< Mat, 0, T1 >(*this, indices); + } + + + +template +template +inline +subview_each2< Mat, 1, T1 > +Mat::each_row(const Base& indices) + { + arma_extra_debug_sigprint(); + + return subview_each2< Mat, 1, T1 >(*this, indices); + } + + + +template +template +inline +const subview_each2< Mat, 0, T1 > +Mat::each_col(const Base& indices) const + { + arma_extra_debug_sigprint(); + + return subview_each2< Mat, 0, T1 >(*this, indices); + } + + + +template +template +inline +const subview_each2< Mat, 1, T1 > +Mat::each_row(const Base& indices) const + { + arma_extra_debug_sigprint(); + + return subview_each2< Mat, 1, T1 >(*this, indices); + } + + + +//! apply a lambda function to each column, where each column is interpreted as a column vector +template +inline +Mat& +Mat::each_col(const std::function< void(Col&) >& F) + { + arma_extra_debug_sigprint(); + + for(uword ii=0; ii < n_cols; ++ii) + { + Col tmp(colptr(ii), n_rows, false, true); + F(tmp); + } + + return *this; + } + + + +template +inline +const Mat& +Mat::each_col(const std::function< void(const Col&) >& F) const + { + arma_extra_debug_sigprint(); + + for(uword ii=0; ii < n_cols; ++ii) + { + const Col tmp(const_cast(colptr(ii)), n_rows, false, true); + F(tmp); + } + + return *this; + } + + + +//! apply a lambda function to each row, where each row is interpreted as a row vector +template +inline +Mat& +Mat::each_row(const std::function< void(Row&) >& F) + { + arma_extra_debug_sigprint(); + + podarray array1(n_cols); + podarray array2(n_cols); + + Row tmp1( array1.memptr(), n_cols, false, true ); + Row tmp2( array2.memptr(), n_cols, false, true ); + + eT* tmp1_mem = tmp1.memptr(); + eT* tmp2_mem = tmp2.memptr(); + + uword ii, jj; + + for(ii=0, jj=1; jj < n_rows; ii+=2, jj+=2) + { + for(uword col_id = 0; col_id < n_cols; ++col_id) + { + const eT* col_mem = colptr(col_id); + + tmp1_mem[col_id] = col_mem[ii]; + tmp2_mem[col_id] = col_mem[jj]; + } + + F(tmp1); + F(tmp2); + + for(uword col_id = 0; col_id < n_cols; ++col_id) + { + eT* col_mem = colptr(col_id); + + col_mem[ii] = tmp1_mem[col_id]; + col_mem[jj] = tmp2_mem[col_id]; + } + } + + if(ii < n_rows) + { + tmp1 = (*this).row(ii); + + F(tmp1); + + (*this).row(ii) = tmp1; + } + + return *this; + } + + + +template +inline +const Mat& +Mat::each_row(const std::function< void(const Row&) >& F) const + { + arma_extra_debug_sigprint(); + + podarray array1(n_cols); + podarray array2(n_cols); + + Row tmp1( array1.memptr(), n_cols, false, true ); + Row tmp2( array2.memptr(), n_cols, false, true ); + + eT* tmp1_mem = tmp1.memptr(); + eT* tmp2_mem = tmp2.memptr(); + + uword ii, jj; + + for(ii=0, jj=1; jj < n_rows; ii+=2, jj+=2) + { + for(uword col_id = 0; col_id < n_cols; ++col_id) + { + const eT* col_mem = colptr(col_id); + + tmp1_mem[col_id] = col_mem[ii]; + tmp2_mem[col_id] = col_mem[jj]; + } + + F(tmp1); + F(tmp2); + } + + if(ii < n_rows) + { + tmp1 = (*this).row(ii); + + F(tmp1); + } + + return *this; + } + + + +//! creation of diagview (diagonal) +template +arma_inline +diagview +Mat::diag(const sword in_id) + { + arma_extra_debug_sigprint(); + + const uword row_offset = (in_id < 0) ? uword(-in_id) : 0; + const uword col_offset = (in_id > 0) ? uword( in_id) : 0; + + arma_debug_check_bounds + ( + ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)), + "Mat::diag(): requested diagonal out of bounds" + ); + + const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset); + + return diagview(*this, row_offset, col_offset, len); + } + + + +//! creation of diagview (diagonal) +template +arma_inline +const diagview +Mat::diag(const sword in_id) const + { + arma_extra_debug_sigprint(); + + const uword row_offset = uword( (in_id < 0) ? -in_id : 0 ); + const uword col_offset = uword( (in_id > 0) ? in_id : 0 ); + + arma_debug_check_bounds + ( + ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)), + "Mat::diag(): requested diagonal out of bounds" + ); + + const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset); + + return diagview(*this, row_offset, col_offset, len); + } + + + +template +inline +void +Mat::swap_rows(const uword in_row1, const uword in_row2) + { + arma_extra_debug_sigprint(); + + const uword local_n_rows = n_rows; + const uword local_n_cols = n_cols; + + arma_debug_check_bounds + ( + (in_row1 >= local_n_rows) || (in_row2 >= local_n_rows), + "Mat::swap_rows(): index out of bounds" + ); + + if(n_elem > 0) + { + for(uword ucol=0; ucol < local_n_cols; ++ucol) + { + const uword offset = ucol * local_n_rows; + const uword pos1 = in_row1 + offset; + const uword pos2 = in_row2 + offset; + + std::swap( access::rw(mem[pos1]), access::rw(mem[pos2]) ); + } + } + } + + + +template +inline +void +Mat::swap_cols(const uword in_colA, const uword in_colB) + { + arma_extra_debug_sigprint(); + + const uword local_n_rows = n_rows; + const uword local_n_cols = n_cols; + + arma_debug_check_bounds + ( + (in_colA >= local_n_cols) || (in_colB >= local_n_cols), + "Mat::swap_cols(): index out of bounds" + ); + + if(n_elem > 0) + { + eT* ptrA = colptr(in_colA); + eT* ptrB = colptr(in_colB); + + eT tmp_i; + eT tmp_j; + + uword iq,jq; + for(iq=0, jq=1; jq < local_n_rows; iq+=2, jq+=2) + { + tmp_i = ptrA[iq]; + tmp_j = ptrA[jq]; + + ptrA[iq] = ptrB[iq]; + ptrA[jq] = ptrB[jq]; + + ptrB[iq] = tmp_i; + ptrB[jq] = tmp_j; + } + + if(iq < local_n_rows) + { + std::swap( ptrA[iq], ptrB[iq] ); + } + } + } + + + +//! remove specified row +template +inline +void +Mat::shed_row(const uword row_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( row_num >= n_rows, "Mat::shed_row(): index out of bounds" ); + + shed_rows(row_num, row_num); + } + + + +//! remove specified column +template +inline +void +Mat::shed_col(const uword col_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( col_num >= n_cols, "Mat::shed_col(): index out of bounds" ); + + shed_cols(col_num, col_num); + } + + + +//! remove specified rows +template +inline +void +Mat::shed_rows(const uword in_row1, const uword in_row2) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds + ( + (in_row1 > in_row2) || (in_row2 >= n_rows), + "Mat::shed_rows(): indices out of bounds or incorrectly used" + ); + + const uword n_keep_front = in_row1; + const uword n_keep_back = n_rows - (in_row2 + 1); + + Mat X(n_keep_front + n_keep_back, n_cols, arma_nozeros_indicator()); + + if(n_keep_front > 0) + { + X.rows( 0, (n_keep_front-1) ) = rows( 0, (in_row1-1) ); + } + + if(n_keep_back > 0) + { + X.rows( n_keep_front, (n_keep_front+n_keep_back-1) ) = rows( (in_row2+1), (n_rows-1) ); + } + + steal_mem(X); + } + + + +//! remove specified columns +template +inline +void +Mat::shed_cols(const uword in_col1, const uword in_col2) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds + ( + (in_col1 > in_col2) || (in_col2 >= n_cols), + "Mat::shed_cols(): indices out of bounds or incorrectly used" + ); + + const uword n_keep_front = in_col1; + const uword n_keep_back = n_cols - (in_col2 + 1); + + Mat X(n_rows, n_keep_front + n_keep_back, arma_nozeros_indicator()); + + if(n_keep_front > 0) + { + X.cols( 0, (n_keep_front-1) ) = cols( 0, (in_col1-1) ); + } + + if(n_keep_back > 0) + { + X.cols( n_keep_front, (n_keep_front+n_keep_back-1) ) = cols( (in_col2+1), (n_cols-1) ); + } + + steal_mem(X); + } + + + +//! remove specified rows +template +template +inline +void +Mat::shed_rows(const Base& indices) + { + arma_extra_debug_sigprint(); + + const unwrap_check_mixed U(indices.get_ref(), *this); + const Mat& tmp1 = U.M; + + arma_debug_check( ((tmp1.is_vec() == false) && (tmp1.is_empty() == false)), "Mat::shed_rows(): list of indices must be a vector" ); + + if(tmp1.is_empty()) { return; } + + const Col tmp2(const_cast(tmp1.memptr()), tmp1.n_elem, false, false); + + const Col& rows_to_shed = (tmp2.is_sorted("strictascend") == false) + ? Col(unique(tmp2)) + : Col(const_cast(tmp2.memptr()), tmp2.n_elem, false, false); + + const uword* rows_to_shed_mem = rows_to_shed.memptr(); + const uword N = rows_to_shed.n_elem; + + if(arma_config::debug) + { + for(uword i=0; i= n_rows), "Mat::shed_rows(): indices out of bounds" ); + } + } + + Col tmp3(n_rows, arma_nozeros_indicator()); + + uword* tmp3_mem = tmp3.memptr(); + + uword i = 0; + uword count = 0; + + for(uword j=0; j < n_rows; ++j) + { + if(i < N) + { + if( j != rows_to_shed_mem[i] ) + { + tmp3_mem[count] = j; + ++count; + } + else + { + ++i; + } + } + else + { + tmp3_mem[count] = j; + ++count; + } + } + + const Col rows_to_keep(tmp3.memptr(), count, false, false); + + Mat X = (*this).rows(rows_to_keep); + + steal_mem(X); + } + + + +//! remove specified columns +template +template +inline +void +Mat::shed_cols(const Base& indices) + { + arma_extra_debug_sigprint(); + + const unwrap_check_mixed U(indices.get_ref(), *this); + const Mat& tmp1 = U.M; + + arma_debug_check( ((tmp1.is_vec() == false) && (tmp1.is_empty() == false)), "Mat::shed_cols(): list of indices must be a vector" ); + + if(tmp1.is_empty()) { return; } + + const Col tmp2(const_cast(tmp1.memptr()), tmp1.n_elem, false, false); + + const Col& cols_to_shed = (tmp2.is_sorted("strictascend") == false) + ? Col(unique(tmp2)) + : Col(const_cast(tmp2.memptr()), tmp2.n_elem, false, false); + + const uword* cols_to_shed_mem = cols_to_shed.memptr(); + const uword N = cols_to_shed.n_elem; + + if(arma_config::debug) + { + for(uword i=0; i= n_cols), "Mat::shed_cols(): indices out of bounds" ); + } + } + + Col tmp3(n_cols, arma_nozeros_indicator()); + + uword* tmp3_mem = tmp3.memptr(); + + uword i = 0; + uword count = 0; + + for(uword j=0; j < n_cols; ++j) + { + if(i < N) + { + if( j != cols_to_shed_mem[i] ) + { + tmp3_mem[count] = j; + ++count; + } + else + { + ++i; + } + } + else + { + tmp3_mem[count] = j; + ++count; + } + } + + const Col cols_to_keep(tmp3.memptr(), count, false, false); + + Mat X = (*this).cols(cols_to_keep); + + steal_mem(X); + } + + + +template +inline +void +Mat::insert_rows(const uword row_num, const uword N, const bool set_to_zero) + { + arma_extra_debug_sigprint(); + + arma_ignore(set_to_zero); + + (*this).insert_rows(row_num, N); + } + + + +template +inline +void +Mat::insert_rows(const uword row_num, const uword N) + { + arma_extra_debug_sigprint(); + + const uword t_n_rows = n_rows; + const uword t_n_cols = n_cols; + + const uword A_n_rows = row_num; + const uword B_n_rows = t_n_rows - row_num; + + // insertion at row_num == n_rows is in effect an append operation + arma_debug_check_bounds( (row_num > t_n_rows), "Mat::insert_rows(): index out of bounds" ); + + if(N == 0) { return; } + + Mat out(t_n_rows + N, t_n_cols, arma_nozeros_indicator()); + + if(A_n_rows > 0) + { + out.rows(0, A_n_rows-1) = rows(0, A_n_rows-1); + } + + if(B_n_rows > 0) + { + out.rows(row_num + N, t_n_rows + N - 1) = rows(row_num, t_n_rows-1); + } + + out.rows(row_num, row_num + N - 1).zeros(); + + steal_mem(out); + } + + + +template +inline +void +Mat::insert_cols(const uword col_num, const uword N, const bool set_to_zero) + { + arma_extra_debug_sigprint(); + + arma_ignore(set_to_zero); + + (*this).insert_cols(col_num, N); + } + + + +template +inline +void +Mat::insert_cols(const uword col_num, const uword N) + { + arma_extra_debug_sigprint(); + + const uword t_n_rows = n_rows; + const uword t_n_cols = n_cols; + + const uword A_n_cols = col_num; + const uword B_n_cols = t_n_cols - col_num; + + // insertion at col_num == n_cols is in effect an append operation + arma_debug_check_bounds( (col_num > t_n_cols), "Mat::insert_cols(): index out of bounds" ); + + if(N == 0) { return; } + + Mat out(t_n_rows, t_n_cols + N, arma_nozeros_indicator()); + + if(A_n_cols > 0) + { + out.cols(0, A_n_cols-1) = cols(0, A_n_cols-1); + } + + if(B_n_cols > 0) + { + out.cols(col_num + N, t_n_cols + N - 1) = cols(col_num, t_n_cols-1); + } + + out.cols(col_num, col_num + N - 1).zeros(); + + steal_mem(out); + } + + + +//! insert the given object at the specified row position; +//! the given object must have the same number of columns as the matrix +template +template +inline +void +Mat::insert_rows(const uword row_num, const Base& X) + { + arma_extra_debug_sigprint(); + + const unwrap tmp(X.get_ref()); + const Mat& C = tmp.M; + + const uword C_n_rows = C.n_rows; + const uword C_n_cols = C.n_cols; + + const uword t_n_rows = n_rows; + const uword t_n_cols = n_cols; + + const uword A_n_rows = row_num; + const uword B_n_rows = t_n_rows - row_num; + + bool err_state = false; + char* err_msg = nullptr; + + const char* error_message_1 = "Mat::insert_rows(): index out of bounds"; + const char* error_message_2 = "Mat::insert_rows(): given object has an incompatible number of columns"; + + // insertion at row_num == n_rows is in effect an append operation + + arma_debug_set_error + ( + err_state, + err_msg, + (row_num > t_n_rows), + error_message_1 + ); + + arma_debug_set_error + ( + err_state, + err_msg, + ( (C_n_cols != t_n_cols) && ( (t_n_rows > 0) || (t_n_cols > 0) ) && ( (C_n_rows > 0) || (C_n_cols > 0) ) ), + error_message_2 + ); + + arma_debug_check_bounds(err_state, err_msg); + + if(C_n_rows > 0) + { + Mat out( t_n_rows + C_n_rows, (std::max)(t_n_cols, C_n_cols), arma_nozeros_indicator() ); + + if(t_n_cols > 0) + { + if(A_n_rows > 0) + { + out.rows(0, A_n_rows-1) = rows(0, A_n_rows-1); + } + + if( (t_n_cols > 0) && (B_n_rows > 0) ) + { + out.rows(row_num + C_n_rows, t_n_rows + C_n_rows - 1) = rows(row_num, t_n_rows - 1); + } + } + + if(C_n_cols > 0) + { + out.rows(row_num, row_num + C_n_rows - 1) = C; + } + + steal_mem(out); + } + } + + + +//! insert the given object at the specified column position; +//! the given object must have the same number of rows as the matrix +template +template +inline +void +Mat::insert_cols(const uword col_num, const Base& X) + { + arma_extra_debug_sigprint(); + + const unwrap tmp(X.get_ref()); + const Mat& C = tmp.M; + + const uword C_n_rows = C.n_rows; + const uword C_n_cols = C.n_cols; + + const uword t_n_rows = n_rows; + const uword t_n_cols = n_cols; + + const uword A_n_cols = col_num; + const uword B_n_cols = t_n_cols - col_num; + + bool err_state = false; + char* err_msg = nullptr; + + const char* error_message_1 = "Mat::insert_cols(): index out of bounds"; + const char* error_message_2 = "Mat::insert_cols(): given object has an incompatible number of rows"; + + // insertion at col_num == n_cols is in effect an append operation + + arma_debug_set_error + ( + err_state, + err_msg, + (col_num > t_n_cols), + error_message_1 + ); + + arma_debug_set_error + ( + err_state, + err_msg, + ( (C_n_rows != t_n_rows) && ( (t_n_rows > 0) || (t_n_cols > 0) ) && ( (C_n_rows > 0) || (C_n_cols > 0) ) ), + error_message_2 + ); + + arma_debug_check_bounds(err_state, err_msg); + + if(C_n_cols > 0) + { + Mat out( (std::max)(t_n_rows, C_n_rows), t_n_cols + C_n_cols, arma_nozeros_indicator() ); + + if(t_n_rows > 0) + { + if(A_n_cols > 0) + { + out.cols(0, A_n_cols-1) = cols(0, A_n_cols-1); + } + + if(B_n_cols > 0) + { + out.cols(col_num + C_n_cols, t_n_cols + C_n_cols - 1) = cols(col_num, t_n_cols - 1); + } + } + + if(C_n_rows > 0) + { + out.cols(col_num, col_num + C_n_cols - 1) = C; + } + + steal_mem(out); + } + } + + + +template +template +inline +Mat::Mat(const Gen& X) + : n_rows(X.n_rows) + , n_cols(X.n_cols) + , n_elem(n_rows*n_cols) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + init_cold(); + + X.apply(*this); + } + + + +template +template +inline +Mat& +Mat::operator=(const Gen& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + init_warm(X.n_rows, X.n_cols); + + X.apply(*this); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const Gen& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + X.apply_inplace_plus(*this); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator-=(const Gen& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + X.apply_inplace_minus(*this); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator*=(const Gen& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat tmp(X); + + return (*this).operator*=(tmp); + } + + + +template +template +inline +Mat& +Mat::operator%=(const Gen& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + X.apply_inplace_schur(*this); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator/=(const Gen& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + X.apply_inplace_div(*this); + + return *this; + } + + + +//! create a matrix from Op, ie. run the previously delayed unary operations +template +template +inline +Mat::Mat(const Op& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + op_type::apply(*this, X); + } + + + +//! create a matrix from Op, ie. run the previously delayed unary operations +template +template +inline +Mat& +Mat::operator=(const Op& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + op_type::apply(*this, X); + + return *this; + } + + + +//! in-place matrix addition, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator+=(const Op& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat m(X); + + return (*this).operator+=(m); + } + + + +//! in-place matrix subtraction, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator-=(const Op& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat m(X); + + return (*this).operator-=(m); + } + + + +//! in-place matrix multiplication, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator*=(const Op& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +//! in-place matrix element-wise multiplication, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator%=(const Op& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat m(X); + + return (*this).operator%=(m); + } + + + +//! in-place matrix element-wise division, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator/=(const Op& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat m(X); + + return (*this).operator/=(m); + } + + + +//! create a matrix from eOp, ie. run the previously delayed unary operations +template +template +inline +Mat::Mat(const eOp& X) + : n_rows(X.get_n_rows()) + , n_cols(X.get_n_cols()) + , n_elem(X.get_n_elem()) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + init_cold(); + + eop_type::apply(*this, X); + } + + + +//! create a matrix from eOp, ie. run the previously delayed unary operations +template +template +inline +Mat& +Mat::operator=(const eOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const bool bad_alias = (eOp::proxy_type::has_subview && X.P.is_alias(*this)); + + if(bad_alias) { Mat tmp(X); steal_mem(tmp); return *this; } + + init_warm(X.get_n_rows(), X.get_n_cols()); + + eop_type::apply(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const eOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const bool bad_alias = (eOp::proxy_type::has_subview && X.P.is_alias(*this)); + + if(bad_alias) { const Mat tmp(X); return (*this).operator+=(tmp); } + + eop_type::apply_inplace_plus(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator-=(const eOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const bool bad_alias = (eOp::proxy_type::has_subview && X.P.is_alias(*this)); + + if(bad_alias) { const Mat tmp(X); return (*this).operator-=(tmp); } + + eop_type::apply_inplace_minus(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator*=(const eOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const eOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const bool bad_alias = (eOp::proxy_type::has_subview && X.P.is_alias(*this)); + + if(bad_alias) { const Mat tmp(X); return (*this).operator%=(tmp); } + + eop_type::apply_inplace_schur(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator/=(const eOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const bool bad_alias = (eOp::proxy_type::has_subview && X.P.is_alias(*this)); + + if(bad_alias) { const Mat tmp(X); return (*this).operator/=(tmp); } + + eop_type::apply_inplace_div(*this, X); + + return *this; + } + + + +template +template +inline +Mat::Mat(const mtOp& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + op_type::apply(*this, X); + } + + + +template +template +inline +Mat& +Mat::operator=(const mtOp& X) + { + arma_extra_debug_sigprint(); + + op_type::apply(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const mtOp& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator+=(m); + } + + + +template +template +inline +Mat& +Mat::operator-=(const mtOp& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator-=(m); + } + + + +template +template +inline +Mat& +Mat::operator*=(const mtOp& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator*=(m); + } + + + +template +template +inline +Mat& +Mat::operator%=(const mtOp& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator%=(m); + } + + + +template +template +inline +Mat& +Mat::operator/=(const mtOp& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator/=(m); + } + + + +template +template +inline +Mat::Mat(const CubeToMatOp& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + op_type::apply(*this, X); + } + + + +template +template +inline +Mat& +Mat::operator=(const CubeToMatOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + op_type::apply(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const CubeToMatOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + (*this) = (*this) + X; + + return (*this); + } + + + +template +template +inline +Mat& +Mat::operator-=(const CubeToMatOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + (*this) = (*this) - X; + + return (*this); + } + + + +template +template +inline +Mat& +Mat::operator*=(const CubeToMatOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const CubeToMatOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + (*this) = (*this) % X; + + return (*this); + } + + + +template +template +inline +Mat& +Mat::operator/=(const CubeToMatOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + (*this) = (*this) / X; + + return (*this); + } + + + +template +template +inline +Mat::Mat(const SpToDOp& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + op_type::apply(*this, X); + } + + + +//! create a matrix from an SpToDOp, ie. run the previously delayed unary operations +template +template +inline +Mat& +Mat::operator=(const SpToDOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + op_type::apply(*this, X); + + return *this; + } + + + +//! in-place matrix addition, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator+=(const SpToDOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat m(X); + + return (*this).operator+=(m); + } + + + +//! in-place matrix subtraction, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator-=(const SpToDOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat m(X); + + return (*this).operator-=(m); + } + + + +//! in-place matrix multiplication, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator*=(const SpToDOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +//! in-place matrix element-wise multiplication, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator%=(const SpToDOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat m(X); + + return (*this).operator%=(m); + } + + + +//! in-place matrix element-wise division, with the right-hand-side operand having delayed operations +template +template +inline +Mat& +Mat::operator/=(const SpToDOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const Mat m(X); + + return (*this).operator/=(m); + } + + + +//! create a matrix from Glue, ie. run the previously delayed binary operations +template +template +inline +Mat::Mat(const Glue& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + glue_type::apply(*this, X); + } + + + +//! create a matrix from Glue, ie. run the previously delayed binary operations +template +template +inline +Mat& +Mat::operator=(const Glue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + glue_type::apply(*this, X); + + return *this; + } + + + +//! in-place matrix addition, with the right-hand-side operands having delayed operations +template +template +inline +Mat& +Mat::operator+=(const Glue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const Mat m(X); + + return (*this).operator+=(m); + } + + + +//! in-place matrix subtraction, with the right-hand-side operands having delayed operations +template +template +inline +Mat& +Mat::operator-=(const Glue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const Mat m(X); + + return (*this).operator-=(m); + } + + + +//! in-place matrix multiplications, with the right-hand-side operands having delayed operations +template +template +inline +Mat& +Mat::operator*=(const Glue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +//! in-place matrix element-wise multiplication, with the right-hand-side operands having delayed operations +template +template +inline +Mat& +Mat::operator%=(const Glue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const Mat m(X); + + return (*this).operator%=(m); + } + + + +//! in-place matrix element-wise division, with the right-hand-side operands having delayed operations +template +template +inline +Mat& +Mat::operator/=(const Glue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const Mat m(X); + + return (*this).operator/=(m); + } + + + +template +template +inline +Mat& +Mat::operator+=(const Glue& X) + { + arma_extra_debug_sigprint(); + + glue_times::apply_inplace_plus(*this, X, sword(+1)); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator-=(const Glue& X) + { + arma_extra_debug_sigprint(); + + glue_times::apply_inplace_plus(*this, X, sword(-1)); + + return *this; + } + + + +//! create a matrix from eGlue, ie. run the previously delayed binary operations +template +template +inline +Mat::Mat(const eGlue& X) + : n_rows(X.get_n_rows()) + , n_cols(X.get_n_cols()) + , n_elem(X.get_n_elem()) + , n_alloc() + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + init_cold(); + + eglue_type::apply(*this, X); + } + + + +//! create a matrix from eGlue, ie. run the previously delayed binary operations +template +template +inline +Mat& +Mat::operator=(const eGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const bool bad_alias = + ( + (eGlue::proxy1_type::has_subview && X.P1.is_alias(*this)) + || + (eGlue::proxy2_type::has_subview && X.P2.is_alias(*this)) + ); + + if(bad_alias) { Mat tmp(X); steal_mem(tmp); return *this; } + + init_warm(X.get_n_rows(), X.get_n_cols()); + + eglue_type::apply(*this, X); + + return *this; + } + + + +//! in-place matrix addition, with the right-hand-side operands having delayed operations +template +template +inline +Mat& +Mat::operator+=(const eGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const bool bad_alias = + ( + (eGlue::proxy1_type::has_subview && X.P1.is_alias(*this)) + || + (eGlue::proxy2_type::has_subview && X.P2.is_alias(*this)) + ); + + if(bad_alias) { const Mat tmp(X); return (*this).operator+=(tmp); } + + eglue_type::apply_inplace_plus(*this, X); + + return *this; + } + + + +//! in-place matrix subtraction, with the right-hand-side operands having delayed operations +template +template +inline +Mat& +Mat::operator-=(const eGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const bool bad_alias = + ( + (eGlue::proxy1_type::has_subview && X.P1.is_alias(*this)) + || + (eGlue::proxy2_type::has_subview && X.P2.is_alias(*this)) + ); + + if(bad_alias) { const Mat tmp(X); return (*this).operator-=(tmp); } + + eglue_type::apply_inplace_minus(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator*=(const eGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const eGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const bool bad_alias = + ( + (eGlue::proxy1_type::has_subview && X.P1.is_alias(*this)) + || + (eGlue::proxy2_type::has_subview && X.P2.is_alias(*this)) + ); + + if(bad_alias) { const Mat tmp(X); return (*this).operator%=(tmp); } + + eglue_type::apply_inplace_schur(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator/=(const eGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const bool bad_alias = + ( + (eGlue::proxy1_type::has_subview && X.P1.is_alias(*this)) + || + (eGlue::proxy2_type::has_subview && X.P2.is_alias(*this)) + ); + + if(bad_alias) { const Mat tmp(X); return (*this).operator/=(tmp); } + + eglue_type::apply_inplace_div(*this, X); + + return *this; + } + + + +template +template +inline +Mat::Mat(const mtGlue& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + glue_type::apply(*this, X); + } + + + +template +template +inline +Mat& +Mat::operator=(const mtGlue& X) + { + arma_extra_debug_sigprint(); + + glue_type::apply(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const mtGlue& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator+=(m); + } + + + +template +template +inline +Mat& +Mat::operator-=(const mtGlue& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator-=(m); + } + + + +template +template +inline +Mat& +Mat::operator*=(const mtGlue& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + glue_times::apply_inplace(*this, m); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const mtGlue& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator%=(m); + } + + + +template +template +inline +Mat& +Mat::operator/=(const mtGlue& X) + { + arma_extra_debug_sigprint(); + + const Mat m(X); + + return (*this).operator/=(m); + } + + + +template +template +inline +Mat::Mat(const SpToDGlue& X) + : n_rows(0) + , n_cols(0) + , n_elem(0) + , n_alloc(0) + , vec_state(0) + , mem_state(0) + , mem() + { + arma_extra_debug_sigprint_this(this); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + glue_type::apply(*this, X); + } + + + +template +template +inline +Mat& +Mat::operator=(const SpToDGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + glue_type::apply(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator+=(const SpToDGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const Mat m(X); + + return (*this).operator+=(m); + } + + + +template +template +inline +Mat& +Mat::operator-=(const SpToDGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const Mat m(X); + + return (*this).operator-=(m); + } + + + +template +template +inline +Mat& +Mat::operator*=(const SpToDGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + glue_times::apply_inplace(*this, X); + + return *this; + } + + + +template +template +inline +Mat& +Mat::operator%=(const SpToDGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const Mat m(X); + + return (*this).operator%=(m); + } + + + +template +template +inline +Mat& +Mat::operator/=(const SpToDGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const Mat m(X); + + return (*this).operator/=(m); + } + + + +//! linear element accessor (treats the matrix as a vector); no bounds check; assumes memory is aligned +template +arma_inline +const eT& +Mat::at_alt(const uword ii) const + { + const eT* mem_aligned = mem; + + memory::mark_as_aligned(mem_aligned); + + return mem_aligned[ii]; + } + + + +//! linear element accessor (treats the matrix as a vector); bounds checking not done when ARMA_NO_DEBUG is defined +template +arma_inline +eT& +Mat::operator() (const uword ii) + { + arma_debug_check_bounds( (ii >= n_elem), "Mat::operator(): index out of bounds" ); + + return access::rw(mem[ii]); + } + + + +//! linear element accessor (treats the matrix as a vector); bounds checking not done when ARMA_NO_DEBUG is defined +template +arma_inline +const eT& +Mat::operator() (const uword ii) const + { + arma_debug_check_bounds( (ii >= n_elem), "Mat::operator(): index out of bounds" ); + + return mem[ii]; + } + + +//! linear element accessor (treats the matrix as a vector); no bounds check. +template +arma_inline +eT& +Mat::operator[] (const uword ii) + { + return access::rw(mem[ii]); + } + + + +//! linear element accessor (treats the matrix as a vector); no bounds check +template +arma_inline +const eT& +Mat::operator[] (const uword ii) const + { + return mem[ii]; + } + + + +//! linear element accessor (treats the matrix as a vector); no bounds check. +template +arma_inline +eT& +Mat::at(const uword ii) + { + return access::rw(mem[ii]); + } + + + +//! linear element accessor (treats the matrix as a vector); no bounds check +template +arma_inline +const eT& +Mat::at(const uword ii) const + { + return mem[ii]; + } + + + +//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined +template +arma_inline +eT& +Mat::operator() (const uword in_row, const uword in_col) + { + arma_debug_check_bounds( ((in_row >= n_rows) || (in_col >= n_cols)), "Mat::operator(): index out of bounds" ); + + return access::rw(mem[in_row + in_col*n_rows]); + } + + + +//! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined +template +arma_inline +const eT& +Mat::operator() (const uword in_row, const uword in_col) const + { + arma_debug_check_bounds( ((in_row >= n_rows) || (in_col >= n_cols)), "Mat::operator(): index out of bounds" ); + + return mem[in_row + in_col*n_rows]; + } + + + +//! element accessor; no bounds check +template +arma_inline +eT& +Mat::at(const uword in_row, const uword in_col) + { + return access::rw( mem[in_row + in_col*n_rows] ); + } + + + +//! element accessor; no bounds check +template +arma_inline +const eT& +Mat::at(const uword in_row, const uword in_col) const + { + return mem[in_row + in_col*n_rows]; + } + + + +#if defined(__cpp_multidimensional_subscript) + + //! element accessor; no bounds check + template + arma_inline + eT& + Mat::operator[] (const uword in_row, const uword in_col) + { + return access::rw( mem[in_row + in_col*n_rows] ); + } + + + + //! element accessor; no bounds check + template + arma_inline + const eT& + Mat::operator[] (const uword in_row, const uword in_col) const + { + return mem[in_row + in_col*n_rows]; + } + +#endif + + + +//! prefix ++ +template +arma_inline +const Mat& +Mat::operator++() + { + Mat_aux::prefix_pp(*this); + + return *this; + } + + + +//! postfix ++ (must not return the object by reference) +template +arma_inline +void +Mat::operator++(int) + { + Mat_aux::postfix_pp(*this); + } + + + +//! prefix -- +template +arma_inline +const Mat& +Mat::operator--() + { + Mat_aux::prefix_mm(*this); + + return *this; + } + + + +//! postfix -- (must not return the object by reference) +template +arma_inline +void +Mat::operator--(int) + { + Mat_aux::postfix_mm(*this); + } + + + +//! returns true if the matrix has no elements +template +arma_inline +bool +Mat::is_empty() const + { + return (n_elem == 0); + } + + + +//! returns true if the object can be interpreted as a column or row vector +template +arma_inline +bool +Mat::is_vec() const + { + return ( (n_rows == 1) || (n_cols == 1) ); + } + + + +//! returns true if the object can be interpreted as a row vector +template +arma_inline +bool +Mat::is_rowvec() const + { + return (n_rows == 1); + } + + + +//! returns true if the object can be interpreted as a column vector +template +arma_inline +bool +Mat::is_colvec() const + { + return (n_cols == 1); + } + + + +//! returns true if the object has the same number of non-zero rows and columnns +template +arma_inline +bool +Mat::is_square() const + { + return (n_rows == n_cols); + } + + + +template +inline +bool +Mat::internal_is_finite() const + { + arma_extra_debug_sigprint(); + + return arrayops::is_finite(memptr(), n_elem); + } + + + +template +inline +bool +Mat::internal_has_inf() const + { + arma_extra_debug_sigprint(); + + return arrayops::has_inf(memptr(), n_elem); + } + + + +template +inline +bool +Mat::internal_has_nan() const + { + arma_extra_debug_sigprint(); + + return arrayops::has_nan(memptr(), n_elem); + } + + + +template +inline +bool +Mat::internal_has_nonfinite() const + { + arma_extra_debug_sigprint(); + + return (arrayops::is_finite(memptr(), n_elem) == false); + } + + + +template +inline +bool +Mat::is_sorted(const char* direction) const + { + arma_extra_debug_sigprint(); + + return (*this).is_sorted(direction, (((vec_state == 2) || (n_rows == 1)) ? uword(1) : uword(0))); + } + + + +template +inline +bool +Mat::is_sorted(const char* direction, const uword dim) const + { + arma_extra_debug_sigprint(); + + const char sig1 = (direction != nullptr) ? direction[0] : char(0); + + // direction is one of: + // "ascend" + // "descend" + // "strictascend" + // "strictdescend" + + arma_debug_check( ((sig1 != 'a') && (sig1 != 'd') && (sig1 != 's')), "Mat::is_sorted(): unknown sort direction" ); + + // "strictascend" + // "strictdescend" + // 0123456 + + const char sig2 = (sig1 == 's') ? direction[6] : char(0); + + if(sig1 == 's') { arma_debug_check( ((sig2 != 'a') && (sig2 != 'd')), "Mat::is_sorted(): unknown sort direction" ); } + + arma_debug_check( (dim > 1), "Mat::is_sorted(): parameter 'dim' must be 0 or 1" ); + + if(sig1 == 'a') + { + // case: ascend + + // deliberately using the opposite direction comparator, + // as we need to handle the case of two elements being equal + + arma_gt_comparator comparator; + + return (*this).is_sorted_helper(comparator, dim); + } + else + if(sig1 == 'd') + { + // case: descend + + // deliberately using the opposite direction comparator, + // as we need to handle the case of two elements being equal + + arma_lt_comparator comparator; + + return (*this).is_sorted_helper(comparator, dim); + } + else + if((sig1 == 's') && (sig2 == 'a')) + { + // case: strict ascend + + arma_geq_comparator comparator; + + return (*this).is_sorted_helper(comparator, dim); + } + else + if((sig1 == 's') && (sig2 == 'd')) + { + // case: strict descend + + arma_leq_comparator comparator; + + return (*this).is_sorted_helper(comparator, dim); + } + + return true; + } + + + +template +template +inline +bool +Mat::is_sorted_helper(const comparator& comp, const uword dim) const + { + arma_extra_debug_sigprint(); + + if(n_elem <= 1) { return true; } + + const uword local_n_cols = n_cols; + const uword local_n_rows = n_rows; + + if(dim == 0) + { + if(local_n_rows <= 1u) { return true; } + + const uword local_n_rows_m1 = local_n_rows - 1; + + for(uword c=0; c < local_n_cols; ++c) + { + const eT* coldata = colptr(c); + + for(uword r=0; r < local_n_rows_m1; ++r) + { + const eT val1 = (*coldata); coldata++; + const eT val2 = (*coldata); + + if(comp(val1,val2)) { return false; } + } + } + } + else + if(dim == 1) + { + if(local_n_cols <= 1u) { return true; } + + const uword local_n_cols_m1 = local_n_cols - 1; + + if(local_n_rows == 1) + { + const eT* rowdata = memptr(); + + for(uword c=0; c < local_n_cols_m1; ++c) + { + const eT val1 = (*rowdata); rowdata++; + const eT val2 = (*rowdata); + + if(comp(val1,val2)) { return false; } + } + } + else + { + for(uword r=0; r < local_n_rows; ++r) + for(uword c=0; c < local_n_cols_m1; ++c) + { + const eT val1 = at(r,c ); + const eT val2 = at(r,c+1); + + if(comp(val1,val2)) { return false; } + } + } + } + + return true; + } + + + +//! returns true if the given index is currently in range +template +arma_inline +bool +Mat::in_range(const uword ii) const + { + return (ii < n_elem); + } + + + +//! returns true if the given start and end indices are currently in range +template +arma_inline +bool +Mat::in_range(const span& x) const + { + arma_extra_debug_sigprint(); + + if(x.whole) + { + return true; + } + else + { + const uword a = x.a; + const uword b = x.b; + + return ( (a <= b) && (b < n_elem) ); + } + } + + + +//! returns true if the given location is currently in range +template +arma_inline +bool +Mat::in_range(const uword in_row, const uword in_col) const + { + return ( (in_row < n_rows) && (in_col < n_cols) ); + } + + + +template +arma_inline +bool +Mat::in_range(const span& row_span, const uword in_col) const + { + arma_extra_debug_sigprint(); + + if(row_span.whole) + { + return (in_col < n_cols); + } + else + { + const uword in_row1 = row_span.a; + const uword in_row2 = row_span.b; + + return ( (in_row1 <= in_row2) && (in_row2 < n_rows) && (in_col < n_cols) ); + } + } + + + +template +arma_inline +bool +Mat::in_range(const uword in_row, const span& col_span) const + { + arma_extra_debug_sigprint(); + + if(col_span.whole) + { + return (in_row < n_rows); + } + else + { + const uword in_col1 = col_span.a; + const uword in_col2 = col_span.b; + + return ( (in_row < n_rows) && (in_col1 <= in_col2) && (in_col2 < n_cols) ); + } + } + + + +template +arma_inline +bool +Mat::in_range(const span& row_span, const span& col_span) const + { + arma_extra_debug_sigprint(); + + const uword in_row1 = row_span.a; + const uword in_row2 = row_span.b; + + const uword in_col1 = col_span.a; + const uword in_col2 = col_span.b; + + const bool rows_ok = row_span.whole ? true : ( (in_row1 <= in_row2) && (in_row2 < n_rows) ); + const bool cols_ok = col_span.whole ? true : ( (in_col1 <= in_col2) && (in_col2 < n_cols) ); + + return ( rows_ok && cols_ok ); + } + + + +template +arma_inline +bool +Mat::in_range(const uword in_row, const uword in_col, const SizeMat& s) const + { + const uword l_n_rows = n_rows; + const uword l_n_cols = n_cols; + + if( (in_row >= l_n_rows) || (in_col >= l_n_cols) || ((in_row + s.n_rows) > l_n_rows) || ((in_col + s.n_cols) > l_n_cols) ) + { + return false; + } + else + { + return true; + } + } + + + +//! returns a pointer to array of eTs for a specified column; no bounds check +template +arma_inline +eT* +Mat::colptr(const uword in_col) + { + return & access::rw(mem[in_col*n_rows]); + } + + + +//! returns a pointer to array of eTs for a specified column; no bounds check +template +arma_inline +const eT* +Mat::colptr(const uword in_col) const + { + return & mem[in_col*n_rows]; + } + + + +//! returns a pointer to array of eTs used by the matrix +template +arma_inline +eT* +Mat::memptr() + { + return const_cast(mem); + } + + + +//! returns a pointer to array of eTs used by the matrix +template +arma_inline +const eT* +Mat::memptr() const + { + return mem; + } + + + +//! change the matrix to have user specified dimensions (data is not preserved) +template +inline +Mat& +Mat::set_size(const uword new_n_elem) + { + arma_extra_debug_sigprint(); + + switch(vec_state) + { + case 0: + // fallthrough + case 1: + init_warm(new_n_elem, 1); + break; + + case 2: + init_warm(1, new_n_elem); + break; + + default: + ; + } + + return *this; + } + + + +//! change the matrix to have user specified dimensions (data is not preserved) +template +inline +Mat& +Mat::set_size(const uword new_n_rows, const uword new_n_cols) + { + arma_extra_debug_sigprint(); + + init_warm(new_n_rows, new_n_cols); + + return *this; + } + + + +template +inline +Mat& +Mat::set_size(const SizeMat& s) + { + arma_extra_debug_sigprint(); + + init_warm(s.n_rows, s.n_cols); + + return *this; + } + + + +//! change the matrix to have user specified dimensions (data is preserved) +template +inline +Mat& +Mat::resize(const uword new_n_elem) + { + arma_extra_debug_sigprint(); + + switch(vec_state) + { + case 0: + // fallthrough + case 1: + (*this).resize(new_n_elem, 1); + break; + + case 2: + (*this).resize(1, new_n_elem); + break; + + default: + ; + } + + return *this; + } + + + +//! change the matrix to have user specified dimensions (data is preserved) +template +inline +Mat& +Mat::resize(const uword new_n_rows, const uword new_n_cols) + { + arma_extra_debug_sigprint(); + + op_resize::apply_mat_inplace((*this), new_n_rows, new_n_cols); + + return *this; + } + + + +template +inline +Mat& +Mat::resize(const SizeMat& s) + { + arma_extra_debug_sigprint(); + + op_resize::apply_mat_inplace((*this), s.n_rows, s.n_cols); + + return *this; + } + + + +//! change the matrix to have user specified dimensions (data is preserved) +template +inline +Mat& +Mat::reshape(const uword new_n_rows, const uword new_n_cols) + { + arma_extra_debug_sigprint(); + + op_reshape::apply_mat_inplace((*this), new_n_rows, new_n_cols); + + return *this; + } + + + +template +inline +Mat& +Mat::reshape(const SizeMat& s) + { + arma_extra_debug_sigprint(); + + op_reshape::apply_mat_inplace((*this), s.n_rows, s.n_cols); + + return *this; + } + + + +//! NOTE: don't use this form; it's deprecated and will be removed +template +inline +void +Mat::reshape(const uword new_n_rows, const uword new_n_cols, const uword dim) + { + arma_extra_debug_sigprint(); + + arma_debug_check( (dim > 1), "reshape(): parameter 'dim' must be 0 or 1" ); + + if(dim == 0) + { + op_reshape::apply_mat_inplace((*this), new_n_rows, new_n_cols); + } + else + if(dim == 1) + { + Mat tmp; + + op_strans::apply_mat_noalias(tmp, (*this)); + + op_reshape::apply_mat_noalias((*this), tmp, new_n_rows, new_n_cols); + } + } + + + +//! change the matrix (without preserving data) to have the same dimensions as the given expression +template +template +inline +Mat& +Mat::copy_size(const Base& X) + { + arma_extra_debug_sigprint(); + + const Proxy P(X.get_ref()); + + const uword X_n_rows = P.get_n_rows(); + const uword X_n_cols = P.get_n_cols(); + + init_warm(X_n_rows, X_n_cols); + + return *this; + } + + + +//! apply a functor to each element +template +template +inline +Mat& +Mat::for_each(functor F) + { + arma_extra_debug_sigprint(); + + eT* data = memptr(); + + const uword N = n_elem; + + uword ii, jj; + + for(ii=0, jj=1; jj < N; ii+=2, jj+=2) + { + F(data[ii]); + F(data[jj]); + } + + if(ii < N) + { + F(data[ii]); + } + + return *this; + } + + + +template +template +inline +const Mat& +Mat::for_each(functor F) const + { + arma_extra_debug_sigprint(); + + const eT* data = memptr(); + + const uword N = n_elem; + + uword ii, jj; + + for(ii=0, jj=1; jj < N; ii+=2, jj+=2) + { + F(data[ii]); + F(data[jj]); + } + + if(ii < N) + { + F(data[ii]); + } + + return *this; + } + + + +//! transform each element in the matrix using a functor +template +template +inline +Mat& +Mat::transform(functor F) + { + arma_extra_debug_sigprint(); + + eT* out_mem = memptr(); + + const uword N = n_elem; + + uword ii, jj; + + for(ii=0, jj=1; jj < N; ii+=2, jj+=2) + { + eT tmp_ii = out_mem[ii]; + eT tmp_jj = out_mem[jj]; + + tmp_ii = eT( F(tmp_ii) ); + tmp_jj = eT( F(tmp_jj) ); + + out_mem[ii] = tmp_ii; + out_mem[jj] = tmp_jj; + } + + if(ii < N) + { + out_mem[ii] = eT( F(out_mem[ii]) ); + } + + return *this; + } + + + +//! imbue (fill) the matrix with values provided by a functor +template +template +inline +Mat& +Mat::imbue(functor F) + { + arma_extra_debug_sigprint(); + + eT* out_mem = memptr(); + + const uword N = n_elem; + + uword ii, jj; + + for(ii=0, jj=1; jj < N; ii+=2, jj+=2) + { + const eT tmp_ii = eT( F() ); + const eT tmp_jj = eT( F() ); + + out_mem[ii] = tmp_ii; + out_mem[jj] = tmp_jj; + } + + if(ii < N) + { + out_mem[ii] = eT( F() ); + } + + return *this; + } + + + +template +inline +Mat& +Mat::replace(const eT old_val, const eT new_val) + { + arma_extra_debug_sigprint(); + + arrayops::replace(memptr(), n_elem, old_val, new_val); + + return *this; + } + + + +template +inline +Mat& +Mat::clean(const typename get_pod_type::result threshold) + { + arma_extra_debug_sigprint(); + + arrayops::clean(memptr(), n_elem, threshold); + + return *this; + } + + + +template +inline +Mat& +Mat::clamp(const eT min_val, const eT max_val) + { + arma_extra_debug_sigprint(); + + if(is_cx::no) + { + arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "Mat::clamp(): min_val must be less than max_val" ); + } + else + { + arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "Mat::clamp(): real(min_val) must be less than real(max_val)" ); + arma_debug_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "Mat::clamp(): imag(min_val) must be less than imag(max_val)" ); + } + + arrayops::clamp(memptr(), n_elem, min_val, max_val); + + return *this; + } + + + +//! fill the matrix with the specified value +template +inline +Mat& +Mat::fill(const eT val) + { + arma_extra_debug_sigprint(); + + arrayops::inplace_set( memptr(), val, n_elem ); + + return *this; + } + + + +//! fill the matrix with the specified pattern +template +template +inline +Mat& +Mat::fill(const fill::fill_class&) + { + arma_extra_debug_sigprint(); + + if(is_same_type::yes) { (*this).zeros(); } + if(is_same_type::yes) { (*this).ones(); } + if(is_same_type::yes) { (*this).eye(); } + if(is_same_type::yes) { (*this).randu(); } + if(is_same_type::yes) { (*this).randn(); } + + return *this; + } + + + +template +inline +Mat& +Mat::zeros() + { + arma_extra_debug_sigprint(); + + arrayops::fill_zeros(memptr(), n_elem); + + return *this; + } + + + +template +inline +Mat& +Mat::zeros(const uword new_n_elem) + { + arma_extra_debug_sigprint(); + + set_size(new_n_elem); + + return (*this).zeros(); + } + + + +template +inline +Mat& +Mat::zeros(const uword new_n_rows, const uword new_n_cols) + { + arma_extra_debug_sigprint(); + + set_size(new_n_rows, new_n_cols); + + return (*this).zeros(); + } + + + +template +inline +Mat& +Mat::zeros(const SizeMat& s) + { + arma_extra_debug_sigprint(); + + return (*this).zeros(s.n_rows, s.n_cols); + } + + + +template +inline +Mat& +Mat::ones() + { + arma_extra_debug_sigprint(); + + return fill(eT(1)); + } + + + +template +inline +Mat& +Mat::ones(const uword new_n_elem) + { + arma_extra_debug_sigprint(); + + set_size(new_n_elem); + + return fill(eT(1)); + } + + + +template +inline +Mat& +Mat::ones(const uword new_n_rows, const uword new_n_cols) + { + arma_extra_debug_sigprint(); + + set_size(new_n_rows, new_n_cols); + + return fill(eT(1)); + } + + + +template +inline +Mat& +Mat::ones(const SizeMat& s) + { + arma_extra_debug_sigprint(); + + return (*this).ones(s.n_rows, s.n_cols); + } + + + +template +inline +Mat& +Mat::randu() + { + arma_extra_debug_sigprint(); + + arma_rng::randu::fill( memptr(), n_elem ); + + return *this; + } + + + +template +inline +Mat& +Mat::randu(const uword new_n_elem) + { + arma_extra_debug_sigprint(); + + set_size(new_n_elem); + + return (*this).randu(); + } + + + +template +inline +Mat& +Mat::randu(const uword new_n_rows, const uword new_n_cols) + { + arma_extra_debug_sigprint(); + + set_size(new_n_rows, new_n_cols); + + return (*this).randu(); + } + + + +template +inline +Mat& +Mat::randu(const SizeMat& s) + { + arma_extra_debug_sigprint(); + + return (*this).randu(s.n_rows, s.n_cols); + } + + + +template +inline +Mat& +Mat::randn() + { + arma_extra_debug_sigprint(); + + arma_rng::randn::fill( memptr(), n_elem ); + + return *this; + } + + + +template +inline +Mat& +Mat::randn(const uword new_n_elem) + { + arma_extra_debug_sigprint(); + + set_size(new_n_elem); + + return (*this).randn(); + } + + + +template +inline +Mat& +Mat::randn(const uword new_n_rows, const uword new_n_cols) + { + arma_extra_debug_sigprint(); + + set_size(new_n_rows, new_n_cols); + + return (*this).randn(); + } + + + +template +inline +Mat& +Mat::randn(const SizeMat& s) + { + arma_extra_debug_sigprint(); + + return (*this).randn(s.n_rows, s.n_cols); + } + + + +template +inline +Mat& +Mat::eye() + { + arma_extra_debug_sigprint(); + + (*this).zeros(); + + const uword N = (std::min)(n_rows, n_cols); + + for(uword ii=0; ii +inline +Mat& +Mat::eye(const uword new_n_rows, const uword new_n_cols) + { + arma_extra_debug_sigprint(); + + set_size(new_n_rows, new_n_cols); + + return (*this).eye(); + } + + + +template +inline +Mat& +Mat::eye(const SizeMat& s) + { + arma_extra_debug_sigprint(); + + return (*this).eye(s.n_rows, s.n_cols); + } + + + +template +inline +void +Mat::reset() + { + arma_extra_debug_sigprint(); + + const uword new_n_rows = (vec_state == 2) ? 1 : 0; + const uword new_n_cols = (vec_state == 1) ? 1 : 0; + + init_warm(new_n_rows, new_n_cols); + } + + + +template +inline +void +Mat::soft_reset() + { + arma_extra_debug_sigprint(); + + // don't change the size if the matrix has a fixed size or is a cube slice + if(mem_state <= 1) + { + reset(); + } + else + { + zeros(); + } + } + + + +template +template +inline +void +Mat::set_real(const Base::pod_type,T1>& X) + { + arma_extra_debug_sigprint(); + + Mat_aux::set_real(*this, X); + } + + + +template +template +inline +void +Mat::set_imag(const Base::pod_type,T1>& X) + { + arma_extra_debug_sigprint(); + + Mat_aux::set_imag(*this, X); + } + + + +template +inline +eT +Mat::min() const + { + arma_extra_debug_sigprint(); + + if(n_elem == 0) + { + arma_debug_check(true, "Mat::min(): object has no elements"); + + return Datum::nan; + } + + return op_min::direct_min(memptr(), n_elem); + } + + + +template +inline +eT +Mat::max() const + { + arma_extra_debug_sigprint(); + + if(n_elem == 0) + { + arma_debug_check(true, "Mat::max(): object has no elements"); + + return Datum::nan; + } + + return op_max::direct_max(memptr(), n_elem); + } + + + +template +inline +eT +Mat::min(uword& index_of_min_val) const + { + arma_extra_debug_sigprint(); + + if(n_elem == 0) + { + arma_debug_check(true, "Mat::min(): object has no elements"); + + index_of_min_val = uword(0); + + return Datum::nan; + } + + return op_min::direct_min(memptr(), n_elem, index_of_min_val); + } + + + +template +inline +eT +Mat::max(uword& index_of_max_val) const + { + arma_extra_debug_sigprint(); + + if(n_elem == 0) + { + arma_debug_check(true, "Mat::max(): object has no elements"); + + index_of_max_val = uword(0); + + return Datum::nan; + } + + return op_max::direct_max(memptr(), n_elem, index_of_max_val); + } + + + +template +inline +eT +Mat::min(uword& row_of_min_val, uword& col_of_min_val) const + { + arma_extra_debug_sigprint(); + + if(n_elem == 0) + { + arma_debug_check(true, "Mat::min(): object has no elements"); + + row_of_min_val = uword(0); + col_of_min_val = uword(0); + + return Datum::nan; + } + + uword iq; + + eT val = op_min::direct_min(memptr(), n_elem, iq); + + row_of_min_val = iq % n_rows; + col_of_min_val = iq / n_rows; + + return val; + } + + + +template +inline +eT +Mat::max(uword& row_of_max_val, uword& col_of_max_val) const + { + arma_extra_debug_sigprint(); + + if(n_elem == 0) + { + arma_debug_check(true, "Mat::max(): object has no elements"); + + row_of_max_val = uword(0); + col_of_max_val = uword(0); + + return Datum::nan; + } + + uword iq; + + eT val = op_max::direct_max(memptr(), n_elem, iq); + + row_of_max_val = iq % n_rows; + col_of_max_val = iq / n_rows; + + return val; + } + + + +//! save the matrix to a file +template +inline +bool +Mat::save(const std::string name, const file_type type) const + { + arma_extra_debug_sigprint(); + + bool save_okay = false; + + switch(type) + { + case raw_ascii: + save_okay = diskio::save_raw_ascii(*this, name); + break; + + case arma_ascii: + save_okay = diskio::save_arma_ascii(*this, name); + break; + + case csv_ascii: + return (*this).save(csv_name(name), type); + break; + + case ssv_ascii: + return (*this).save(csv_name(name), type); + break; + + case coord_ascii: + save_okay = diskio::save_coord_ascii(*this, name); + break; + + case raw_binary: + save_okay = diskio::save_raw_binary(*this, name); + break; + + case arma_binary: + save_okay = diskio::save_arma_binary(*this, name); + break; + + case pgm_binary: + save_okay = diskio::save_pgm_binary(*this, name); + break; + + case hdf5_binary: + return (*this).save(hdf5_name(name)); + break; + + case hdf5_binary_trans: // kept for compatibility with earlier versions of Armadillo + return (*this).save(hdf5_name(name, std::string(), hdf5_opts::trans)); + break; + + default: + arma_debug_warn_level(1, "Mat::save(): unsupported file type"); + save_okay = false; + } + + if(save_okay == false) { arma_debug_warn_level(3, "Mat::save(): write failed; file: ", name); } + + return save_okay; + } + + + +template +inline +bool +Mat::save(const hdf5_name& spec, const file_type type) const + { + arma_extra_debug_sigprint(); + + // handling of hdf5_binary_trans kept for compatibility with earlier versions of Armadillo + + if( (type != hdf5_binary) && (type != hdf5_binary_trans) ) + { + arma_stop_runtime_error("Mat::save(): unsupported file type for hdf5_name()"); + return false; + } + + const bool do_trans = bool(spec.opts.flags & hdf5_opts::flag_trans ) || (type == hdf5_binary_trans); + const bool append = bool(spec.opts.flags & hdf5_opts::flag_append ); + const bool replace = bool(spec.opts.flags & hdf5_opts::flag_replace); + + if(append && replace) + { + arma_stop_runtime_error("Mat::save(): only one of 'append' or 'replace' options can be used"); + return false; + } + + bool save_okay = false; + + std::string err_msg; + + if(do_trans) + { + Mat tmp; + + op_strans::apply_mat_noalias(tmp, *this); + + save_okay = diskio::save_hdf5_binary(tmp, spec, err_msg); + } + else + { + save_okay = diskio::save_hdf5_binary(*this, spec, err_msg); + } + + if(save_okay == false) + { + if(err_msg.length() > 0) + { + arma_debug_warn_level(3, "Mat::save(): ", err_msg, "; file: ", spec.filename); + } + else + { + arma_debug_warn_level(3, "Mat::save(): write failed; file: ", spec.filename); + } + } + + return save_okay; + } + + + +template +inline +bool +Mat::save(const csv_name& spec, const file_type type) const + { + arma_extra_debug_sigprint(); + + if( (type != csv_ascii) && (type != ssv_ascii) ) + { + arma_stop_runtime_error("Mat::save(): unsupported file type for csv_name()"); + return false; + } + + const bool do_trans = bool(spec.opts.flags & csv_opts::flag_trans ); + const bool no_header = bool(spec.opts.flags & csv_opts::flag_no_header ); + const bool with_header = bool(spec.opts.flags & csv_opts::flag_with_header) && (no_header == false); + const bool use_semicolon = bool(spec.opts.flags & csv_opts::flag_semicolon ) || (type == ssv_ascii); + + arma_extra_debug_print("Mat::save(csv_name): enabled flags:"); + + if(do_trans ) { arma_extra_debug_print("trans"); } + if(no_header ) { arma_extra_debug_print("no_header"); } + if(with_header ) { arma_extra_debug_print("with_header"); } + if(use_semicolon) { arma_extra_debug_print("semicolon"); } + + const char separator = (use_semicolon) ? char(';') : char(','); + + if(with_header) + { + if( (spec.header_ro.n_cols != 1) && (spec.header_ro.n_rows != 1) ) + { + arma_debug_warn_level(1, "Mat::save(): given header must have a vector layout"); + return false; + } + + for(uword i=0; i < spec.header_ro.n_elem; ++i) + { + const std::string& token = spec.header_ro.at(i); + + if(token.find(separator) != std::string::npos) + { + arma_debug_warn_level(1, "Mat::save(): token within the header contains the separator character: '", token, "'"); + return false; + } + } + + const uword save_n_cols = (do_trans) ? (*this).n_rows : (*this).n_cols; + + if(spec.header_ro.n_elem != save_n_cols) + { + arma_debug_warn_level(1, "Mat::save(): size mismatch between header and matrix"); + return false; + } + } + + bool save_okay = false; + + if(do_trans) + { + const Mat tmp = (*this).st(); + + save_okay = diskio::save_csv_ascii(tmp, spec.filename, spec.header_ro, with_header, separator); + } + else + { + save_okay = diskio::save_csv_ascii(*this, spec.filename, spec.header_ro, with_header, separator); + } + + if(save_okay == false) { arma_debug_warn_level(3, "Mat::save(): write failed; file: ", spec.filename); } + + return save_okay; + } + + + +//! save the matrix to a stream +template +inline +bool +Mat::save(std::ostream& os, const file_type type) const + { + arma_extra_debug_sigprint(); + + bool save_okay = false; + + switch(type) + { + case raw_ascii: + save_okay = diskio::save_raw_ascii(*this, os); + break; + + case arma_ascii: + save_okay = diskio::save_arma_ascii(*this, os); + break; + + case csv_ascii: + save_okay = diskio::save_csv_ascii(*this, os, char(',')); + break; + + case ssv_ascii: + save_okay = diskio::save_csv_ascii(*this, os, char(';')); + break; + + case coord_ascii: + save_okay = diskio::save_coord_ascii(*this, os); + break; + + case raw_binary: + save_okay = diskio::save_raw_binary(*this, os); + break; + + case arma_binary: + save_okay = diskio::save_arma_binary(*this, os); + break; + + case pgm_binary: + save_okay = diskio::save_pgm_binary(*this, os); + break; + + default: + arma_debug_warn_level(1, "Mat::save(): unsupported file type"); + save_okay = false; + } + + if(save_okay == false) { arma_debug_warn_level(3, "Mat::save(): stream write failed"); } + + return save_okay; + } + + + +//! load a matrix from a file +template +inline +bool +Mat::load(const std::string name, const file_type type) + { + arma_extra_debug_sigprint(); + + bool load_okay = false; + std::string err_msg; + + switch(type) + { + case auto_detect: + load_okay = diskio::load_auto_detect(*this, name, err_msg); + break; + + case raw_ascii: + load_okay = diskio::load_raw_ascii(*this, name, err_msg); + break; + + case arma_ascii: + load_okay = diskio::load_arma_ascii(*this, name, err_msg); + break; + + case csv_ascii: + return (*this).load(csv_name(name), type); + break; + + case ssv_ascii: + return (*this).load(csv_name(name), type); + break; + + case coord_ascii: + load_okay = diskio::load_coord_ascii(*this, name, err_msg); + break; + + case raw_binary: + load_okay = diskio::load_raw_binary(*this, name, err_msg); + break; + + case arma_binary: + load_okay = diskio::load_arma_binary(*this, name, err_msg); + break; + + case pgm_binary: + load_okay = diskio::load_pgm_binary(*this, name, err_msg); + break; + + case hdf5_binary: + return (*this).load(hdf5_name(name)); + break; + + case hdf5_binary_trans: // kept for compatibility with earlier versions of Armadillo + return (*this).load(hdf5_name(name, std::string(), hdf5_opts::trans)); + break; + + default: + arma_debug_warn_level(1, "Mat::load(): unsupported file type"); + load_okay = false; + } + + if(load_okay == false) + { + if(err_msg.length() > 0) + { + arma_debug_warn_level(3, "Mat::load(): ", err_msg, "; file: ", name); + } + else + { + arma_debug_warn_level(3, "Mat::load(): read failed; file: ", name); + } + } + + if(load_okay == false) { (*this).soft_reset(); } + + return load_okay; + } + + + +template +inline +bool +Mat::load(const hdf5_name& spec, const file_type type) + { + arma_extra_debug_sigprint(); + + if( (type != hdf5_binary) && (type != hdf5_binary_trans) ) + { + arma_stop_runtime_error("Mat::load(): unsupported file type for hdf5_name()"); + return false; + } + + bool load_okay = false; + std::string err_msg; + + const bool do_trans = bool(spec.opts.flags & hdf5_opts::flag_trans) || (type == hdf5_binary_trans); + + if(do_trans) + { + Mat tmp; + + load_okay = diskio::load_hdf5_binary(tmp, spec, err_msg); + + if(load_okay) { op_strans::apply_mat_noalias(*this, tmp); } + } + else + { + load_okay = diskio::load_hdf5_binary(*this, spec, err_msg); + } + + + if(load_okay == false) + { + if(err_msg.length() > 0) + { + arma_debug_warn_level(3, "Mat::load(): ", err_msg, "; file: ", spec.filename); + } + else + { + arma_debug_warn_level(3, "Mat::load(): read failed; file: ", spec.filename); + } + } + + if(load_okay == false) { (*this).soft_reset(); } + + return load_okay; + } + + + +template +inline +bool +Mat::load(const csv_name& spec, const file_type type) + { + arma_extra_debug_sigprint(); + + if( (type != csv_ascii) && (type != ssv_ascii) ) + { + arma_stop_runtime_error("Mat::load(): unsupported file type for csv_name()"); + return false; + } + + const bool do_trans = bool(spec.opts.flags & csv_opts::flag_trans ); + const bool no_header = bool(spec.opts.flags & csv_opts::flag_no_header ); + const bool with_header = bool(spec.opts.flags & csv_opts::flag_with_header) && (no_header == false); + const bool use_semicolon = bool(spec.opts.flags & csv_opts::flag_semicolon ) || (type == ssv_ascii); + const bool strict = bool(spec.opts.flags & csv_opts::flag_strict ); + + arma_extra_debug_print("Mat::load(csv_name): enabled flags:"); + + if(do_trans ) { arma_extra_debug_print("trans"); } + if(no_header ) { arma_extra_debug_print("no_header"); } + if(with_header ) { arma_extra_debug_print("with_header"); } + if(use_semicolon) { arma_extra_debug_print("semicolon"); } + if(strict ) { arma_extra_debug_print("strict"); } + + const char separator = (use_semicolon) ? char(';') : char(','); + + bool load_okay = false; + std::string err_msg; + + if(do_trans) + { + Mat tmp_mat; + + load_okay = diskio::load_csv_ascii(tmp_mat, spec.filename, err_msg, spec.header_rw, with_header, separator, strict); + + if(load_okay) + { + (*this) = tmp_mat.st(); + + if(with_header) + { + // field::set_size() preserves data if the number of elements hasn't changed + spec.header_rw.set_size(spec.header_rw.n_elem, 1); + } + } + } + else + { + load_okay = diskio::load_csv_ascii(*this, spec.filename, err_msg, spec.header_rw, with_header, separator, strict); + } + + if(load_okay == false) + { + if(err_msg.length() > 0) + { + arma_debug_warn_level(3, "Mat::load(): ", err_msg, "; file: ", spec.filename); + } + else + { + arma_debug_warn_level(3, "Mat::load(): read failed; file: ", spec.filename); + } + } + else + { + const uword load_n_cols = (do_trans) ? (*this).n_rows : (*this).n_cols; + + if(with_header && (spec.header_rw.n_elem != load_n_cols)) + { + arma_debug_warn_level(3, "Mat::load(): size mismatch between header and matrix"); + } + } + + if(load_okay == false) + { + (*this).soft_reset(); + + if(with_header) { spec.header_rw.reset(); } + } + + return load_okay; + } + + + +//! load a matrix from a stream +template +inline +bool +Mat::load(std::istream& is, const file_type type) + { + arma_extra_debug_sigprint(); + + bool load_okay = false; + std::string err_msg; + + switch(type) + { + case auto_detect: + load_okay = diskio::load_auto_detect(*this, is, err_msg); + break; + + case raw_ascii: + load_okay = diskio::load_raw_ascii(*this, is, err_msg); + break; + + case arma_ascii: + load_okay = diskio::load_arma_ascii(*this, is, err_msg); + break; + + case csv_ascii: + load_okay = diskio::load_csv_ascii(*this, is, err_msg, char(','), false); + break; + + case ssv_ascii: + load_okay = diskio::load_csv_ascii(*this, is, err_msg, char(';'), false); + break; + + case coord_ascii: + load_okay = diskio::load_coord_ascii(*this, is, err_msg); + break; + + case raw_binary: + load_okay = diskio::load_raw_binary(*this, is, err_msg); + break; + + case arma_binary: + load_okay = diskio::load_arma_binary(*this, is, err_msg); + break; + + case pgm_binary: + load_okay = diskio::load_pgm_binary(*this, is, err_msg); + break; + + default: + arma_debug_warn_level(1, "Mat::load(): unsupported file type"); + load_okay = false; + } + + if(load_okay == false) + { + if(err_msg.length() > 0) + { + arma_debug_warn_level(3, "Mat::load(): ", err_msg); + } + else + { + arma_debug_warn_level(3, "Mat::load(): stream read failed"); + } + } + + if(load_okay == false) { (*this).soft_reset(); } + + return load_okay; + } + + + +template +inline +bool +Mat::quiet_save(const std::string name, const file_type type) const + { + arma_extra_debug_sigprint(); + + return (*this).save(name, type); + } + + + +template +inline +bool +Mat::quiet_save(const hdf5_name& spec, const file_type type) const + { + arma_extra_debug_sigprint(); + + return (*this).save(spec, type); + } + + + +template +inline +bool +Mat::quiet_save(const csv_name& spec, const file_type type) const + { + arma_extra_debug_sigprint(); + + return (*this).save(spec, type); + } + + + +template +inline +bool +Mat::quiet_save(std::ostream& os, const file_type type) const + { + arma_extra_debug_sigprint(); + + return (*this).save(os, type); + } + + + +template +inline +bool +Mat::quiet_load(const std::string name, const file_type type) + { + arma_extra_debug_sigprint(); + + return (*this).load(name, type); + } + + + +template +inline +bool +Mat::quiet_load(const hdf5_name& spec, const file_type type) + { + arma_extra_debug_sigprint(); + + return (*this).load(spec, type); + } + + + +template +inline +bool +Mat::quiet_load(const csv_name& spec, const file_type type) + { + arma_extra_debug_sigprint(); + + return (*this).load(spec, type); + } + + + +template +inline +bool +Mat::quiet_load(std::istream& is, const file_type type) + { + arma_extra_debug_sigprint(); + + return (*this).load(is, type); + } + + + +template +inline +Mat::row_iterator::row_iterator() + : M (nullptr) + , current_row(0 ) + , current_col(0 ) + { + arma_extra_debug_sigprint(); + + // NOTE: this instance of row_iterator is invalid (it does not point to a valid element) + } + + + +template +inline +Mat::row_iterator::row_iterator(const row_iterator& X) + : M (X.M ) + , current_row(X.current_row) + , current_col(X.current_col) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +Mat::row_iterator::row_iterator(Mat& in_M, const uword in_row, const uword in_col) + : M (&in_M ) + , current_row(in_row) + , current_col(in_col) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +eT& +Mat::row_iterator::operator*() + { + return M->at(current_row,current_col); + } + + + +template +inline +typename Mat::row_iterator& +Mat::row_iterator::operator++() + { + current_col++; + + if(current_col == M->n_cols) + { + current_col = 0; + current_row++; + } + + return *this; + } + + + +template +inline +typename Mat::row_iterator +Mat::row_iterator::operator++(int) + { + typename Mat::row_iterator temp(*this); + + ++(*this); + + return temp; + } + + + +template +inline +typename Mat::row_iterator& +Mat::row_iterator::operator--() + { + if(current_col > 0) + { + current_col--; + } + else + { + if(current_row > 0) + { + current_col = M->n_cols - 1; + current_row--; + } + } + + return *this; + } + + + +template +inline +typename Mat::row_iterator +Mat::row_iterator::operator--(int) + { + typename Mat::row_iterator temp(*this); + + --(*this); + + return temp; + } + + + +template +inline +bool +Mat::row_iterator::operator!=(const typename Mat::row_iterator& X) const + { + return ( (current_row != X.current_row) || (current_col != X.current_col) ); + } + + + +template +inline +bool +Mat::row_iterator::operator==(const typename Mat::row_iterator& X) const + { + return ( (current_row == X.current_row) && (current_col == X.current_col) ); + } + + + +template +inline +bool +Mat::row_iterator::operator!=(const typename Mat::const_row_iterator& X) const + { + return ( (current_row != X.current_row) || (current_col != X.current_col) ); + } + + + +template +inline +bool +Mat::row_iterator::operator==(const typename Mat::const_row_iterator& X) const + { + return ( (current_row == X.current_row) && (current_col == X.current_col) ); + } + + + +template +inline +Mat::const_row_iterator::const_row_iterator() + : M (nullptr) + , current_row(0 ) + , current_col(0 ) + { + arma_extra_debug_sigprint(); + + // NOTE: this instance of const_row_iterator is invalid (it does not point to a valid element) + } + + + +template +inline +Mat::const_row_iterator::const_row_iterator(const typename Mat::row_iterator& X) + : M (X.M ) + , current_row(X.current_row) + , current_col(X.current_col) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +Mat::const_row_iterator::const_row_iterator(const typename Mat::const_row_iterator& X) + : M (X.M ) + , current_row(X.current_row) + , current_col(X.current_col) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +Mat::const_row_iterator::const_row_iterator(const Mat& in_M, const uword in_row, const uword in_col) + : M (&in_M ) + , current_row(in_row) + , current_col(in_col) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +const eT& +Mat::const_row_iterator::operator*() const + { + return M->at(current_row,current_col); + } + + + +template +inline +typename Mat::const_row_iterator& +Mat::const_row_iterator::operator++() + { + current_col++; + + if(current_col == M->n_cols) + { + current_col = 0; + current_row++; + } + + return *this; + } + + + +template +inline +typename Mat::const_row_iterator +Mat::const_row_iterator::operator++(int) + { + typename Mat::const_row_iterator temp(*this); + + ++(*this); + + return temp; + } + + + +template +inline +typename Mat::const_row_iterator& +Mat::const_row_iterator::operator--() + { + if(current_col > 0) + { + current_col--; + } + else + { + if(current_row > 0) + { + current_col = M->n_cols - 1; + current_row--; + } + } + + return *this; + } + + + +template +inline +typename Mat::const_row_iterator +Mat::const_row_iterator::operator--(int) + { + typename Mat::const_row_iterator temp(*this); + + --(*this); + + return temp; + } + + + +template +inline +bool +Mat::const_row_iterator::operator!=(const typename Mat::row_iterator& X) const + { + return ( (current_row != X.current_row) || (current_col != X.current_col) ); + } + + + +template +inline +bool +Mat::const_row_iterator::operator==(const typename Mat::row_iterator& X) const + { + return ( (current_row == X.current_row) && (current_col == X.current_col) ); + } + + + +template +inline +bool +Mat::const_row_iterator::operator!=(const typename Mat::const_row_iterator& X) const + { + return ( (current_row != X.current_row) || (current_col != X.current_col) ); + } + + + +template +inline +bool +Mat::const_row_iterator::operator==(const typename Mat::const_row_iterator& X) const + { + return ( (current_row == X.current_row) && (current_col == X.current_col) ); + } + + + +template +inline +Mat::row_col_iterator::row_col_iterator() + : M (nullptr) + , current_ptr(nullptr) + , current_col(0 ) + , current_row(0 ) + { + arma_extra_debug_sigprint(); + // Technically this iterator is invalid (it does not point to a valid element) + } + + + +template +inline +Mat::row_col_iterator::row_col_iterator(const row_col_iterator& in_it) + : M (in_it.M ) + , current_ptr(in_it.current_ptr) + , current_col(in_it.current_col) + , current_row(in_it.current_row) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +Mat::row_col_iterator::row_col_iterator(Mat& in_M, const uword in_row, const uword in_col) + : M (&in_M ) + , current_ptr(&in_M.at(in_row,in_col)) + , current_col(in_col ) + , current_row(in_row ) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +eT& +Mat::row_col_iterator::operator*() + { + return *current_ptr; + } + + + +template +inline +typename Mat::row_col_iterator& +Mat::row_col_iterator::operator++() + { + if(current_col < M->n_cols) + { + current_ptr++; + current_row++; + + // Check to see if we moved a column. + if(current_row == M->n_rows) + { + current_col++; + current_row = 0; + } + } + + return *this; + } + + + +template +inline +typename Mat::row_col_iterator +Mat::row_col_iterator::operator++(int) + { + typename Mat::row_col_iterator temp(*this); + + ++(*this); + + return temp; + } + + + +template +inline typename Mat::row_col_iterator& +Mat::row_col_iterator::operator--() + { + if(current_row > 0) + { + current_ptr--; + current_row--; + } + else + if(current_col > 0) + { + current_ptr--; + current_col--; + current_row = M->n_rows - 1; + } + + return *this; + } + + + +template +inline +typename Mat::row_col_iterator +Mat::row_col_iterator::operator--(int) + { + typename Mat::row_col_iterator temp(*this); + + --(*this); + + return temp; + } + + + +template +inline +uword +Mat::row_col_iterator::row() const + { + return current_row; + } + + + +template +inline +uword +Mat::row_col_iterator::col() const + { + return current_col; + } + + + +template +inline +bool +Mat::row_col_iterator::operator==(const row_col_iterator& rhs) const + { + return (current_ptr == rhs.current_ptr); + } + + + +template +inline +bool +Mat::row_col_iterator::operator!=(const row_col_iterator& rhs) const + { + return (current_ptr != rhs.current_ptr); + } + + + +template +inline +bool +Mat::row_col_iterator::operator==(const const_row_col_iterator& rhs) const + { + return (current_ptr == rhs.current_ptr); + } + + + +template +inline +bool +Mat::row_col_iterator::operator!=(const const_row_col_iterator& rhs) const + { + return (current_ptr != rhs.current_ptr); + } + + + +template +inline +Mat::const_row_col_iterator::const_row_col_iterator() + : M (nullptr) + , current_ptr(nullptr) + , current_col(0 ) + , current_row(0 ) + { + arma_extra_debug_sigprint(); + // Technically this iterator is invalid (it does not point to a valid element) + } + + + +template +inline +Mat::const_row_col_iterator::const_row_col_iterator(const row_col_iterator& in_it) + : M (in_it.M ) + , current_ptr(in_it.current_ptr) + , current_col(in_it.col() ) + , current_row(in_it.row() ) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +Mat::const_row_col_iterator::const_row_col_iterator(const const_row_col_iterator& in_it) + : M (in_it.M ) + , current_ptr(in_it.current_ptr) + , current_col(in_it.col() ) + , current_row(in_it.row() ) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +Mat::const_row_col_iterator::const_row_col_iterator(const Mat& in_M, const uword in_row, const uword in_col) + : M (&in_M ) + , current_ptr(&in_M.at(in_row,in_col)) + , current_col(in_col ) + , current_row(in_row ) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +const eT& +Mat::const_row_col_iterator::operator*() const + { + return *current_ptr; + } + + + +template +inline +typename Mat::const_row_col_iterator& +Mat::const_row_col_iterator::operator++() + { + if(current_col < M->n_cols) + { + current_ptr++; + current_row++; + + // Check to see if we moved a column. + if(current_row == M->n_rows) + { + current_col++; + current_row = 0; + } + } + + return *this; + } + + + +template +inline +typename Mat::const_row_col_iterator +Mat::const_row_col_iterator::operator++(int) + { + typename Mat::const_row_col_iterator temp(*this); + + ++(*this); + + return temp; + } + + + +template +inline +typename Mat::const_row_col_iterator& +Mat::const_row_col_iterator::operator--() + { + if(current_row > 0) + { + current_ptr--; + current_row--; + } + else + if(current_col > 0) + { + current_ptr--; + current_col--; + current_row = M->n_rows - 1; + } + + return *this; + } + + + +template +inline +typename Mat::const_row_col_iterator +Mat::const_row_col_iterator::operator--(int) + { + typename Mat::const_row_col_iterator temp(*this); + + --(*this); + + return temp; + } + + + +template +inline +uword +Mat::const_row_col_iterator::row() const + { + return current_row; + } + + + +template +inline +uword +Mat::const_row_col_iterator::col() const + { + return current_col; + } + + + +template +inline +bool +Mat::const_row_col_iterator::operator==(const const_row_col_iterator& rhs) const + { + return (current_ptr == rhs.current_ptr); + } + + + +template +inline +bool +Mat::const_row_col_iterator::operator!=(const const_row_col_iterator& rhs) const + { + return (current_ptr != rhs.current_ptr); + } + + + +template +inline +bool +Mat::const_row_col_iterator::operator==(const row_col_iterator& rhs) const + { + return (current_ptr == rhs.current_ptr); + } + + + +template +inline +bool +Mat::const_row_col_iterator::operator!=(const row_col_iterator& rhs) const + { + return (current_ptr != rhs.current_ptr); + } + + + +template +inline +typename Mat::iterator +Mat::begin() + { + arma_extra_debug_sigprint(); + + return memptr(); + } + + + +template +inline +typename Mat::const_iterator +Mat::begin() const + { + arma_extra_debug_sigprint(); + + return memptr(); + } + + + +template +inline +typename Mat::const_iterator +Mat::cbegin() const + { + arma_extra_debug_sigprint(); + + return memptr(); + } + + + +template +inline +typename Mat::iterator +Mat::end() + { + arma_extra_debug_sigprint(); + + return memptr() + n_elem; + } + + + +template +inline +typename Mat::const_iterator +Mat::end() const + { + arma_extra_debug_sigprint(); + + return memptr() + n_elem; + } + + + +template +inline +typename Mat::const_iterator +Mat::cend() const + { + arma_extra_debug_sigprint(); + + return memptr() + n_elem; + } + + + +template +inline +typename Mat::col_iterator +Mat::begin_col(const uword col_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (col_num >= n_cols), "Mat::begin_col(): index out of bounds" ); + + return colptr(col_num); + } + + + +template +inline +typename Mat::const_col_iterator +Mat::begin_col(const uword col_num) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (col_num >= n_cols), "Mat::begin_col(): index out of bounds" ); + + return colptr(col_num); + } + + + +template +inline +typename Mat::col_iterator +Mat::end_col(const uword col_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (col_num >= n_cols), "Mat::end_col(): index out of bounds" ); + + return colptr(col_num) + n_rows; + } + + + +template +inline +typename Mat::const_col_iterator +Mat::end_col(const uword col_num) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (col_num >= n_cols), "Mat::end_col(): index out of bounds" ); + + return colptr(col_num) + n_rows; + } + + + +template +inline +typename Mat::row_iterator +Mat::begin_row(const uword row_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (row_num >= n_rows), "Mat::begin_row(): index out of bounds" ); + + return typename Mat::row_iterator(*this, row_num, uword(0)); + } + + + +template +inline +typename Mat::const_row_iterator +Mat::begin_row(const uword row_num) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (row_num >= n_rows), "Mat::begin_row(): index out of bounds" ); + + return typename Mat::const_row_iterator(*this, row_num, uword(0)); + } + + + +template +inline +typename Mat::row_iterator +Mat::end_row(const uword row_num) + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (row_num >= n_rows), "Mat::end_row(): index out of bounds" ); + + return typename Mat::row_iterator(*this, (row_num + uword(1)), 0); + } + + + +template +inline +typename Mat::const_row_iterator +Mat::end_row(const uword row_num) const + { + arma_extra_debug_sigprint(); + + arma_debug_check_bounds( (row_num >= n_rows), "Mat::end_row(): index out of bounds" ); + + return typename Mat::const_row_iterator(*this, (row_num + uword(1)), 0); + } + + + +template +inline +typename Mat::row_col_iterator +Mat::begin_row_col() + { + return row_col_iterator(*this); + } + + + +template +inline +typename Mat::const_row_col_iterator +Mat::begin_row_col() const + { + return const_row_col_iterator(*this); + } + + + +template +inline typename Mat::row_col_iterator +Mat::end_row_col() + { + return row_col_iterator(*this, 0, n_cols); + } + + + +template +inline typename Mat::const_row_col_iterator +Mat::end_row_col() const + { + return const_row_col_iterator(*this, 0, n_cols); + } + + + +//! resets this matrix to an empty matrix +template +inline +void +Mat::clear() + { + reset(); + } + + + +//! returns true if the matrix has no elements +template +inline +bool +Mat::empty() const + { + return (n_elem == 0); + } + + + +//! returns the number of elements in this matrix +template +inline +uword +Mat::size() const + { + return n_elem; + } + + + +template +inline +eT& +Mat::front() + { + arma_debug_check( (n_elem == 0), "Mat::front(): matrix is empty" ); + + return access::rw(mem[0]); + } + + + +template +inline +const eT& +Mat::front() const + { + arma_debug_check( (n_elem == 0), "Mat::front(): matrix is empty" ); + + return mem[0]; + } + + + +template +inline +eT& +Mat::back() + { + arma_debug_check( (n_elem == 0), "Mat::back(): matrix is empty" ); + + return access::rw(mem[n_elem-1]); + } + + + +template +inline +const eT& +Mat::back() const + { + arma_debug_check( (n_elem == 0), "Mat::back(): matrix is empty" ); + + return mem[n_elem-1]; + } + + + +template +template +arma_inline +Mat::fixed::fixed() + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + if(arma_config::zero_init) + { + arma_extra_debug_print("Mat::fixed::constructor: zeroing memory"); + + eT* mem_use = (use_extra) ? &(mem_local_extra[0]) : &(mem_local[0]); + + arrayops::inplace_set_fixed( mem_use, eT(0) ); + } + } + + + +template +template +arma_inline +Mat::fixed::fixed(const fixed& X) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + eT* dest = (use_extra) ? mem_local_extra : mem_local; + const eT* src = (use_extra) ? X.mem_local_extra : X.mem_local; + + arrayops::copy( dest, src, fixed_n_elem ); + } + + + +template +template +inline +Mat::fixed::fixed(const fill::scalar_holder f) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + (*this).fill(f.scalar); + } + + + +template +template +template +inline +Mat::fixed::fixed(const fill::fill_class&) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + if(is_same_type::yes) { (*this).zeros(); } + if(is_same_type::yes) { (*this).ones(); } + if(is_same_type::yes) { (*this).eye(); } + if(is_same_type::yes) { (*this).randu(); } + if(is_same_type::yes) { (*this).randn(); } + } + + + +template +template +template +inline +Mat::fixed::fixed(const Base& A) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + Mat::operator=(A.get_ref()); + } + + + +template +template +template +inline +Mat::fixed::fixed(const Base& A, const Base& B) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + Mat::init(A,B); + } + + + +template +template +inline +Mat::fixed::fixed(const eT* aux_mem) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + eT* dest = (use_extra) ? mem_local_extra : mem_local; + + arrayops::copy( dest, aux_mem, fixed_n_elem ); + } + + + +template +template +inline +Mat::fixed::fixed(const char* text) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + Mat::operator=(text); + } + + + +template +template +inline +Mat::fixed::fixed(const std::string& text) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + Mat::operator=(text); + } + + + +template +template +inline +Mat::fixed::fixed(const std::initializer_list& list) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + (*this).operator=(list); + } + + + +template +template +inline +Mat& +Mat::fixed::operator=(const std::initializer_list& list) + { + arma_extra_debug_sigprint(); + + const uword N = uword(list.size()); + + arma_debug_check( (N > fixed_n_elem), "Mat::fixed: initialiser list is too long" ); + + eT* this_mem = (*this).memptr(); + + arrayops::copy( this_mem, list.begin(), N ); + + for(uword iq=N; iq < fixed_n_elem; ++iq) { this_mem[iq] = eT(0); } + + return *this; + } + + + +template +template +inline +Mat::fixed::fixed(const std::initializer_list< std::initializer_list >& list) + : Mat( arma_fixed_indicator(), fixed_n_rows, fixed_n_cols, 0, ((use_extra) ? mem_local_extra : Mat::mem_local) ) + { + arma_extra_debug_sigprint_this(this); + + Mat::init(list); + } + + + +template +template +inline +Mat& +Mat::fixed::operator=(const std::initializer_list< std::initializer_list >& list) + { + arma_extra_debug_sigprint(); + + Mat::init(list); + + return *this; + } + + + +template +template +arma_inline +Mat& +Mat::fixed::operator=(const fixed& X) + { + arma_extra_debug_sigprint(); + + if(this != &X) + { + eT* dest = (use_extra) ? mem_local_extra : mem_local; + const eT* src = (use_extra) ? X.mem_local_extra : X.mem_local; + + arrayops::copy( dest, src, fixed_n_elem ); + } + + return *this; + } + + + +#if defined(ARMA_GOOD_COMPILER) + + template + template + template + inline + Mat& + Mat::fixed::operator=(const eOp& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + + const bool bad_alias = (eOp::proxy_type::has_subview && X.P.is_alias(*this)); + + if(bad_alias) { const Mat tmp(X); (*this) = tmp; return *this; } + + arma_debug_assert_same_size(fixed_n_rows, fixed_n_cols, X.get_n_rows(), X.get_n_cols(), "Mat::fixed::operator="); + + eop_type::apply(*this, X); + + return *this; + } + + + + template + template + template + inline + Mat& + Mat::fixed::operator=(const eGlue& X) + { + arma_extra_debug_sigprint(); + + arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); + arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); + + const bool bad_alias = + ( + (eGlue::proxy1_type::has_subview && X.P1.is_alias(*this)) + || + (eGlue::proxy2_type::has_subview && X.P2.is_alias(*this)) + ); + + if(bad_alias) { const Mat tmp(X); (*this) = tmp; return *this; } + + arma_debug_assert_same_size(fixed_n_rows, fixed_n_cols, X.get_n_rows(), X.get_n_cols(), "Mat::fixed::operator="); + + eglue_type::apply(*this, X); + + return *this; + } + +#endif + + + +template +template +arma_inline +const Op< typename Mat::template fixed::Mat_fixed_type, op_htrans > +Mat::fixed::t() const + { + return Op< typename Mat::template fixed::Mat_fixed_type, op_htrans >(*this); + } + + + +template +template +arma_inline +const Op< typename Mat::template fixed::Mat_fixed_type, op_htrans > +Mat::fixed::ht() const + { + return Op< typename Mat::template fixed::Mat_fixed_type, op_htrans >(*this); + } + + + +template +template +arma_inline +const Op< typename Mat::template fixed::Mat_fixed_type, op_strans > +Mat::fixed::st() const + { + return Op< typename Mat::template fixed::Mat_fixed_type, op_strans >(*this); + } + + + +template +template +arma_inline +const eT& +Mat::fixed::at_alt(const uword ii) const + { + #if defined(ARMA_HAVE_ALIGNED_ATTRIBUTE) + + return (use_extra) ? mem_local_extra[ii] : mem_local[ii]; + + #else + const eT* mem_aligned = (use_extra) ? mem_local_extra : mem_local; + + memory::mark_as_aligned(mem_aligned); + + return mem_aligned[ii]; + #endif + } + + + +template +template +arma_inline +eT& +Mat::fixed::operator[] (const uword ii) + { + return (use_extra) ? mem_local_extra[ii] : mem_local[ii]; + } + + + +template +template +arma_inline +const eT& +Mat::fixed::operator[] (const uword ii) const + { + return (use_extra) ? mem_local_extra[ii] : mem_local[ii]; + } + + + +template +template +arma_inline +eT& +Mat::fixed::at(const uword ii) + { + return (use_extra) ? mem_local_extra[ii] : mem_local[ii]; + } + + + +template +template +arma_inline +const eT& +Mat::fixed::at(const uword ii) const + { + return (use_extra) ? mem_local_extra[ii] : mem_local[ii]; + } + + + +template +template +arma_inline +eT& +Mat::fixed::operator() (const uword ii) + { + arma_debug_check_bounds( (ii >= fixed_n_elem), "Mat::operator(): index out of bounds" ); + + return (use_extra) ? mem_local_extra[ii] : mem_local[ii]; + } + + + +template +template +arma_inline +const eT& +Mat::fixed::operator() (const uword ii) const + { + arma_debug_check_bounds( (ii >= fixed_n_elem), "Mat::operator(): index out of bounds" ); + + return (use_extra) ? mem_local_extra[ii] : mem_local[ii]; + } + + + +#if defined(__cpp_multidimensional_subscript) + + template + template + arma_inline + eT& + Mat::fixed::operator[] (const uword in_row, const uword in_col) + { + const uword iq = in_row + in_col*fixed_n_rows; + + return (use_extra) ? mem_local_extra[iq] : mem_local[iq]; + } + + + + template + template + arma_inline + const eT& + Mat::fixed::operator[] (const uword in_row, const uword in_col) const + { + const uword iq = in_row + in_col*fixed_n_rows; + + return (use_extra) ? mem_local_extra[iq] : mem_local[iq]; + } + +#endif + + + +template +template +arma_inline +eT& +Mat::fixed::at(const uword in_row, const uword in_col) + { + const uword iq = in_row + in_col*fixed_n_rows; + + return (use_extra) ? mem_local_extra[iq] : mem_local[iq]; + } + + + +template +template +arma_inline +const eT& +Mat::fixed::at(const uword in_row, const uword in_col) const + { + const uword iq = in_row + in_col*fixed_n_rows; + + return (use_extra) ? mem_local_extra[iq] : mem_local[iq]; + } + + + +template +template +arma_inline +eT& +Mat::fixed::operator() (const uword in_row, const uword in_col) + { + arma_debug_check_bounds( ((in_row >= fixed_n_rows) || (in_col >= fixed_n_cols)), "Mat::operator(): index out of bounds" ); + + const uword iq = in_row + in_col*fixed_n_rows; + + return (use_extra) ? mem_local_extra[iq] : mem_local[iq]; + } + + + +template +template +arma_inline +const eT& +Mat::fixed::operator() (const uword in_row, const uword in_col) const + { + arma_debug_check_bounds( ((in_row >= fixed_n_rows) || (in_col >= fixed_n_cols)), "Mat::operator(): index out of bounds" ); + + const uword iq = in_row + in_col*fixed_n_rows; + + return (use_extra) ? mem_local_extra[iq] : mem_local[iq]; + } + + + +template +template +arma_inline +eT* +Mat::fixed::colptr(const uword in_col) + { + eT* mem_actual = (use_extra) ? mem_local_extra : mem_local; + + return & access::rw(mem_actual[in_col*fixed_n_rows]); + } + + + +template +template +arma_inline +const eT* +Mat::fixed::colptr(const uword in_col) const + { + const eT* mem_actual = (use_extra) ? mem_local_extra : mem_local; + + return & mem_actual[in_col*fixed_n_rows]; + } + + + +template +template +arma_inline +eT* +Mat::fixed::memptr() + { + return (use_extra) ? mem_local_extra : mem_local; + } + + + +template +template +arma_inline +const eT* +Mat::fixed::memptr() const + { + return (use_extra) ? mem_local_extra : mem_local; + } + + + +template +template +arma_inline +bool +Mat::fixed::is_vec() const + { + return ( (fixed_n_rows == 1) || (fixed_n_cols == 1) ); + } + + + +template +template +inline +const Mat& +Mat::fixed::fill(const eT val) + { + arma_extra_debug_sigprint(); + + eT* mem_use = (use_extra) ? &(mem_local_extra[0]) : &(mem_local[0]); + + arrayops::inplace_set_fixed( mem_use, val ); + + return *this; + } + + + +template +template +inline +const Mat& +Mat::fixed::zeros() + { + arma_extra_debug_sigprint(); + + eT* mem_use = (use_extra) ? &(mem_local_extra[0]) : &(mem_local[0]); + + arrayops::inplace_set_fixed( mem_use, eT(0) ); + + return *this; + } + + + +template +template +inline +const Mat& +Mat::fixed::ones() + { + arma_extra_debug_sigprint(); + + eT* mem_use = (use_extra) ? &(mem_local_extra[0]) : &(mem_local[0]); + + arrayops::inplace_set_fixed( mem_use, eT(1) ); + + return *this; + } + + + +//! prefix ++ +template +inline +void +Mat_aux::prefix_pp(Mat& x) + { + eT* memptr = x.memptr(); + const uword n_elem = x.n_elem; + + uword i,j; + + for(i=0, j=1; j +inline +void +Mat_aux::prefix_pp(Mat< std::complex >& x) + { + x += T(1); + } + + + +//! postfix ++ +template +inline +void +Mat_aux::postfix_pp(Mat& x) + { + eT* memptr = x.memptr(); + const uword n_elem = x.n_elem; + + uword i,j; + + for(i=0, j=1; j +inline +void +Mat_aux::postfix_pp(Mat< std::complex >& x) + { + x += T(1); + } + + + +//! prefix -- +template +inline +void +Mat_aux::prefix_mm(Mat& x) + { + eT* memptr = x.memptr(); + const uword n_elem = x.n_elem; + + uword i,j; + + for(i=0, j=1; j +inline +void +Mat_aux::prefix_mm(Mat< std::complex >& x) + { + x -= T(1); + } + + + +//! postfix -- +template +inline +void +Mat_aux::postfix_mm(Mat& x) + { + eT* memptr = x.memptr(); + const uword n_elem = x.n_elem; + + uword i,j; + + for(i=0, j=1; j +inline +void +Mat_aux::postfix_mm(Mat< std::complex >& x) + { + x -= T(1); + } + + + +template +inline +void +Mat_aux::set_real(Mat& out, const Base& X) + { + arma_extra_debug_sigprint(); + + const unwrap tmp(X.get_ref()); + const Mat& A = tmp.M; + + arma_debug_assert_same_size( out, A, "Mat::set_real()" ); + + out = A; + } + + + +template +inline +void +Mat_aux::set_imag(Mat&, const Base&) + { + arma_extra_debug_sigprint(); + } + + + +template +inline +void +Mat_aux::set_real(Mat< std::complex >& out, const Base& X) + { + arma_extra_debug_sigprint(); + + typedef typename std::complex eT; + + const Proxy P(X.get_ref()); + + const uword local_n_rows = P.get_n_rows(); + const uword local_n_cols = P.get_n_cols(); + + arma_debug_assert_same_size( out.n_rows, out.n_cols, local_n_rows, local_n_cols, "Mat::set_real()" ); + + eT* out_mem = out.memptr(); + + if(Proxy::use_at == false) + { + typedef typename Proxy::ea_type ea_type; + + ea_type A = P.get_ea(); + + const uword N = out.n_elem; + + for(uword i=0; i +inline +void +Mat_aux::set_imag(Mat< std::complex >& out, const Base& X) + { + arma_extra_debug_sigprint(); + + typedef typename std::complex eT; + + const Proxy P(X.get_ref()); + + const uword local_n_rows = P.get_n_rows(); + const uword local_n_cols = P.get_n_cols(); + + arma_debug_assert_same_size( out.n_rows, out.n_cols, local_n_rows, local_n_cols, "Mat::set_imag()" ); + + eT* out_mem = out.memptr(); + + if(Proxy::use_at == false) + { + typedef typename Proxy::ea_type ea_type; + + ea_type A = P.get_ea(); + + const uword N = out.n_elem; + + for(uword i=0; i