arma_hot inline bool arrayops::is_finite(const eT* src, const uword n_elem) { uword j; for(j=1; j<n_elem; j+=2) { const eT val_i = (*src); src++; const eT val_j = (*src); src++; if( (arma_isfinite(val_i) == false) || (arma_isfinite(val_j) == false) ) { return false; } } if((j-1) < n_elem) { if(arma_isfinite(*src) == false) { return false; } } return true; }
arma_hot arma_pure inline bool arrayops::is_finite(const eT* src, const u32 n_elem) { u32 i,j; for(i=0, j=1; j<n_elem; i+=2, j+=2) { const eT val_i = src[i]; const eT val_j = src[j]; if( (arma_isfinite(val_i) == false) || (arma_isfinite(val_j) == false) ) { return false; } } if(i < n_elem) { if(arma_isfinite(src[i]) == false) { return false; } } return true; }
arma_inline bool arma_isfinite(const std::complex<T>& x) { if( (arma_isfinite(x.real()) == false) || (arma_isfinite(x.imag()) == false) ) { return false; } else { return true; } }
inline arma_warn_unused bool is_finite(const SpBase<typename T1::elem_type,T1>& X) { arma_extra_debug_sigprint(); const SpProxy<T1> P(X.get_ref()); if(is_SpMat<typename SpProxy<T1>::stored_type>::value) { const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q); return tmp.M.is_finite(); } else { typename SpProxy<T1>::const_iterator_type it = P.begin(); typename SpProxy<T1>::const_iterator_type it_end = P.end(); while(it != it_end) { if(arma_isfinite(*it) == false) { return false; } ++it; } } return true; }
inline eT spop_mean::iterator_mean(T1& it, const T1& end, const uword n_zero, const eT junk) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename get_pod_type<eT>::result T; eT acc = eT(0); T1 backup_it(it); // in case we have to use robust iterator_mean const uword it_begin_pos = it.pos(); while (it != end) { acc += (*it); ++it; } const uword count = n_zero + (it.pos() - it_begin_pos); const eT result = (count > 0) ? eT(acc / T(count)) : eT(0); return arma_isfinite(result) ? result : spop_mean::iterator_mean_robust(backup_it, end, n_zero, eT(0)); }
inline eT op_mean::mean_all(const diagview<eT>& X) { arma_extra_debug_sigprint(); typedef typename get_pod_type<eT>::result T; const uword X_n_elem = X.n_elem; if(X_n_elem == 0) { arma_debug_check(true, "mean(): object has no elements"); return Datum<eT>::nan; } eT val = eT(0); for(uword i=0; i<X_n_elem; ++i) { val += X[i]; } const eT result = val / T(X_n_elem); return arma_isfinite(result) ? result : op_mean::mean_all_robust(X); }
inline eT op_mean::direct_mean(const Mat<eT>& X, const uword row) { arma_extra_debug_sigprint(); typedef typename get_pod_type<eT>::result T; const uword X_n_cols = X.n_cols; eT val = eT(0); uword i,j; for(i=0, j=1; j < X_n_cols; i+=2, j+=2) { val += X.at(row,i); val += X.at(row,j); } if(i < X_n_cols) { val += X.at(row,i); } const eT result = val / T(X_n_cols); return arma_isfinite(result) ? result : op_mean::direct_mean_robust(X, row); }
inline void arma_ostream::print_elem(std::ostream& o, const std::complex<T>& x, const bool modify) { if( (x.real() != T(0)) || (x.imag() != T(0)) || (modify == false) ) { std::ostringstream ss; ss.flags(o.flags()); //ss.imbue(o.getloc()); ss.precision(o.precision()); ss << '('; const T a = x.real(); if(arma_isfinite(a)) { ss << a; } else { ss << ( arma_isinf(a) ? ((a <= T(0)) ? "-inf" : "+inf") : "nan" ); } ss << ','; const T b = x.imag(); if(arma_isfinite(b)) { ss << b; } else { ss << ( arma_isinf(b) ? ((b <= T(0)) ? "-inf" : "+inf") : "nan" ); } ss << ')'; o << ss.str(); } else { o << "(0,0)"; } }
arma_inline arma_warn_unused bool is_finite(const eT x, const typename arma_scalar_only<eT>::result* junk = 0) { arma_ignore(junk); return arma_isfinite(x); }
inline eT op_mean::mean_all(const subview<eT>& X) { arma_extra_debug_sigprint(); typedef typename get_pod_type<eT>::result T; const uword X_n_rows = X.n_rows; const uword X_n_cols = X.n_cols; const uword X_n_elem = X.n_elem; if(X_n_elem == 0) { arma_debug_check(true, "mean(): object has no elements"); return Datum<eT>::nan; } eT val = eT(0); if(X_n_rows == 1) { const Mat<eT>& A = X.m; const uword start_row = X.aux_row1; const uword start_col = X.aux_col1; const uword end_col_p1 = start_col + X_n_cols; uword i,j; for(i=start_col, j=start_col+1; j < end_col_p1; i+=2, j+=2) { val += A.at(start_row, i); val += A.at(start_row, j); } if(i < end_col_p1) { val += A.at(start_row, i); } } else { for(uword col=0; col < X_n_cols; ++col) { val += arrayops::accumulate(X.colptr(col), X_n_rows); } } const eT result = val / T(X_n_elem); return arma_isfinite(result) ? result : op_mean::mean_all_robust(X); }
inline eT op_mean::direct_mean(const eT* const X, const uword n_elem) { arma_extra_debug_sigprint(); typedef typename get_pod_type<eT>::result T; const eT result = arrayops::accumulate(X, n_elem) / T(n_elem); return arma_isfinite(result) ? result : op_mean::direct_mean_robust(X, n_elem); }
inline void running_stat<eT>::operator() (const std::complex< typename running_stat<eT>::T >& sample) { arma_extra_debug_sigprint(); if( arma_isfinite(sample) == false ) { arma_debug_warn("running_stat: sample ignored as it is non-finite" ); return; } running_stat_aux::update_stats(*this, sample); }
inline eT spop_mean::direct_mean ( const eT* const X, const uword length, const uword N ) { arma_extra_debug_sigprint(); typedef typename get_pod_type<eT>::result T; const eT result = ((length > 0) && (N > 0)) ? eT(arrayops::accumulate(X, length) / T(N)) : eT(0); return arma_isfinite(result) ? result : spop_mean::direct_mean_robust(X, length, N); }
arma_hot inline eT op_norm::vec_norm_2_direct_std(const Mat<eT>& X) { arma_extra_debug_sigprint(); const uword N = X.n_elem; const eT* A = X.memptr(); eT result; if(N < uword(32)) { result = op_norm::vec_norm_2_direct_mem(N,A); } else { #if defined(ARMA_USE_ATLAS) { result = atlas::cblas_nrm2(N,A); } #elif defined(ARMA_USE_BLAS) { result = blas::nrm2(N,A); } #else { result = op_norm::vec_norm_2_direct_mem(N,A); } #endif } if( (result != eT(0)) && arma_isfinite(result) ) { return result; } else { arma_extra_debug_print("op_norm::vec_norm_2_direct_std(): detected possible underflow or overflow"); return op_norm::vec_norm_2_direct_robust(X); } }
inline typename arma_real_only<eT>::result log_add_exp(eT log_a, eT log_b) { if(log_a < log_b) { std::swap(log_a, log_b); } const eT negdelta = log_b - log_a; if( (negdelta < Datum<eT>::log_min) || (arma_isfinite(negdelta) == false) ) { return log_a; } else { return (log_a + arma_log1p(std::exp(negdelta))); } }
arma_warn_unused inline Col<uword> find_nonfinite(const SpBase<typename T1::elem_type,T1>& X) { arma_extra_debug_sigprint(); const SpProxy<T1> P(X.get_ref()); const uword n_rows = P.get_n_rows(); const uword n_nz = P.get_n_nonzero(); Mat<uword> tmp(n_nz,1); uword* tmp_mem = tmp.memptr(); typename SpProxy<T1>::const_iterator_type it = P.begin(); uword count = 0; for(uword i=0; i<n_nz; ++i) { if(arma_isfinite(*it) == false) { const uword index = it.row() + it.col()*n_rows; tmp_mem[count] = index; ++count; } ++it; } Col<uword> out; if(count > 0) { out.steal_mem_col(tmp, count); } return out; }
arma_inline void arma_ostream::print_elem(std::ostream& o, const eT& x, const bool modify) { if(is_signed<eT>::value) { typedef typename promote_type<eT, s16>::result promoted_eT; if(x != eT(0)) { if(arma_isfinite(x)) { o << promoted_eT(x); } else { o << ( arma_isinf(x) ? ((x <= eT(0)) ? "-inf" : "inf") : "nan" ); } } else { arma_ostream::print_elem_zero<promoted_eT>(o, modify); } } else { typedef typename promote_type<eT, u16>::result promoted_eT; if(x != eT(0)) { o << promoted_eT(x); } else { arma_ostream::print_elem_zero<promoted_eT>(o, modify); } } }
inline typename arma_float_only<eT>::result log_add(eT log_a, eT log_b) { if(log_a < log_b) { std::swap(log_a, log_b); } const eT negdelta = log_b - log_a; if( (negdelta < Math<eT>::log_min()) || (arma_isfinite(negdelta) == false) ) { return log_a; } else { #if defined(ARMA_HAVE_LOG1P) return (log_a + log1p(std::exp(negdelta))); #else return (log_a + std::log(1.0 + std::exp(negdelta))); #endif } }
inline void op_mean::apply_noalias_unwrap(Cube<typename T1::elem_type>& out, const ProxyCube<T1>& P, const uword dim) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; typedef typename get_pod_type<eT>::result T; typedef typename ProxyCube<T1>::stored_type P_stored_type; const unwrap_cube<P_stored_type> U(P.Q); const Cube<eT>& X = U.M; const uword X_n_rows = X.n_rows; const uword X_n_cols = X.n_cols; const uword X_n_slices = X.n_slices; if(dim == 0) { out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols, X_n_slices); if(X_n_rows == 0) { return; } for(uword slice=0; slice < X_n_slices; ++slice) { eT* out_mem = out.slice_memptr(slice); for(uword col=0; col < X_n_cols; ++col) { out_mem[col] = op_mean::direct_mean( X.slice_colptr(slice,col), X_n_rows ); } } } else if(dim == 1) { out.zeros(X_n_rows, (X_n_cols > 0) ? 1 : 0, X_n_slices); if(X_n_cols == 0) { return; } for(uword slice=0; slice < X_n_slices; ++slice) { eT* out_mem = out.slice_memptr(slice); for(uword col=0; col < X_n_cols; ++col) { const eT* col_mem = X.slice_colptr(slice,col); for(uword row=0; row < X_n_rows; ++row) { out_mem[row] += col_mem[row]; } } const Mat<eT> tmp('j', X.slice_memptr(slice), X_n_rows, X_n_cols); for(uword row=0; row < X_n_rows; ++row) { out_mem[row] /= T(X_n_cols); if(arma_isfinite(out_mem[row]) == false) { out_mem[row] = op_mean::direct_mean_robust( tmp, row ); } } } } else if(dim == 2) { out.zeros(X_n_rows, X_n_cols, (X_n_slices > 0) ? 1 : 0); if(X_n_slices == 0) { return; } eT* out_mem = out.memptr(); for(uword slice=0; slice < X_n_slices; ++slice) { arrayops::inplace_plus(out_mem, X.slice_memptr(slice), X.n_elem_slice ); } out /= T(X_n_slices); podarray<eT> tmp(X_n_slices); for(uword col=0; col < X_n_cols; ++col) for(uword row=0; row < X_n_rows; ++row) { if(arma_isfinite(out.at(row,col,0)) == false) { for(uword slice=0; slice < X_n_slices; ++slice) { tmp[slice] = X.at(row,col,slice); } out.at(row,col,0) = op_mean::direct_mean_robust(tmp.memptr(), X_n_slices); } } } }
inline void glue_hist::apply(Mat<uword>& out, const mtGlue<uword,T1,T2,glue_hist>& in) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const uword dim = in.aux_uword; const unwrap_check_mixed<T1> tmp1(in.A, out); const unwrap_check_mixed<T2> tmp2(in.B, out); const Mat<eT>& X = tmp1.M; const Mat<eT>& C = tmp2.M; arma_debug_check ( (C.is_vec() == false), "hist(): parameter 'centers' must be a vector" ); arma_debug_check ( (dim > 1), "hist(): parameter 'dim' must be 0 or 1" ); 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 C_n_elem = C.n_elem; if( C_n_elem == 0 ) { out.reset(); return; } // for vectors we are currently ignoring the "dim" parameter uword out_n_rows = 0; uword out_n_cols = 0; if(X.is_vec()) { if(X.is_rowvec()) { out_n_rows = 1; out_n_cols = C_n_elem; } else if(X.is_colvec()) { out_n_rows = C_n_elem; out_n_cols = 1; } } else { if(dim == 0) { out_n_rows = C_n_elem; out_n_cols = X_n_cols; } else if(dim == 1) { out_n_rows = X_n_rows; out_n_cols = C_n_elem; } } out.zeros(out_n_rows, out_n_cols); const eT* C_mem = C.memptr(); const eT center_0 = C_mem[0]; if(X.is_vec()) { const eT* X_mem = X.memptr(); uword* out_mem = out.memptr(); for(uword i=0; i < X_n_elem; ++i) { const eT val = X_mem[i]; if(is_finite(val)) { eT opt_dist = (val >= center_0) ? (val - center_0) : (center_0 - val); uword opt_index = 0; for(uword j=1; j < C_n_elem; ++j) { const eT center = C_mem[j]; const eT dist = (val >= center) ? (val - center) : (center - val); if(dist < opt_dist) { opt_dist = dist; opt_index = j; } else { break; } } out_mem[opt_index]++; } else { // -inf if(val < eT(0)) { out_mem[0]++; } // +inf if(val > eT(0)) { out_mem[C_n_elem-1]++; } // ignore NaN } } } else { if(dim == 0) { for(uword col=0; col < X_n_cols; ++col) { const eT* X_coldata = X.colptr(col); uword* out_coldata = out.colptr(col); for(uword row=0; row < X_n_rows; ++row) { const eT val = X_coldata[row]; if(arma_isfinite(val)) { eT opt_dist = (center_0 >= val) ? (center_0 - val) : (val - center_0); uword opt_index = 0; for(uword j=1; j < C_n_elem; ++j) { const eT center = C_mem[j]; const eT dist = (center >= val) ? (center - val) : (val - center); if(dist < opt_dist) { opt_dist = dist; opt_index = j; } else { break; } } out_coldata[opt_index]++; } else { // -inf if(val < eT(0)) { out_coldata[0]++; } // +inf if(val > eT(0)) { out_coldata[C_n_elem-1]++; } // ignore NaN } } } } else if(dim == 1) { for(uword row=0; row < X_n_rows; ++row) { for(uword col=0; col < X_n_cols; ++col) { const eT val = X.at(row,col); if(arma_isfinite(val)) { eT opt_dist = (center_0 >= val) ? (center_0 - val) : (val - center_0); uword opt_index = 0; for(uword j=1; j < C_n_elem; ++j) { const eT center = C_mem[j]; const eT dist = (center >= val) ? (center - val) : (val - center); if(dist < opt_dist) { opt_dist = dist; opt_index = j; } else { break; } } out.at(row,opt_index)++; } else { // -inf if(val < eT(0)) { out.at(row,0)++; } // +inf if(val > eT(0)) { out.at(row,C_n_elem-1)++; } // ignore NaN } } } } } }
inline void op_mean::apply_noalias_unwrap(Mat<typename T1::elem_type>& out, const Proxy<T1>& P, const uword dim) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; typedef typename get_pod_type<eT>::result T; typedef typename Proxy<T1>::stored_type P_stored_type; const unwrap<P_stored_type> tmp(P.Q); const typename unwrap<P_stored_type>::stored_type& X = tmp.M; const uword X_n_rows = X.n_rows; const uword X_n_cols = X.n_cols; if(dim == 0) { out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols); if(X_n_rows == 0) { return; } eT* out_mem = out.memptr(); for(uword col=0; col < X_n_cols; ++col) { out_mem[col] = op_mean::direct_mean( X.colptr(col), X_n_rows ); } } else if(dim == 1) { out.zeros(X_n_rows, (X_n_cols > 0) ? 1 : 0); if(X_n_cols == 0) { return; } eT* out_mem = out.memptr(); for(uword col=0; col < X_n_cols; ++col) { const eT* col_mem = X.colptr(col); for(uword row=0; row < X_n_rows; ++row) { out_mem[row] += col_mem[row]; } } out /= T(X_n_cols); for(uword row=0; row < X_n_rows; ++row) { if(arma_isfinite(out_mem[row]) == false) { out_mem[row] = op_mean::direct_mean_robust( X, row ); } } } }
arma_hot inline typename T1::pod_type op_norm::vec_norm_2(const Proxy<T1>& P, const typename arma_cx_only<typename T1::elem_type>::result* junk) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename T1::pod_type T; T acc = T(0); if(Proxy<T1>::use_at == false) { typename Proxy<T1>::ea_type A = P.get_ea(); const uword N = P.get_n_elem(); for(uword i=0; i<N; ++i) { const std::complex<T>& X = A[i]; const T a = X.real(); const T b = X.imag(); acc += (a*a) + (b*b); } } else { const uword n_rows = P.get_n_rows(); const uword n_cols = P.get_n_cols(); if(n_rows == 1) { for(uword col=0; col<n_cols; ++col) { const std::complex<T>& X = P.at(0,col); const T a = X.real(); const T b = X.imag(); acc += (a*a) + (b*b); } } else { for(uword col=0; col<n_cols; ++col) for(uword row=0; row<n_rows; ++row) { const std::complex<T>& X = P.at(row,col); const T a = X.real(); const T b = X.imag(); acc += (a*a) + (b*b); } } } const T sqrt_acc = std::sqrt(acc); if( (sqrt_acc != T(0)) && arma_isfinite(sqrt_acc) ) { return sqrt_acc; } else { arma_extra_debug_print("op_norm::vec_norm_2(): detected possible underflow or overflow"); const quasi_unwrap<typename Proxy<T1>::stored_type> R(P.Q); const uword N = R.M.n_elem; const eT* R_mem = R.M.memptr(); T max_val = priv::most_neg<T>(); for(uword i=0; i<N; ++i) { const T val_i = std::abs(R_mem[i]); if(val_i > max_val) { max_val = val_i; } } if(max_val == T(0)) { return T(0); } T alt_acc = T(0); for(uword i=0; i<N; ++i) { const T val_i = std::abs(R_mem[i]) / max_val; alt_acc += val_i * val_i; } return ( std::sqrt(alt_acc) * max_val ); } }
arma_hot inline typename T1::pod_type op_norm::vec_norm_2(const Proxy<T1>& P, const typename arma_not_cx<typename T1::elem_type>::result* junk) { arma_extra_debug_sigprint(); arma_ignore(junk); const bool have_direct_mem = (is_Mat<typename Proxy<T1>::stored_type>::value) || (is_subview_col<typename Proxy<T1>::stored_type>::value); if(have_direct_mem) { const quasi_unwrap<typename Proxy<T1>::stored_type> tmp(P.Q); return op_norm::vec_norm_2_direct_std(tmp.M); } typedef typename T1::pod_type T; T acc = T(0); if(Proxy<T1>::use_at == false) { typename Proxy<T1>::ea_type A = P.get_ea(); const uword N = P.get_n_elem(); T acc1 = T(0); T acc2 = T(0); uword i,j; for(i=0, j=1; j<N; i+=2, j+=2) { const T tmp_i = A[i]; const T tmp_j = A[j]; acc1 += tmp_i * tmp_i; acc2 += tmp_j * tmp_j; } if(i < N) { const T tmp_i = A[i]; acc1 += tmp_i * tmp_i; } acc = acc1 + acc2; } else { const uword n_rows = P.get_n_rows(); const uword n_cols = P.get_n_cols(); if(n_rows == 1) { for(uword col=0; col<n_cols; ++col) { const T tmp = P.at(0,col); acc += tmp * tmp; } } else { for(uword col=0; col<n_cols; ++col) { uword i,j; for(i=0, j=1; j<n_rows; i+=2, j+=2) { const T tmp_i = P.at(i,col); const T tmp_j = P.at(j,col); acc += tmp_i * tmp_i; acc += tmp_j * tmp_j; } if(i < n_rows) { const T tmp_i = P.at(i,col); acc += tmp_i * tmp_i; } } } } const T sqrt_acc = std::sqrt(acc); if( (sqrt_acc != T(0)) && arma_isfinite(sqrt_acc) ) { return sqrt_acc; } else { arma_extra_debug_print("op_norm::vec_norm_2(): detected possible underflow or overflow"); const quasi_unwrap<typename Proxy<T1>::stored_type> tmp(P.Q); return op_norm::vec_norm_2_direct_robust(tmp.M); } }
inline arma_warn_unused typename enable_if2 < is_arma_type<T1>::value, bool >::result is_finite(const T1& X) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const Proxy<T1> P(X); const bool have_direct_mem = (is_Mat<typename Proxy<T1>::stored_type>::value) || (is_subview_col<typename Proxy<T1>::stored_type>::value); if(have_direct_mem) { const quasi_unwrap<typename Proxy<T1>::stored_type> tmp(P.Q); return tmp.M.is_finite(); } if(Proxy<T1>::prefer_at_accessor == false) { const typename Proxy<T1>::ea_type Pea = P.get_ea(); const uword n_elem = P.get_n_elem(); uword i,j; for(i=0, j=1; j<n_elem; i+=2, j+=2) { const eT val_i = Pea[i]; const eT val_j = Pea[j]; if( (arma_isfinite(val_i) == false) || (arma_isfinite(val_j) == false) ) { return false; } } if(i < n_elem) { if(arma_isfinite(Pea[i]) == false) { return false; } } } else { const uword n_rows = P.get_n_rows(); const uword n_cols = P.get_n_cols(); for(uword col=0; col<n_cols; ++col) for(uword row=0; row<n_rows; ++row) { if(arma_isfinite(P.at(row,col)) == false) { return false; } } } return true; }
inline void op_hist::apply(Mat<uword>& out, const mtOp<uword, T1, op_hist>& X) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const uword n_bins = X.aux_uword_a; const unwrap_check_mixed<T1> tmp(X.m, out); const Mat<eT>& A = tmp.M; arma_debug_check( ((A.is_vec() == false) && (A.is_empty() == false)), "hist(): only vectors are supported when automatically determining bin centers" ); uword A_n_elem = A.n_elem; const eT* A_mem = A.memptr(); eT min_val = priv::most_pos<eT>(); eT max_val = priv::most_neg<eT>(); uword i,j; for(i=0, j=1; j < A_n_elem; i+=2, j+=2) { const eT val_i = A_mem[i]; const eT val_j = A_mem[j]; if(min_val > val_i) { min_val = val_i; } if(min_val > val_j) { min_val = val_j; } if(max_val < val_i) { max_val = val_i; } if(max_val < val_j) { max_val = val_j; } } if(i < A_n_elem) { const eT val_i = A_mem[i]; if(min_val > val_i) { min_val = val_i; } if(max_val < val_i) { max_val = val_i; } } if(arma_isfinite(min_val) == false) { min_val = priv::most_neg<eT>(); } if(arma_isfinite(max_val) == false) { max_val = priv::most_pos<eT>(); } if(n_bins >= 1) { Col<eT> c(n_bins); eT* c_mem = c.memptr(); for(uword ii=0; ii < n_bins; ++ii) { c_mem[ii] = (0.5 + ii) / double(n_bins); // TODO: may need to be modified for integer matrices } c = ((max_val - min_val) * c) + min_val; out = hist(A, c); } else { out.reset(); } }
inline void glue_hist::apply_noalias(Mat<uword>& out, const Mat<eT>& X, const Mat<eT>& C, const uword dim) { arma_extra_debug_sigprint(); arma_debug_check( ((C.is_vec() == false) && (C.is_empty() == false)), "hist(): parameter 'centers' must be a vector" ); const uword X_n_rows = X.n_rows; const uword X_n_cols = X.n_cols; const uword C_n_elem = C.n_elem; if( C_n_elem == 0 ) { out.reset(); return; } arma_debug_check ( ((Col<eT>(const_cast<eT*>(C.memptr()), C_n_elem, false, false)).is_sorted("strictascend") == false), "hist(): given 'centers' vector does not contain monotonically increasing values" ); const eT* C_mem = C.memptr(); const eT center_0 = C_mem[0]; if(dim == 0) { out.zeros(C_n_elem, X_n_cols); for(uword col=0; col < X_n_cols; ++col) { const eT* X_coldata = X.colptr(col); uword* out_coldata = out.colptr(col); for(uword row=0; row < X_n_rows; ++row) { const eT val = X_coldata[row]; if(arma_isfinite(val)) { eT opt_dist = (center_0 >= val) ? (center_0 - val) : (val - center_0); uword opt_index = 0; for(uword j=1; j < C_n_elem; ++j) { const eT center = C_mem[j]; const eT dist = (center >= val) ? (center - val) : (val - center); if(dist < opt_dist) { opt_dist = dist; opt_index = j; } else { break; } } out_coldata[opt_index]++; } else { // -inf if(val < eT(0)) { out_coldata[0]++; } // +inf if(val > eT(0)) { out_coldata[C_n_elem-1]++; } // ignore NaN } } } } else if(dim == 1) { out.zeros(X_n_rows, C_n_elem); if(X_n_rows == 1) { const uword X_n_elem = X.n_elem; const eT* X_mem = X.memptr(); uword* out_mem = out.memptr(); for(uword i=0; i < X_n_elem; ++i) { const eT val = X_mem[i]; if(is_finite(val)) { eT opt_dist = (val >= center_0) ? (val - center_0) : (center_0 - val); uword opt_index = 0; for(uword j=1; j < C_n_elem; ++j) { const eT center = C_mem[j]; const eT dist = (val >= center) ? (val - center) : (center - val); if(dist < opt_dist) { opt_dist = dist; opt_index = j; } else { break; } } out_mem[opt_index]++; } else { // -inf if(val < eT(0)) { out_mem[0]++; } // +inf if(val > eT(0)) { out_mem[C_n_elem-1]++; } // ignore NaN } } } else { for(uword row=0; row < X_n_rows; ++row) { for(uword col=0; col < X_n_cols; ++col) { const eT val = X.at(row,col); if(arma_isfinite(val)) { eT opt_dist = (center_0 >= val) ? (center_0 - val) : (val - center_0); uword opt_index = 0; for(uword j=1; j < C_n_elem; ++j) { const eT center = C_mem[j]; const eT dist = (center >= val) ? (center - val) : (val - center); if(dist < opt_dist) { opt_dist = dist; opt_index = j; } else { break; } } out.at(row,opt_index)++; } else { // -inf if(val < eT(0)) { out.at(row,0)++; } // +inf if(val > eT(0)) { out.at(row,C_n_elem-1)++; } // ignore NaN } } } } } }