Chris@49: // Copyright (C) 2011-2013 NICTA (www.nicta.com.au) Chris@49: // Copyright (C) 2011-2013 Conrad Sanderson Chris@49: // Chris@49: // This Source Code Form is subject to the terms of the Mozilla Public Chris@49: // License, v. 2.0. If a copy of the MPL was not distributed with this Chris@49: // file, You can obtain one at http://mozilla.org/MPL/2.0/. Chris@49: Chris@49: Chris@49: //! \addtogroup arrayops Chris@49: //! @{ Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: arma_inline Chris@49: void Chris@49: arrayops::copy(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: switch(n_elem) Chris@49: { Chris@49: default: Chris@49: arrayops::copy_big(dest, src, n_elem); Chris@49: break; Chris@49: case 8: Chris@49: dest[7] = src[7]; Chris@49: case 7: Chris@49: dest[6] = src[6]; Chris@49: case 6: Chris@49: dest[5] = src[5]; Chris@49: case 5: Chris@49: dest[4] = src[4]; Chris@49: case 4: Chris@49: dest[3] = src[3]; Chris@49: case 3: Chris@49: dest[2] = src[2]; Chris@49: case 2: Chris@49: dest[1] = src[1]; Chris@49: case 1: Chris@49: dest[0] = src[0]; Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: void Chris@49: arrayops::copy_big(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: switch(n_elem) Chris@49: { Chris@49: default: Chris@49: std::memcpy(dest, src, n_elem*sizeof(eT)); Chris@49: break; Chris@49: case 32: Chris@49: dest[31] = src[31]; Chris@49: case 31: Chris@49: dest[30] = src[30]; Chris@49: case 30: Chris@49: dest[29] = src[29]; Chris@49: case 29: Chris@49: dest[28] = src[28]; Chris@49: case 28: Chris@49: dest[27] = src[27]; Chris@49: case 27: Chris@49: dest[26] = src[26]; Chris@49: case 26: Chris@49: dest[25] = src[25]; Chris@49: case 25: Chris@49: dest[24] = src[24]; Chris@49: case 24: Chris@49: dest[23] = src[23]; Chris@49: case 23: Chris@49: dest[22] = src[22]; Chris@49: case 22: Chris@49: dest[21] = src[21]; Chris@49: case 21: Chris@49: dest[20] = src[20]; Chris@49: case 20: Chris@49: dest[19] = src[19]; Chris@49: case 19: Chris@49: dest[18] = src[18]; Chris@49: case 18: Chris@49: dest[17] = src[17]; Chris@49: case 17: Chris@49: dest[16] = src[16]; Chris@49: case 16: Chris@49: dest[15] = src[15]; Chris@49: case 15: Chris@49: dest[14] = src[14]; Chris@49: case 14: Chris@49: dest[13] = src[13]; Chris@49: case 13: Chris@49: dest[12] = src[12]; Chris@49: case 12: Chris@49: dest[11] = src[11]; Chris@49: case 11: Chris@49: dest[10] = src[10]; Chris@49: case 10: Chris@49: dest[9] = src[9]; Chris@49: case 9: Chris@49: dest[8] = src[8]; Chris@49: case 8: Chris@49: dest[7] = src[7]; Chris@49: case 7: Chris@49: dest[6] = src[6]; Chris@49: case 6: Chris@49: dest[5] = src[5]; Chris@49: case 5: Chris@49: dest[4] = src[4]; Chris@49: case 4: Chris@49: dest[3] = src[3]; Chris@49: case 3: Chris@49: dest[2] = src[2]; Chris@49: case 2: Chris@49: dest[1] = src[1]; Chris@49: case 1: Chris@49: dest[0] = src[0]; Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::copy_forwards(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: // can't use std::memcpy(), as we don't know how it copies data Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j < n_elem; i+=2, j+=2) Chris@49: { Chris@49: dest[i] = src[i]; Chris@49: dest[j] = src[j]; Chris@49: } Chris@49: Chris@49: if(i < n_elem) Chris@49: { Chris@49: dest[i] = src[i]; Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: // template Chris@49: // arma_hot Chris@49: // inline Chris@49: // void Chris@49: // arrayops::copy_backwards(eT* dest, const eT* src, const uword n_elem) Chris@49: // { Chris@49: // // can't use std::memcpy(), as we don't know how it copies data Chris@49: // Chris@49: // switch(n_elem) Chris@49: // { Chris@49: // default: Chris@49: // for(uword i = (n_elem-1); i >= 1; --i) { dest[i] = src[i]; } Chris@49: // // NOTE: the 'break' statement has been deliberately omitted Chris@49: // case 1: Chris@49: // dest[0] = src[0]; Chris@49: // case 0: Chris@49: // ; Chris@49: // } Chris@49: // } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::copy_backwards(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: // can't use std::memcpy(), as we don't know how it copies data Chris@49: Chris@49: switch(n_elem) Chris@49: { Chris@49: default: Chris@49: { Chris@49: uword i, j; Chris@49: for(i = (n_elem-1), j = (n_elem-2); j >= 2; i-=2, j-=2) Chris@49: { Chris@49: const eT tmp_i = src[i]; Chris@49: const eT tmp_j = src[j]; Chris@49: Chris@49: dest[i] = tmp_i; Chris@49: dest[j] = tmp_j; Chris@49: } Chris@49: Chris@49: // j is less than 2: it can be 1 or 0 Chris@49: // i is j+1, ie. less than 3: it can be 2 or 1 Chris@49: Chris@49: if(i == 2) Chris@49: { Chris@49: dest[2] = src[2]; Chris@49: } Chris@49: } Chris@49: // NOTE: the 'break' statement has been deliberately omitted Chris@49: case 2: Chris@49: dest[1] = src[1]; Chris@49: case 1: Chris@49: dest[0] = src[0]; Chris@49: case 0: Chris@49: ; Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: arma_inline Chris@49: void Chris@49: arrayops::convert_cx_scalar Chris@49: ( Chris@49: out_eT& out, Chris@49: const in_eT& in, Chris@49: const typename arma_not_cx::result* junk1, Chris@49: const typename arma_not_cx< in_eT>::result* junk2 Chris@49: ) Chris@49: { Chris@49: arma_ignore(junk1); Chris@49: arma_ignore(junk2); Chris@49: Chris@49: out = out_eT(in); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: arma_inline Chris@49: void Chris@49: arrayops::convert_cx_scalar Chris@49: ( Chris@49: out_eT& out, Chris@49: const std::complex& in, Chris@49: const typename arma_not_cx::result* junk Chris@49: ) Chris@49: { Chris@49: arma_ignore(junk); Chris@49: Chris@49: out = out_eT( in.real() ); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: arma_inline Chris@49: void Chris@49: arrayops::convert_cx_scalar Chris@49: ( Chris@49: std::complex& out, Chris@49: const std::complex< in_T>& in Chris@49: ) Chris@49: { Chris@49: typedef std::complex out_eT; Chris@49: Chris@49: out = out_eT(in); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::convert(out_eT* dest, const in_eT* src, const uword n_elem) Chris@49: { Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j::value) Chris@49: ? out_eT( tmp_i ) Chris@49: : ( cond_rel< is_signed::value >::lt(tmp_i, in_eT(0)) ? out_eT(0) : out_eT(tmp_i) ); Chris@49: Chris@49: dest[j] = (is_signed::value) Chris@49: ? out_eT( tmp_j ) Chris@49: : ( cond_rel< is_signed::value >::lt(tmp_j, in_eT(0)) ? out_eT(0) : out_eT(tmp_j) ); Chris@49: } Chris@49: Chris@49: if(i < n_elem) Chris@49: { Chris@49: const in_eT tmp_i = src[i]; Chris@49: Chris@49: // dest[i] = out_eT( tmp_i ); Chris@49: Chris@49: dest[i] = (is_signed::value) Chris@49: ? out_eT( tmp_i ) Chris@49: : ( cond_rel< is_signed::value >::lt(tmp_i, in_eT(0)) ? out_eT(0) : out_eT(tmp_i) ); Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::convert_cx(out_eT* dest, const in_eT* src, const uword n_elem) Chris@49: { Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_plus(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: if(memory::is_aligned(src)) Chris@49: { Chris@49: memory::mark_as_aligned(src); Chris@49: Chris@49: arrayops::inplace_plus_base(dest, src, n_elem); Chris@49: } Chris@49: else Chris@49: { Chris@49: arrayops::inplace_plus_base(dest, src, n_elem); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: if(memory::is_aligned(src)) Chris@49: { Chris@49: memory::mark_as_aligned(src); Chris@49: Chris@49: arrayops::inplace_plus_base(dest, src, n_elem); Chris@49: } Chris@49: else Chris@49: { Chris@49: arrayops::inplace_plus_base(dest, src, n_elem); Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_minus(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: if(memory::is_aligned(src)) Chris@49: { Chris@49: memory::mark_as_aligned(src); Chris@49: Chris@49: arrayops::inplace_minus_base(dest, src, n_elem); Chris@49: } Chris@49: else Chris@49: { Chris@49: arrayops::inplace_minus_base(dest, src, n_elem); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: if(memory::is_aligned(src)) Chris@49: { Chris@49: memory::mark_as_aligned(src); Chris@49: Chris@49: arrayops::inplace_minus_base(dest, src, n_elem); Chris@49: } Chris@49: else Chris@49: { Chris@49: arrayops::inplace_minus_base(dest, src, n_elem); Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_mul(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: if(memory::is_aligned(src)) Chris@49: { Chris@49: memory::mark_as_aligned(src); Chris@49: Chris@49: arrayops::inplace_mul_base(dest, src, n_elem); Chris@49: } Chris@49: else Chris@49: { Chris@49: arrayops::inplace_mul_base(dest, src, n_elem); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: if(memory::is_aligned(src)) Chris@49: { Chris@49: memory::mark_as_aligned(src); Chris@49: Chris@49: arrayops::inplace_mul_base(dest, src, n_elem); Chris@49: } Chris@49: else Chris@49: { Chris@49: arrayops::inplace_mul_base(dest, src, n_elem); Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_div(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: if(memory::is_aligned(src)) Chris@49: { Chris@49: memory::mark_as_aligned(src); Chris@49: Chris@49: arrayops::inplace_div_base(dest, src, n_elem); Chris@49: } Chris@49: else Chris@49: { Chris@49: arrayops::inplace_div_base(dest, src, n_elem); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: if(memory::is_aligned(src)) Chris@49: { Chris@49: memory::mark_as_aligned(src); Chris@49: Chris@49: arrayops::inplace_div_base(dest, src, n_elem); Chris@49: } Chris@49: else Chris@49: { Chris@49: arrayops::inplace_div_base(dest, src, n_elem); Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_plus_base(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_minus_base(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_mul_base(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_div_base(eT* dest, const eT* src, const uword n_elem) Chris@49: { Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_set(eT* dest, const eT val, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_set_fixed(eT* dest, const eT val) Chris@49: { Chris@49: for(uword i=0; i Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_plus(eT* dest, const eT val, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_minus(eT* dest, const eT val, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_mul(eT* dest, const eT val, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: arrayops::inplace_div(eT* dest, const eT val, const uword n_elem) Chris@49: { Chris@49: if(memory::is_aligned(dest)) Chris@49: { Chris@49: memory::mark_as_aligned(dest); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: eT Chris@49: arrayops::accumulate(const eT* src, const uword n_elem) Chris@49: { Chris@49: uword i,j; Chris@49: Chris@49: eT acc1 = eT(0); Chris@49: eT acc2 = eT(0); Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: eT Chris@49: arrayops::product(const eT* src, const uword n_elem) Chris@49: { Chris@49: eT val1 = eT(1); Chris@49: eT val2 = eT(1); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: bool Chris@49: arrayops::is_finite(const eT* src, const uword n_elem) Chris@49: { Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: typename get_pod_type::result Chris@49: arrayops::norm_1(const eT* src, const uword n_elem) Chris@49: { Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: T acc = T(0); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: eT Chris@49: arrayops::norm_2(const eT* src, const uword n_elem, const typename arma_not_cx::result* junk) Chris@49: { Chris@49: arma_ignore(junk); Chris@49: Chris@49: eT acc = eT(0); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: T Chris@49: arrayops::norm_2(const std::complex* src, const uword n_elem) Chris@49: { Chris@49: T acc = T(0); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: typename get_pod_type::result Chris@49: arrayops::norm_k(const eT* src, const uword n_elem, const int k) Chris@49: { Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: T acc = T(0); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=0, j=1; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: typename get_pod_type::result Chris@49: arrayops::norm_max(const eT* src, const uword n_elem) Chris@49: { Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: T max_val = std::abs(src[0]); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=1, j=2; j Chris@49: arma_hot Chris@49: arma_pure Chris@49: inline Chris@49: typename get_pod_type::result Chris@49: arrayops::norm_min(const eT* src, const uword n_elem) Chris@49: { Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: T min_val = std::abs(src[0]); Chris@49: Chris@49: uword i,j; Chris@49: Chris@49: for(i=1, j=2; j tmp_i) { min_val = tmp_i; } Chris@49: if(min_val > tmp_j) { min_val = tmp_j; } Chris@49: } Chris@49: Chris@49: if(i < n_elem) Chris@49: { Chris@49: const T tmp_i = std::abs(src[i]); Chris@49: Chris@49: if(min_val > tmp_i) { min_val = tmp_i; } Chris@49: } Chris@49: Chris@49: return min_val; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: //! @}