// 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_hot arma_inline void arrayops::copy(eT* dest, const eT* src, const uword n_elem) { if(is_cx::no) { if(n_elem <= 9) { arrayops::copy_small(dest, src, n_elem); } else { std::memcpy(dest, src, n_elem*sizeof(eT)); } } else { if(n_elem > 0) { std::memcpy(dest, src, n_elem*sizeof(eT)); } } } template arma_cold inline void arrayops::copy_small(eT* dest, const eT* src, const uword n_elem) { switch(n_elem) { case 9: dest[ 8] = src[ 8]; // fallthrough case 8: dest[ 7] = src[ 7]; // fallthrough case 7: dest[ 6] = src[ 6]; // fallthrough case 6: dest[ 5] = src[ 5]; // fallthrough case 5: dest[ 4] = src[ 4]; // fallthrough case 4: dest[ 3] = src[ 3]; // fallthrough case 3: dest[ 2] = src[ 2]; // fallthrough case 2: dest[ 1] = src[ 1]; // fallthrough case 1: dest[ 0] = src[ 0]; // fallthrough default: ; } } template inline void arrayops::fill_zeros(eT* dest, const uword n_elem) { typedef typename get_pod_type::result pod_type; if(std::numeric_limits::is_integer || std::numeric_limits::is_iec559) { if(n_elem > 0) { std::memset((void*)dest, 0, sizeof(eT)*n_elem); } } else { arrayops::inplace_set_simple(dest, eT(0), n_elem); } } template arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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_hot arma_inline void arrayops::convert_cx_scalar ( out_eT& out, const std::complex& in, const typename arma_not_cx::result* junk ) { arma_ignore(junk); out = out_eT( in.real() ); } template arma_hot 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 arma_hot 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; } 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) ); dest++; (*dest) = (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) ); dest++; } if((j-1) < n_elem) { const in_eT tmp_i = (*src); // dest[i] = out_eT( tmp_i ); (*dest) = (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) ); } } template arma_hot inline void arrayops::convert_cx(out_eT* dest, const in_eT* src, const uword n_elem) { uword j; for(j=1; j arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 { if( (n_elem <= 9) && (is_cx::no) ) { arrayops::inplace_set_small(dest, val, n_elem); } else { arrayops::inplace_set_simple(dest, val, n_elem); } } } template arma_hot 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 arma_hot 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 arma_cold inline void arrayops::inplace_set_small(eT* dest, const eT val, const uword n_elem) { switch(n_elem) { case 9: dest[ 8] = val; // fallthrough case 8: dest[ 7] = val; // fallthrough case 7: dest[ 6] = val; // fallthrough case 6: dest[ 5] = val; // fallthrough case 5: dest[ 4] = val; // fallthrough case 4: dest[ 3] = val; // fallthrough case 3: dest[ 2] = val; // fallthrough case 2: dest[ 1] = val; // fallthrough case 1: dest[ 0] = val; // fallthrough default:; } } template arma_hot inline void arrayops::inplace_set_fixed(eT* dest, const eT val) { for(uword i=0; i arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot 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 arma_hot inline eT arrayops::accumulate(const eT* src, const uword n_elem) { #if defined(__FINITE_MATH_ONLY__) && (__FINITE_MATH_ONLY__ > 0) { eT acc = eT(0); if(memory::is_aligned(src)) { memory::mark_as_aligned(src); for(uword i=0; i arma_hot 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 arma_hot 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 arma_hot 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 arma_hot inline bool arrayops::is_finite(const eT* src, const uword n_elem) { uword j; for(j=1; j arma_hot inline bool arrayops::has_inf(const eT* src, const uword n_elem) { uword j; for(j=1; j arma_hot inline bool arrayops::has_nan(const eT* src, const uword n_elem) { uword j; for(j=1; j