// 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 arrayops //! @{ template arma_inline void arrayops::copy(eT* dest, const eT* src, const uword n_elem) { if( (dest == src) || (n_elem == 0) ) { return; } std::memcpy(dest, src, n_elem*sizeof(eT)); } template inline void arrayops::fill_zeros(eT* dest, const uword n_elem) { typedef typename get_pod_type::result pod_type; if(n_elem == 0) { return; } if(std::numeric_limits::is_integer || std::numeric_limits::is_iec559) { std::memset((void*)dest, 0, sizeof(eT)*n_elem); } else { arrayops::inplace_set_simple(dest, eT(0), n_elem); } } template inline void arrayops::replace(eT* mem, const uword n_elem, const eT old_val, const eT new_val) { if(arma_isnan(old_val)) { for(uword i=0; i inline void arrayops::clean(eT* mem, const uword n_elem, const eT abs_limit, const typename arma_not_cx::result* junk) { arma_ignore(junk); for(uword i=0; i inline void arrayops::clean(std::complex* mem, const uword n_elem, const T abs_limit) { typedef typename std::complex eT; for(uword i=0; i(T(0), val_imag); } else if(std::abs(val_imag) <= abs_limit) { val = std::complex(val_real, T(0)); } } } template inline void arrayops::clamp(eT* mem, const uword n_elem, const eT min_val, const eT max_val, const typename arma_not_cx::result* junk) { arma_ignore(junk); for(uword i=0; i max_val) ? max_val : val); } } template inline void arrayops::clamp(std::complex* mem, const uword n_elem, const std::complex& min_val, const std::complex& max_val) { typedef typename std::complex eT; const T min_val_real = std::real(min_val); const T min_val_imag = std::imag(min_val); const T max_val_real = std::real(max_val); const T max_val_imag = std::imag(max_val); for(uword i=0; i max_val_real) ? max_val_real : val_real); val_imag = (val_imag < min_val_imag) ? min_val_imag : ((val_imag > max_val_imag) ? max_val_imag : val_imag); val = std::complex(val_real,val_imag); } } template arma_inline void arrayops::convert_cx_scalar ( out_eT& out, const in_eT& in, const typename arma_not_cx::result* junk1, const typename arma_not_cx< in_eT>::result* junk2 ) { arma_ignore(junk1); arma_ignore(junk2); out = out_eT(in); } template arma_inline void arrayops::convert_cx_scalar ( out_eT& out, const std::complex& in, const typename arma_not_cx::result* junk ) { arma_ignore(junk); const in_T val = in.real(); const bool conversion_ok = (std::is_integral::value && std::is_floating_point::value) ? arma_isfinite(val) : true; out = conversion_ok ? out_eT(val) : out_eT(0); } template arma_inline void arrayops::convert_cx_scalar ( std::complex& out, const std::complex< in_T>& in ) { typedef std::complex out_eT; out = out_eT(in); } template inline void arrayops::convert(out_eT* dest, const in_eT* src, const uword n_elem) { if(is_same_type::value) { const out_eT* src2 = (const out_eT*)src; if(dest != src2) { arrayops::copy(dest, src2, n_elem); } return; } const bool check_finite = (std::is_integral::value && std::is_floating_point::value); uword j; for(j=1; j::value) ? out_eT( tmp_i ) : ( cond_rel< is_signed::value >::lt(tmp_i, in_eT(0)) ? out_eT(0) : out_eT(tmp_i) ) ) : out_eT(0); dest++; (*dest) = ok_j ? ( (is_signed::value) ? out_eT( tmp_j ) : ( cond_rel< is_signed::value >::lt(tmp_j, in_eT(0)) ? out_eT(0) : out_eT(tmp_j) ) ) : out_eT(0); dest++; } if((j-1) < n_elem) { const in_eT tmp_i = (*src); // dest[i] = out_eT( tmp_i ); const bool ok_i = check_finite ? arma_isfinite(tmp_i) : true; (*dest) = ok_i ? ( (is_signed::value) ? out_eT( tmp_i ) : ( cond_rel< is_signed::value >::lt(tmp_i, in_eT(0)) ? out_eT(0) : out_eT(tmp_i) ) ) : out_eT(0); } } template inline void arrayops::convert_cx(out_eT* dest, const in_eT* src, const uword n_elem) { uword j; for(j=1; j inline void arrayops::inplace_plus(eT* dest, const eT* src, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); if(memory::is_aligned(src)) { memory::mark_as_aligned(src); arrayops::inplace_plus_base(dest, src, n_elem); } else { arrayops::inplace_plus_base(dest, src, n_elem); } } else { if(memory::is_aligned(src)) { memory::mark_as_aligned(src); arrayops::inplace_plus_base(dest, src, n_elem); } else { arrayops::inplace_plus_base(dest, src, n_elem); } } } template inline void arrayops::inplace_minus(eT* dest, const eT* src, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); if(memory::is_aligned(src)) { memory::mark_as_aligned(src); arrayops::inplace_minus_base(dest, src, n_elem); } else { arrayops::inplace_minus_base(dest, src, n_elem); } } else { if(memory::is_aligned(src)) { memory::mark_as_aligned(src); arrayops::inplace_minus_base(dest, src, n_elem); } else { arrayops::inplace_minus_base(dest, src, n_elem); } } } template inline void arrayops::inplace_mul(eT* dest, const eT* src, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); if(memory::is_aligned(src)) { memory::mark_as_aligned(src); arrayops::inplace_mul_base(dest, src, n_elem); } else { arrayops::inplace_mul_base(dest, src, n_elem); } } else { if(memory::is_aligned(src)) { memory::mark_as_aligned(src); arrayops::inplace_mul_base(dest, src, n_elem); } else { arrayops::inplace_mul_base(dest, src, n_elem); } } } template inline void arrayops::inplace_div(eT* dest, const eT* src, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); if(memory::is_aligned(src)) { memory::mark_as_aligned(src); arrayops::inplace_div_base(dest, src, n_elem); } else { arrayops::inplace_div_base(dest, src, n_elem); } } else { if(memory::is_aligned(src)) { memory::mark_as_aligned(src); arrayops::inplace_div_base(dest, src, n_elem); } else { arrayops::inplace_div_base(dest, src, n_elem); } } } template inline void arrayops::inplace_plus_base(eT* dest, const eT* src, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline void arrayops::inplace_minus_base(eT* dest, const eT* src, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline void arrayops::inplace_mul_base(eT* dest, const eT* src, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline void arrayops::inplace_div_base(eT* dest, const eT* src, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline void arrayops::inplace_set(eT* dest, const eT val, const uword n_elem) { if(val == eT(0)) { arrayops::fill_zeros(dest, n_elem); } else { arrayops::inplace_set_simple(dest, val, n_elem); } } template inline void arrayops::inplace_set_simple(eT* dest, const eT val, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); arrayops::inplace_set_base(dest, val, n_elem); } else { arrayops::inplace_set_base(dest, val, n_elem); } } template inline void arrayops::inplace_set_base(eT* dest, const eT val, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline void arrayops::inplace_set_fixed(eT* dest, const eT val) { for(uword i=0; i inline void arrayops::inplace_plus(eT* dest, const eT val, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); arrayops::inplace_plus_base(dest, val, n_elem); } else { arrayops::inplace_plus_base(dest, val, n_elem); } } template inline void arrayops::inplace_minus(eT* dest, const eT val, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); arrayops::inplace_minus_base(dest, val, n_elem); } else { arrayops::inplace_minus_base(dest, val, n_elem); } } template inline void arrayops::inplace_mul(eT* dest, const eT val, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); arrayops::inplace_mul_base(dest, val, n_elem); } else { arrayops::inplace_mul_base(dest, val, n_elem); } } template inline void arrayops::inplace_div(eT* dest, const eT val, const uword n_elem) { if(memory::is_aligned(dest)) { memory::mark_as_aligned(dest); arrayops::inplace_div_base(dest, val, n_elem); } else { arrayops::inplace_div_base(dest, val, n_elem); } } template inline void arrayops::inplace_plus_base(eT* dest, const eT val, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline void arrayops::inplace_minus_base(eT* dest, const eT val, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline void arrayops::inplace_mul_base(eT* dest, const eT val, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline void arrayops::inplace_div_base(eT* dest, const eT val, const uword n_elem) { #if defined(ARMA_SIMPLE_LOOPS) { for(uword i=0; i inline eT arrayops::accumulate(const eT* src, const uword n_elem) { #if defined(__FAST_MATH__) { eT acc = eT(0); if(memory::is_aligned(src)) { memory::mark_as_aligned(src); for(uword i=0; i inline eT arrayops::product(const eT* src, const uword n_elem) { eT val1 = eT(1); eT val2 = eT(1); uword i,j; for(i=0, j=1; j inline bool arrayops::is_zero(const eT* mem, const uword n_elem, const eT abs_limit, const typename arma_not_cx::result* junk) { arma_ignore(junk); if(n_elem == 0) { return false; } if(abs_limit == eT(0)) { for(uword i=0; i abs_limit) { return false; } } } return true; } template inline bool arrayops::is_zero(const std::complex* mem, const uword n_elem, const T abs_limit) { typedef typename std::complex eT; if(n_elem == 0) { return false; } if(abs_limit == T(0)) { for(uword i=0; i abs_limit) { return false; } if(std::abs(std::imag(val)) > abs_limit) { return false; } } } return true; } template inline bool arrayops::is_finite(const eT* src, const uword n_elem) { uword j; for(j=1; j inline bool arrayops::has_inf(const eT* src, const uword n_elem) { uword j; for(j=1; j inline bool arrayops::has_nan(const eT* src, const uword n_elem) { uword j; for(j=1; j