// Copyright (C) 2011-2015 National ICT Australia (NICTA) // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------- // // Written by Conrad Sanderson - http://conradsanderson.id.au //! \addtogroup arrayops //! @{ template arma_hot arma_inline void arrayops::copy(eT* dest, const eT* src, const uword n_elem) { if( (n_elem <= 16) && (is_cx::no) ) { arrayops::copy_small(dest, src, n_elem); } else { std::memcpy(dest, src, n_elem*sizeof(eT)); } } template arma_hot inline void arrayops::copy_small(eT* dest, const eT* src, const uword n_elem) { switch(n_elem) { case 16: dest[15] = src[15]; case 15: dest[14] = src[14]; case 14: dest[13] = src[13]; case 13: dest[12] = src[12]; case 12: dest[11] = src[11]; case 11: dest[10] = src[10]; case 10: dest[ 9] = src[ 9]; case 9: dest[ 8] = src[ 8]; case 8: dest[ 7] = src[ 7]; case 7: dest[ 6] = src[ 6]; case 6: dest[ 5] = src[ 5]; case 5: dest[ 4] = src[ 4]; case 4: dest[ 3] = src[ 3]; case 3: dest[ 2] = src[ 2]; case 2: dest[ 1] = src[ 1]; case 1: dest[ 0] = src[ 0]; default: ; } } template arma_hot inline void arrayops::copy_forwards(eT* dest, const eT* src, const uword n_elem) { // can't use std::memcpy(), as we don't know how it copies data uword j; for(j=1; j < n_elem; j+=2) { const eT tmp_i = (*src); src++; const eT tmp_j = (*src); src++; (*dest) = tmp_i; dest++; (*dest) = tmp_j; dest++; } if((j-1) < n_elem) { (*dest) = (*src); } } template arma_hot inline void arrayops::copy_backwards(eT* dest, const eT* src, const uword n_elem) { // can't use std::memcpy(), as we don't know how it copies data // for(uword i=0; i < n_elem; ++i) // { // const uword j = n_elem-i-1; // // dest[j] = src[j]; // } if(n_elem > 0) { eT* dest_it = &(dest[n_elem-1]); const eT* src_it = &( src[n_elem-1]); uword j; for(j=1; j < n_elem; j+=2) { const eT tmp_i = (*src_it); src_it--; const eT tmp_j = (*src_it); src_it--; (*dest_it) = tmp_i; dest_it--; (*dest_it) = tmp_j; dest_it--; } if((j-1) < n_elem) { (*dest_it) = (*src_it); } } } template arma_hot inline void arrayops::fill_zeros(eT* dest, const uword n_elem) { arrayops::inplace_set(dest, eT(0), n_elem); } 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) { typedef typename get_pod_type::result pod_type; if( (n_elem <= 16) && (is_cx::no) ) { arrayops::inplace_set_small(dest, val, n_elem); } else { if( (val == eT(0)) && (std::numeric_limits::is_integer || (std::numeric_limits::is_iec559 && is_real::value)) ) { std::memset(dest, 0, sizeof(eT)*n_elem); } else { 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_hot inline void arrayops::inplace_set_small(eT* dest, const eT val, const uword n_elem) { switch(n_elem) { case 16: dest[15] = val; case 15: dest[14] = val; case 14: dest[13] = val; case 13: dest[12] = val; case 12: dest[11] = val; case 11: dest[10] = val; case 10: dest[ 9] = val; case 9: dest[ 8] = val; case 8: dest[ 7] = val; case 7: dest[ 6] = val; case 6: dest[ 5] = val; case 5: dest[ 4] = val; case 4: dest[ 3] = val; case 3: dest[ 2] = val; case 2: dest[ 1] = val; case 1: dest[ 0] = val; 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 arma_pure 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 arma_pure 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 arma_pure inline bool arrayops::is_finite(const eT* src, const uword n_elem) { uword j; for(j=1; j arma_hot arma_pure inline bool arrayops::has_inf(const eT* src, const uword n_elem) { uword j; for(j=1; j arma_hot arma_pure inline bool arrayops::has_nan(const eT* src, const uword n_elem) { uword j; for(j=1; j