inline typename T1::elem_type op_median::median_vec ( const T1& X, 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; const Proxy<T1> P(X); const uword n_elem = P.get_n_elem(); if(n_elem == 0) { arma_debug_check(true, "median(): object has no elements"); return Datum<eT>::nan; } std::vector< arma_cx_median_packet<T> > tmp_vec(n_elem); if(Proxy<T1>::prefer_at_accessor == false) { typedef typename Proxy<T1>::ea_type ea_type; ea_type A = P.get_ea(); for(uword i=0; i<n_elem; ++i) { tmp_vec[i].val = std::abs( A[i] ); tmp_vec[i].index = i; } uword index1; uword index2; op_median::direct_cx_median_index(index1, index2, tmp_vec); return op_mean::robust_mean( A[index1], A[index2] ); } else { const uword n_rows = P.get_n_rows(); const uword n_cols = P.get_n_cols(); if(n_cols == 1) { for(uword row=0; row < n_rows; ++row) { tmp_vec[row].val = std::abs( P.at(row,0) ); tmp_vec[row].index = row; } uword index1; uword index2; op_median::direct_cx_median_index(index1, index2, tmp_vec); return op_mean::robust_mean( P.at(index1,0), P.at(index2,0) ); } else if(n_rows == 1) { for(uword col=0; col < n_cols; ++col) { tmp_vec[col].val = std::abs( P.at(0,col) ); tmp_vec[col].index = col; } uword index1; uword index2; op_median::direct_cx_median_index(index1, index2, tmp_vec); return op_mean::robust_mean( P.at(0,index1), P.at(0,index2) ); } else { arma_stop("op_median::median_vec(): expected a vector" ); return eT(0); } } }
inline bool op_princomp::direct_princomp ( Mat< std::complex<typename T1::pod_type> >& coeff_out, Mat< std::complex<typename T1::pod_type> >& score_out, Col< typename T1::pod_type >& latent_out, const Base< std::complex<typename T1::pod_type>, T1 >& X, const typename arma_cx_only<typename T1::elem_type>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::pod_type T; typedef std::complex<T> eT; const unwrap_check<T1> Y( X.get_ref(), score_out ); const Mat<eT>& in = Y.M; const uword n_rows = in.n_rows; const uword n_cols = in.n_cols; if(n_rows > 1) // more than one sample { // subtract the mean - use score_out as temporary matrix score_out = in; score_out.each_row() -= mean(in); // singular value decomposition Mat<eT> U; Col< T> s; const bool svd_ok = svd(U, s, coeff_out, score_out); if(svd_ok == false) { return false; } // normalize the eigenvalues s /= std::sqrt( double(n_rows - 1) ); // project the samples to the principals score_out *= coeff_out; if(n_rows <= n_cols) // number of samples is less than their dimensionality { score_out.cols(n_rows-1,n_cols-1).zeros(); Col<T> s_tmp = zeros< Col<T> >(n_cols); s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); s = s_tmp; } // compute the eigenvalues of the principal vectors latent_out = s%s; } else // 0 or 1 samples { coeff_out.eye(n_cols, n_cols); score_out.copy_size(in); score_out.zeros(); latent_out.set_size(n_cols); latent_out.zeros(); } return true; }
inline bool op_princomp::direct_princomp ( Mat<typename T1::elem_type>& coeff_out, Mat<typename T1::elem_type>& score_out, Col<typename T1::elem_type>& latent_out, Col<typename T1::elem_type>& tsquared_out, const Base<typename T1::elem_type, T1>& X, const typename arma_not_cx<typename T1::elem_type>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; const unwrap_check<T1> Y( X.get_ref(), score_out ); const Mat<eT>& in = Y.M; const uword n_rows = in.n_rows; const uword n_cols = in.n_cols; if(n_rows > 1) // more than one sample { // subtract the mean - use score_out as temporary matrix score_out = in - repmat(mean(in), n_rows, 1); // singular value decomposition Mat<eT> U; Col<eT> s; const bool svd_ok = svd(U,s,coeff_out,score_out); if(svd_ok == false) { return false; } //U.reset(); // TODO: do we need this ? U will get automatically deleted anyway // normalize the eigenvalues s /= std::sqrt( double(n_rows - 1) ); // project the samples to the principals score_out *= coeff_out; if(n_rows <= n_cols) // number of samples is less than their dimensionality { score_out.cols(n_rows-1,n_cols-1).zeros(); //Col<eT> s_tmp = zeros< Col<eT> >(n_cols); Col<eT> s_tmp(n_cols); s_tmp.zeros(); s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); s = s_tmp; // compute the Hotelling's T-squared s_tmp.rows(0,n_rows-2) = eT(1) / s_tmp.rows(0,n_rows-2); const Mat<eT> S = score_out * diagmat(Col<eT>(s_tmp)); tsquared_out = sum(S%S,1); } else { // compute the Hotelling's T-squared const Mat<eT> S = score_out * diagmat(Col<eT>( eT(1) / s)); tsquared_out = sum(S%S,1); } // compute the eigenvalues of the principal vectors latent_out = s%s; } else // 0 or 1 samples { coeff_out.eye(n_cols, n_cols); score_out.copy_size(in); score_out.zeros(); latent_out.set_size(n_cols); latent_out.zeros(); tsquared_out.set_size(n_rows); tsquared_out.zeros(); } return true; }
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 bool eig_pair ( Col< std::complex<eT> >& eigval, Mat< std::complex<eT> >& eigvec, const Base< eT, T1 >& A, const Base< eT, T2 >& B, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_pair(): eigval is an alias of eigvec" ); Mat<eT> dummy_eigvec; Mat<eT> tmp_eigvec; const bool status = auxlib::eig_pair(eigval, dummy_eigvec, tmp_eigvec, A, B, 'r'); if(status == false) { eigval.reset(); eigvec.reset(); arma_bad("eig_pair(): failed to converge", false); } else { const uword n = eigval.n_elem; eigvec.set_size(n,n); if(n > 0) { // from LAPACK docs: // If the j-th and (j+1)-th eigenvalues form a complex conjugate pair, then // v(j) = VR(:,j)+i*VR(:,j+1) and v(j+1) = VR(:,j)-i*VR(:,j+1). for(uword j=0; j<n; ++j) { if( (j < n-1) && (eigval[j] == std::conj(eigval[j+1])) ) { // eigvec.col(j) = Mat< std::complex<eT> >( tmp_eigvec.col(j), tmp_eigvec.col(j+1) ); // eigvec.col(j+1) = Mat< std::complex<eT> >( tmp_eigvec.col(j), -tmp_eigvec.col(j+1) ); for(uword i=0; i<n; ++i) { eigvec.at(i,j) = std::complex<eT>( tmp_eigvec.at(i,j), tmp_eigvec.at(i,j+1) ); eigvec.at(i,j+1) = std::complex<eT>( tmp_eigvec.at(i,j), -tmp_eigvec.at(i,j+1) ); } ++j; } else { // eigvec.col(i) = tmp_eigvec.col(i); for(uword i=0; i<n; ++i) { eigvec.at(i,j) = std::complex<eT>(tmp_eigvec.at(i,j), eT(0)); } } } } } return status; }
inline arma_warn_unused typename enable_if2< is_arma_sparse_type<T1>::value, typename T1::pod_type >::result norm ( const T1& X, const char* method, const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename T1::pod_type T; const SpProxy<T1> P(X); if(P.get_n_nonzero() == 0) { return T(0); } const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q); const SpMat<eT>& A = tmp.M; // create a fake dense vector to allow reuse of code for dense vectors Col<eT> fake_vector( access::rwp(A.values), A.n_nonzero, false ); const Proxy< Col<eT> > P_fake_vector(fake_vector); const char sig = (method != NULL) ? method[0] : char(0); const bool is_vec = (P.get_n_rows() == 1) || (P.get_n_cols() == 1); // TODO: (T1::is_row) || (T1::is_col) || ... if(is_vec == true) { if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // max norm { return op_norm::vec_norm_max(P_fake_vector); } else if(sig == '-') // min norm { const T val = op_norm::vec_norm_min(P_fake_vector); if( P.get_n_nonzero() < P.get_n_elem() ) { return (std::min)(T(0), val); } else { return val; } } else if( (sig == 'f') || (sig == 'F') ) { return op_norm::vec_norm_2(P_fake_vector); } else { arma_stop_logic_error("norm(): unsupported vector norm type"); return T(0); } } else { if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm { return op_norm::mat_norm_inf(P); } else if( (sig == 'f') || (sig == 'F') ) { return op_norm::vec_norm_2(P_fake_vector); } else { arma_stop_logic_error("norm(): unsupported matrix norm type"); return T(0); } } }
inline void op_symmat::apply ( Mat<typename T1::elem_type>& out, const Op<T1,op_symmat>& in, const typename arma_not_cx<typename T1::elem_type>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; const unwrap<T1> tmp(in.m); const Mat<eT>& A = tmp.M; arma_debug_check( (A.is_square() == false), "symmatu()/symmatl(): given matrix must be square" ); const u32 N = A.n_rows; const bool upper = (in.aux_u32_a == 0); if(&out != &A) { out.copy_size(A); if(upper) { // upper triangular: copy the diagonal and the elements above the diagonal for(u32 i=0; i<N; ++i) { const eT* A_data = A.colptr(i); eT* out_data = out.colptr(i); arrayops::copy( out_data, A_data, i+1 ); } } else { // lower triangular: copy the diagonal and the elements below the diagonal for(u32 i=0; i<N; ++i) { const eT* A_data = A.colptr(i); eT* out_data = out.colptr(i); arrayops::copy( &out_data[i], &A_data[i], N-i ); } } } if(upper) { // reflect elements across the diagonal from upper triangle to lower triangle for(u32 col=1; col < N; ++col) { const eT* coldata = out.colptr(col); for(u32 row=0; row < col; ++row) { out.at(col,row) = coldata[row]; } } } else { // reflect elements across the diagonal from lower triangle to upper triangle for(u32 col=0; col < N; ++col) { const eT* coldata = out.colptr(col); for(u32 row=(col+1); row < N; ++row) { out.at(col,row) = coldata[row]; } } } }
inline arma_warn_unused typename T1::pod_type norm ( const Base<typename T1::elem_type,T1>& X, const char* method, const typename arma_float_or_cx_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename T1::pod_type T; const Proxy<T1> A(X.get_ref()); if(A.get_n_elem() == 0) { return T(0); } const char sig = method[0]; const bool is_vec = (A.get_n_rows() == 1) || (A.get_n_cols() == 1); if(is_vec == true) { if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // max norm { return arma_vec_norm_max(A); } else if(sig == '-') // min norm { return arma_vec_norm_min(A); } else if( (sig == 'f') || (sig == 'F') ) { return arma_vec_norm_2(A); } else { arma_stop("norm(): unsupported vector norm type"); return T(0); } } else { if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm { return arma_mat_norm_inf(A); } else if( (sig == 'f') || (sig == 'F') ) { return arma_vec_norm_2(A); } else { arma_stop("norm(): unsupported matrix norm type"); return T(0); } } }
arma_hot inline typename T1::pod_type arma_vec_norm_2(const Proxy<T1>& A, const typename arma_not_cx<typename T1::elem_type>::result* junk = 0) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::pod_type T; T acc = T(0); if(Proxy<T1>::prefer_at_accessor == false) { typename Proxy<T1>::ea_type P = A.get_ea(); const uword N = A.get_n_elem(); uword i,j; for(i=0, j=1; j<N; i+=2, j+=2) { const T tmp_i = P[i]; const T tmp_j = P[j]; acc += tmp_i * tmp_i; acc += tmp_j * tmp_j; } if(i < N) { const T tmp_i = P[i]; acc += tmp_i * tmp_i; } } else { const uword n_rows = A.get_n_rows(); const uword n_cols = A.get_n_cols(); 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 = A.at(i,col); const T tmp_j = A.at(j,col); acc += tmp_i * tmp_i; acc += tmp_j * tmp_j; } if(i < n_rows) { const T tmp_i = A.at(i,col); acc += tmp_i * tmp_i; } } } return std::sqrt(acc); }
inline void running_stat_vec_aux::update_stats ( running_stat_vec<obj_type>& x, const Mat<typename running_stat_vec<obj_type>::eT>& sample, const typename arma_cx_only<typename running_stat_vec<obj_type>::eT>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename running_stat_vec<obj_type>::eT eT; typedef typename running_stat_vec<obj_type>::T T; const T N = x.counter.value(); if(N > T(0)) { arma_debug_assert_same_size(x.r_mean, sample, "running_stat_vec(): dimensionality mismatch"); const uword n_elem = sample.n_elem; const eT* sample_mem = sample.memptr(); eT* r_mean_mem = x.r_mean.memptr(); T* r_var_mem = x.r_var.memptr(); eT* min_val_mem = x.min_val.memptr(); eT* max_val_mem = x.max_val.memptr(); T* min_val_norm_mem = x.min_val_norm.memptr(); T* max_val_norm_mem = x.max_val_norm.memptr(); const T N_plus_1 = x.counter.value_plus_1(); const T N_minus_1 = x.counter.value_minus_1(); if(x.calc_cov == true) { Mat<eT>& tmp1 = x.tmp1; Mat<eT>& tmp2 = x.tmp2; tmp1 = sample - x.r_mean; if(sample.n_cols == 1) { tmp2 = arma::conj(tmp1)*strans(tmp1); } else { tmp2 = trans(tmp1)*tmp1; //tmp2 = strans(conj(tmp1))*tmp1; } x.r_cov *= (N_minus_1/N); x.r_cov += tmp2 / N_plus_1; } for(uword i=0; i<n_elem; ++i) { const eT& val = sample_mem[i]; const T val_norm = std::norm(val); if(val_norm < min_val_norm_mem[i]) { min_val_norm_mem[i] = val_norm; min_val_mem[i] = val; } if(val_norm > max_val_norm_mem[i]) { max_val_norm_mem[i] = val_norm; max_val_mem[i] = val; } const eT& r_mean_val = r_mean_mem[i]; r_var_mem[i] = N_minus_1/N * r_var_mem[i] + std::norm(val - r_mean_val)/N_plus_1; r_mean_mem[i] = r_mean_val + (val - r_mean_val)/N_plus_1; } } else { arma_debug_check( (sample.is_vec() == false), "running_stat_vec(): given sample is not a vector"); x.r_mean.set_size(sample.n_rows, sample.n_cols); x.r_var.zeros(sample.n_rows, sample.n_cols); if(x.calc_cov == true) { x.r_cov.zeros(sample.n_elem, sample.n_elem); } x.min_val.set_size(sample.n_rows, sample.n_cols); x.max_val.set_size(sample.n_rows, sample.n_cols); x.min_val_norm.set_size(sample.n_rows, sample.n_cols); x.max_val_norm.set_size(sample.n_rows, sample.n_cols); const uword n_elem = sample.n_elem; const eT* sample_mem = sample.memptr(); eT* r_mean_mem = x.r_mean.memptr(); eT* min_val_mem = x.min_val.memptr(); eT* max_val_mem = x.max_val.memptr(); T* min_val_norm_mem = x.min_val_norm.memptr(); T* max_val_norm_mem = x.max_val_norm.memptr(); for(uword i=0; i<n_elem; ++i) { const eT& val = sample_mem[i]; const T val_norm = std::norm(val); r_mean_mem[i] = val; min_val_mem[i] = val; max_val_mem[i] = val; min_val_norm_mem[i] = val_norm; max_val_norm_mem[i] = val_norm; } } x.counter++; }
inline arma_warn_unused typename T1::pod_type norm ( const Base<typename T1::elem_type,T1>& X, const uword k, const typename arma_float_or_cx_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename T1::pod_type T; const Proxy<T1> A(X.get_ref()); if(A.get_n_elem() == 0) { return T(0); } const bool is_vec = (A.get_n_rows() == 1) || (A.get_n_cols() == 1); if(is_vec == true) { switch(k) { case 1: return arma_vec_norm_1(A); break; case 2: return arma_vec_norm_2(A); break; default: { arma_debug_check( (k == 0), "norm(): k must be greater than zero" ); return arma_vec_norm_k(A, int(k)); } } } else { switch(k) { case 1: return arma_mat_norm_1(A); break; case 2: return arma_mat_norm_2(A); break; default: arma_stop("norm(): unsupported matrix norm type"); return T(0); } } }
inline bool arma_sort_index_helper(Mat<uword>& out, const Proxy<T1>& P, const uword sort_type, typename arma_not_cx<typename T1::elem_type>::result* junk = 0) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; const uword n_elem = P.get_n_elem(); out.set_size(n_elem, 1); std::vector< arma_sort_index_packet<eT, uword> > packet_vec(n_elem); if(Proxy<T1>::prefer_at_accessor == false) { for(uword i=0; i<n_elem; ++i) { const eT val = P[i]; if(arma_isnan(val)) { out.reset(); return false; } packet_vec[i].val = val; packet_vec[i].index = i; } } else { const uword n_rows = P.get_n_rows(); const uword n_cols = P.get_n_cols(); uword i = 0; for(uword col=0; col < n_cols; ++col) for(uword row=0; row < n_rows; ++row) { const eT val = P.at(row,col); if(arma_isnan(val)) { out.reset(); return false; } packet_vec[i].val = val; packet_vec[i].index = i; ++i; } } if(sort_type == 0) { // ascend arma_sort_index_helper_ascend comparator; if(sort_stable == false) { std::sort( packet_vec.begin(), packet_vec.end(), comparator ); } else { std::stable_sort( packet_vec.begin(), packet_vec.end(), comparator ); } } else { // descend arma_sort_index_helper_descend comparator; if(sort_stable == false) { std::sort( packet_vec.begin(), packet_vec.end(), comparator ); } else { std::stable_sort( packet_vec.begin(), packet_vec.end(), comparator ); } } uword* out_mem = out.memptr(); for(uword i=0; i<n_elem; ++i) { out_mem[i] = packet_vec[i].index; } return true; }
inline bool op_any::any_vec_helper ( const mtOp<uword, T1, op_type>& X, const typename arma_op_rel_only<op_type>::result junk1, const typename arma_not_cx<typename T1::elem_type>::result junk2 ) { arma_extra_debug_sigprint(); arma_ignore(junk1); arma_ignore(junk2); typedef typename T1::elem_type eT; const eT val = X.aux; const Proxy<T1> P(X.m); if(Proxy<T1>::prefer_at_accessor == false) { typename Proxy<T1>::ea_type Pea = P.get_ea(); const uword n_elem = P.get_n_elem(); for(uword i=0; i < n_elem; ++i) { const eT tmp = Pea[i]; if(is_same_type<op_type, op_rel_lt_pre >::yes) { if(val < tmp) { return true; } } else if(is_same_type<op_type, op_rel_lt_post >::yes) { if(tmp < val) { return true; } } else if(is_same_type<op_type, op_rel_gt_pre >::yes) { if(val > tmp) { return true; } } else if(is_same_type<op_type, op_rel_gt_post >::yes) { if(tmp > val) { return true; } } else if(is_same_type<op_type, op_rel_lteq_pre >::yes) { if(val <= tmp) { return true; } } else if(is_same_type<op_type, op_rel_lteq_post>::yes) { if(tmp <= val) { return true; } } else if(is_same_type<op_type, op_rel_gteq_pre >::yes) { if(val >= tmp) { return true; } } else if(is_same_type<op_type, op_rel_gteq_post>::yes) { if(tmp >= val) { return true; } } else if(is_same_type<op_type, op_rel_eq >::yes) { if(tmp == val) { return true; } } else if(is_same_type<op_type, op_rel_noteq >::yes) { if(tmp != val) { return true; } } } } 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) { const eT tmp = P.at(row,col); if(is_same_type<op_type, op_rel_lt_pre >::yes) { if(val < tmp) { return true; } } else if(is_same_type<op_type, op_rel_lt_post >::yes) { if(tmp < val) { return true; } } else if(is_same_type<op_type, op_rel_gt_pre >::yes) { if(val > tmp) { return true; } } else if(is_same_type<op_type, op_rel_gt_post >::yes) { if(tmp > val) { return true; } } else if(is_same_type<op_type, op_rel_lteq_pre >::yes) { if(val <= tmp) { return true; } } else if(is_same_type<op_type, op_rel_lteq_post>::yes) { if(tmp <= val) { return true; } } else if(is_same_type<op_type, op_rel_gteq_pre >::yes) { if(val >= tmp) { return true; } } else if(is_same_type<op_type, op_rel_gteq_post>::yes) { if(tmp >= val) { return true; } } else if(is_same_type<op_type, op_rel_eq >::yes) { if(tmp == val) { return true; } } else if(is_same_type<op_type, op_rel_noteq >::yes) { if(tmp != val) { return true; } } } } return false; }
inline bool op_any::any_vec_helper ( const mtGlue<uword, T1, T2, glue_type>& X, const typename arma_glue_rel_only<glue_type>::result junk1, const typename arma_not_cx<typename T1::elem_type>::result junk2, const typename arma_not_cx<typename T2::elem_type>::result junk3 ) { arma_extra_debug_sigprint(); arma_ignore(junk1); arma_ignore(junk2); arma_ignore(junk3); typedef typename T1::elem_type eT1; typedef typename T2::elem_type eT2; typedef typename Proxy<T1>::ea_type ea_type1; typedef typename Proxy<T2>::ea_type ea_type2; const Proxy<T1> A(X.A); const Proxy<T2> B(X.B); arma_debug_assert_same_size(A, B, "relational operator"); const bool prefer_at_accessor = Proxy<T1>::prefer_at_accessor || Proxy<T2>::prefer_at_accessor; if(prefer_at_accessor == false) { ea_type1 PA = A.get_ea(); ea_type2 PB = B.get_ea(); const uword n_elem = A.get_n_elem(); for(uword i=0; i<n_elem; ++i) { const eT1 tmp1 = PA[i]; const eT2 tmp2 = PB[i]; if(is_same_type<glue_type, glue_rel_lt >::yes) { if(tmp1 < tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_gt >::yes) { if(tmp1 > tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_lteq >::yes) { if(tmp1 <= tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_gteq >::yes) { if(tmp1 >= tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_eq >::yes) { if(tmp1 == tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_noteq >::yes) { if(tmp1 != tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_and >::yes) { if(tmp1 && tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_or >::yes) { if(tmp1 || tmp2) { return true; } } } } else { const uword n_rows = A.get_n_rows(); const uword n_cols = A.get_n_cols(); for(uword col=0; col < n_cols; ++col) for(uword row=0; row < n_rows; ++row) { const eT1 tmp1 = A.at(row,col); const eT2 tmp2 = B.at(row,col); if(is_same_type<glue_type, glue_rel_lt >::yes) { if(tmp1 < tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_gt >::yes) { if(tmp1 > tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_lteq >::yes) { if(tmp1 <= tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_gteq >::yes) { if(tmp1 >= tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_eq >::yes) { if(tmp1 == tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_noteq >::yes) { if(tmp1 != tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_and >::yes) { if(tmp1 && tmp2) { return true; } } else if(is_same_type<glue_type, glue_rel_or >::yes) { if(tmp1 || tmp2) { return true; } } } } return false; }
inline arma_warn_unused typename enable_if2< is_arma_sparse_type<T1>::value, typename T1::pod_type >::result norm ( const T1& X, const uword k = uword(2), const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename T1::pod_type T; const SpProxy<T1> P(X); if(P.get_n_nonzero() == 0) { return T(0); } const bool is_vec = (P.get_n_rows() == 1) || (P.get_n_cols() == 1); if(is_vec == true) { const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q); const SpMat<eT>& A = tmp.M; // create a fake dense vector to allow reuse of code for dense vectors Col<eT> fake_vector( access::rwp(A.values), A.n_nonzero, false ); const Proxy< Col<eT> > P_fake_vector(fake_vector); switch(k) { case 1: return op_norm::vec_norm_1(P_fake_vector); break; case 2: return op_norm::vec_norm_2(P_fake_vector); break; default: { arma_debug_check( (k == 0), "norm(): k must be greater than zero" ); return op_norm::vec_norm_k(P_fake_vector, int(k)); } } } else { switch(k) { case 1: return op_norm::mat_norm_1(P); break; case 2: return op_norm::mat_norm_2(P); break; default: arma_stop_logic_error("norm(): unsupported or unimplemented norm type for sparse matrices"); return T(0); } } }
inline std::streamsize arma_ostream::modify_stream(std::ostream& o, typename SpMat<eT>::const_iterator begin, const uword n_elem, const typename arma_not_cx<eT>::result* junk) { arma_extra_debug_sigprint(); arma_ignore(junk); o.unsetf(ios::showbase); o.unsetf(ios::uppercase); o.unsetf(ios::showpos); o.fill(' '); std::streamsize cell_width; bool use_layout_B = false; bool use_layout_C = false; for(typename SpMat<eT>::const_iterator it = begin; it.pos() < n_elem; ++it) { const eT val = *it; if( val >= eT(+100) || ( (is_signed<eT>::value == true) && (val <= eT(-100)) ) || ( (is_non_integral<eT>::value == true) && (val > eT(0)) && (val <= eT(+1e-4)) ) || ( (is_non_integral<eT>::value == true) && (is_signed<eT>::value == true) && (val < eT(0)) && (val >= eT(-1e-4)) ) ) { use_layout_C = true; break; } if( (val >= eT(+10)) || ( (is_signed<eT>::value == true) && (val <= eT(-10)) ) ) { use_layout_B = true; } } if(use_layout_C == true) { o.setf(ios::scientific); o.setf(ios::right); o.unsetf(ios::fixed); o.precision(4); cell_width = 13; } else if(use_layout_B == true) { o.unsetf(ios::scientific); o.setf(ios::right); o.setf(ios::fixed); o.precision(4); cell_width = 10; } else { o.unsetf(ios::scientific); o.setf(ios::right); o.setf(ios::fixed); o.precision(4); cell_width = 9; } return cell_width; }
inline arma_warn_unused typename enable_if2< is_arma_type<T1>::value, typename T1::pod_type >::result norm ( const T1& X, const uword k = uword(2), const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::pod_type T; const Proxy<T1> P(X); if(P.get_n_elem() == 0) { return T(0); } const bool is_vec = (T1::is_row) || (T1::is_col) || (P.get_n_rows() == 1) || (P.get_n_cols() == 1); if(is_vec) { switch(k) { case 1: return op_norm::vec_norm_1(P); break; case 2: return op_norm::vec_norm_2(P); break; default: { arma_debug_check( (k == 0), "norm(): k must be greater than zero" ); return op_norm::vec_norm_k(P, int(k)); } } } else { switch(k) { case 1: return op_norm::mat_norm_1(P); break; case 2: return op_norm::mat_norm_2(P); break; default: arma_stop_logic_error("norm(): unsupported matrix norm type"); return T(0); } } return T(0); // prevent erroneous compiler warnings }
inline bool eig_gen ( Col< std::complex<eT> >& eigval, Mat< std::complex<eT> >& eigvec, const Base<eT, T1>& X, const char side = 'r', const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); //std::cout << "real" << std::endl; arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_gen(): eigval is an alias of eigvec" ); Mat<eT> dummy_eigvec; Mat<eT> tmp_eigvec; bool status; switch(side) { case 'r': status = auxlib::eig_gen(eigval, dummy_eigvec, tmp_eigvec, X, side); break; case 'l': status = auxlib::eig_gen(eigval, tmp_eigvec, dummy_eigvec, X, side); break; default: arma_stop("eig_gen(): parameter 'side' is invalid"); status = false; } if(status == false) { eigval.reset(); eigvec.reset(); arma_bad("eig_gen(): failed to converge", false); } else { const uword n = eigval.n_elem; if(n > 0) { eigvec.set_size(n,n); for(uword j=0; j<n; ++j) { if( (j < n-1) && (eigval[j] == std::conj(eigval[j+1])) ) { // eigvec.col(j) = Mat< std::complex<eT> >( tmp_eigvec.col(j), tmp_eigvec.col(j+1) ); // eigvec.col(j+1) = Mat< std::complex<eT> >( tmp_eigvec.col(j), -tmp_eigvec.col(j+1) ); for(uword i=0; i<n; ++i) { eigvec.at(i,j) = std::complex<eT>( tmp_eigvec.at(i,j), tmp_eigvec.at(i,j+1) ); eigvec.at(i,j+1) = std::complex<eT>( tmp_eigvec.at(i,j), -tmp_eigvec.at(i,j+1) ); } ++j; } else { // eigvec.col(i) = tmp_eigvec.col(i); for(uword i=0; i<n; ++i) { eigvec.at(i,j) = std::complex<eT>(tmp_eigvec.at(i,j), eT(0)); } } } } } return status; }
inline arma_warn_unused typename enable_if2< is_arma_type<T1>::value, typename T1::pod_type >::result norm ( const T1& X, const char* method, const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::pod_type T; const Proxy<T1> P(X); if(P.get_n_elem() == 0) { return T(0); } const char sig = (method != NULL) ? method[0] : char(0); const bool is_vec = (T1::is_row) || (T1::is_col) || (P.get_n_rows() == 1) || (P.get_n_cols() == 1); if(is_vec) { if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // max norm { return op_norm::vec_norm_max(P); } else if(sig == '-') // min norm { return op_norm::vec_norm_min(P); } else if( (sig == 'f') || (sig == 'F') ) { return op_norm::vec_norm_2(P); } else { arma_stop_logic_error("norm(): unsupported vector norm type"); return T(0); } } else { if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm { return op_norm::mat_norm_inf(P); } else if( (sig == 'f') || (sig == 'F') ) { return op_norm::vec_norm_2(P); } else { arma_stop_logic_error("norm(): unsupported matrix norm type"); return T(0); } } }
arma_warn_unused inline cube_type randg(const uword n_rows, const uword n_cols, const uword n_slices, const distr_param& param = distr_param(), const typename arma_Cube_only<cube_type>::result* junk = 0) { arma_extra_debug_sigprint(); arma_ignore(junk); #if defined(ARMA_USE_CXX11) { cube_type out(n_rows, n_cols, n_slices); double a; double b; if(param.state == 0) { a = double(1); b = double(1); } else if(param.state == 1) { a = double(param.a_int); b = double(param.b_int); } else { a = param.a_double; b = param.b_double; } arma_debug_check( ((a <= double(0)) || (b <= double(0))), "randg(): a and b must be greater than zero" ); #if defined(ARMA_USE_EXTERN_CXX11_RNG) { arma_rng_cxx11_instance.randg_fill(out.memptr(), out.n_elem, a, b); } #else { arma_rng_cxx11 local_arma_rng_cxx11_instance; typedef typename arma_rng_cxx11::seed_type seed_type; local_arma_rng_cxx11_instance.set_seed( seed_type(arma_rng::randi<seed_type>()) ); local_arma_rng_cxx11_instance.randg_fill(out.memptr(), out.n_elem, a, b); } #endif return out; } #else { arma_ignore(n_rows); arma_ignore(n_cols); arma_ignore(n_slices); arma_ignore(param); arma_stop_logic_error("randg(): C++11 compiler required"); return cube_type(); } #endif }
arma_hot inline typename T1::pod_type op_norm::vec_norm_1(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_1_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) { acc1 += std::abs(A[i]); acc2 += std::abs(A[j]); } if(i < N) { acc1 += std::abs(A[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) { acc += std::abs(P.at(0,col)); } } else { T acc1 = T(0); T acc2 = T(0); for(uword col=0; col<n_cols; ++col) { uword i,j; for(i=0, j=1; j<n_rows; i+=2, j+=2) { acc1 += std::abs(P.at(i,col)); acc2 += std::abs(P.at(j,col)); } if(i < n_rows) { acc1 += std::abs(P.at(i,col)); } } acc = acc1 + acc2; } } return acc; }
inline std::string diskio::gen_bin_header(const Mat<eT>& x) { arma_type_check<diskio::is_supported_type<eT>::value == false>::apply(); arma_ignore(x); if(is_u8<eT>::value == true) { return std::string("ARMA_MAT_BIN_IU001"); } else if(is_s8<eT>::value == true) { return std::string("ARMA_MAT_BIN_IS001"); } else if(is_u16<eT>::value == true) { return std::string("ARMA_MAT_BIN_IU002"); } else if(is_s16<eT>::value == true) { return std::string("ARMA_MAT_BIN_IS002"); } else if(is_u32<eT>::value == true) { return std::string("ARMA_MAT_BIN_IU004"); } else if(is_s32<eT>::value == true) { return std::string("ARMA_MAT_BIN_IS004"); } else if(is_float<eT>::value == true) { return std::string("ARMA_MAT_BIN_FN004"); } else if(is_double<eT>::value == true) { return std::string("ARMA_MAT_BIN_FN008"); } else if(is_complex_float<eT>::value == true) { return std::string("ARMA_MAT_BIN_FC008"); } else if(is_complex_double<eT>::value == true) { return std::string("ARMA_MAT_BIN_FC016"); } else { return std::string(); } }
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 ); } }
inline void op_trimat::apply_htrans ( Mat<eT>& out, const Mat<eT>& A, const bool upper, const typename arma_not_cx<eT>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); // This specialisation is for trimatl(trans(X)) = trans(trimatu(X)) and also // trimatu(trans(X)) = trans(trimatl(X)). We want to avoid the creation of an // extra temporary. // It doesn't matter if the input and output matrices are the same; we will // pull data from the upper or lower triangular to the lower or upper // triangular (respectively) and then set the rest to 0, so overwriting issues // aren't present. arma_debug_check( (A.is_square() == false), "trimatu()/trimatl(): given matrix must be square sized" ); const uword N = A.n_rows; if(&out != &A) { out.copy_size(A); } // We can't really get away with any array copy operations here, // unfortunately... if(upper) { // Upper triangular: but since we're transposing, we're taking the lower // triangular and putting it in the upper half. for(uword row = 0; row < N; ++row) { eT* out_colptr = out.colptr(row); for(uword col = 0; col <= row; ++col) { //out.at(col, row) = A.at(row, col); out_colptr[col] = A.at(row, col); } } } else { // Lower triangular: but since we're transposing, we're taking the upper // triangular and putting it in the lower half. for(uword row = 0; row < N; ++row) { for(uword col = row; col < N; ++col) { out.at(col, row) = A.at(row, col); } } } op_trimat::fill_zeros(out, upper); }
inline bool spsolve_helper ( Mat<typename T1::elem_type>& out, const SpBase<typename T1::elem_type, T1>& A, const Base<typename T1::elem_type, T2>& B, const char* solver, const spsolve_opts_base& settings, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::pod_type T; typedef typename T1::elem_type eT; const char sig = (solver != NULL) ? solver[0] : char(0); arma_debug_check( ((sig != 'l') && (sig != 's')), "spsolve(): unknown solver" ); T rcond = T(0); bool status = false; if(sig == 's') // SuperLU solver { const superlu_opts& opts = (settings.id == 1) ? static_cast<const superlu_opts&>(settings) : superlu_opts(); arma_debug_check( ( (opts.pivot_thresh < double(0)) || (opts.pivot_thresh > double(1)) ), "spsolve(): pivot_thresh out of bounds" ); if( (opts.equilibrate == false) && (opts.refine == superlu_opts::REF_NONE) ) { status = sp_auxlib::spsolve_simple(out, A.get_ref(), B.get_ref(), opts); } else { status = sp_auxlib::spsolve_refine(out, rcond, A.get_ref(), B.get_ref(), opts); } } else if(sig == 'l') // brutal LAPACK solver { if(settings.id != 0) { arma_debug_warn("spsolve(): ignoring settings not applicable to LAPACK based solver"); } Mat<eT> AA; bool conversion_ok = false; try { Mat<eT> tmp(A.get_ref()); // conversion from sparse to dense can throw std::bad_alloc AA.steal_mem(tmp); conversion_ok = true; } catch(std::bad_alloc&) { arma_debug_warn("spsolve(): not enough memory to use LAPACK based solver"); } if(conversion_ok) { arma_debug_check( (AA.n_rows != AA.n_cols), "spsolve(): matrix A must be square sized" ); status = auxlib::solve_square_refine(out, rcond, AA, B.get_ref(), false); } } if(status == false) { if(rcond > T(0)) { arma_debug_warn("spsolve(): system appears singular (rcond: ", rcond, ")"); } else { arma_debug_warn("spsolve(): system appears singular"); } out.reset(); } return status; }
inline typename T1::elem_type op_median::median_vec ( const T1& X, const typename arma_not_cx<typename T1::elem_type>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename Proxy<T1>::stored_type P_stored_type; const Proxy<T1> P(X); const uword n_elem = P.get_n_elem(); if(n_elem == 0) { arma_debug_check(true, "median(): object has no elements"); return Datum<eT>::nan; } std::vector<eT> tmp_vec(n_elem); if(is_Mat<P_stored_type>::value == true) { const unwrap<P_stored_type> tmp(P.Q); const typename unwrap<P_stored_type>::stored_type& Y = tmp.M; arrayops::copy( &(tmp_vec[0]), Y.memptr(), n_elem ); } else { if(Proxy<T1>::prefer_at_accessor == false) { typedef typename Proxy<T1>::ea_type ea_type; ea_type A = P.get_ea(); for(uword i=0; i<n_elem; ++i) { tmp_vec[i] = A[i]; } } else { const uword n_rows = P.get_n_rows(); const uword n_cols = P.get_n_cols(); if(n_cols == 1) { for(uword row=0; row < n_rows; ++row) { tmp_vec[row] = P.at(row,0); } } else if(n_rows == 1) { for(uword col=0; col < n_cols; ++col) { tmp_vec[col] = P.at(0,col); } } else { arma_stop("op_median::median_vec(): expected a vector" ); } } } return op_median::direct_median(tmp_vec); }
inline obj_type randg(const uword n_rows, const uword n_cols, const distr_param& param = distr_param(), const typename arma_Mat_Col_Row_only<obj_type>::result* junk = 0) { arma_extra_debug_sigprint(); arma_ignore(junk); #if defined(ARMA_USE_CXX11) { if(is_Col<obj_type>::value == true) { arma_debug_check( (n_cols != 1), "randg(): incompatible size" ); } else if(is_Row<obj_type>::value == true) { arma_debug_check( (n_rows != 1), "randg(): incompatible size" ); } obj_type out(n_rows, n_cols); double a; double b; if(param.state == 0) { a = double(1); b = double(1); } else if(param.state == 1) { a = double(param.a_int); b = double(param.b_int); } else { a = param.a_double; b = param.b_double; } arma_debug_check( ((a <= double(0)) || (b <= double(0))), "randg(): a and b must be greater than zero" ); #if defined(ARMA_USE_EXTERN_CXX11_RNG) { arma_rng_cxx11_instance.randg_fill(out.memptr(), out.n_elem, a, b); } #else { arma_rng_cxx11 local_arma_rng_cxx11_instance; typedef typename arma_rng_cxx11::seed_type seed_type; local_arma_rng_cxx11_instance.set_seed( seed_type(arma_rng::randi<seed_type>()) ); local_arma_rng_cxx11_instance.randg_fill(out.memptr(), out.n_elem, a, b); } #endif return out; } #else { arma_ignore(n_rows); arma_ignore(n_cols); arma_ignore(param); arma_stop("randg(): C++11 compiler required"); return obj_type(); } #endif }
inline void op_min::apply_noalias(Cube<eT>& out, const Cube<eT>& X, const uword dim, const typename arma_cx_only<eT>::result* junk) { arma_extra_debug_sigprint(); arma_ignore(junk); 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) { arma_extra_debug_print("op_min::apply(): 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_min::direct_min( X.slice_colptr(slice,col), X_n_rows ); } } } else if(dim == 1) { arma_extra_debug_print("op_min::apply(): dim = 1"); out.set_size(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); 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] = op_min::direct_min(tmp, row); } } } else if(dim == 2) { arma_extra_debug_print("op_min::apply(): dim = 2"); out.set_size(X_n_rows, X_n_cols, (X_n_slices > 0) ? 1 : 0); if(X_n_slices == 0) { return; } const uword N = X.n_elem_slice; eT* out_mem = out.slice_memptr(0); arrayops::copy(out_mem, X.slice_memptr(0), N); for(uword slice=1; slice < X_n_slices; ++slice) { const eT* X_mem = X.slice_memptr(slice); for(uword i=0; i < N; ++i) { const eT& val = X_mem[i]; if(std::abs(val) < std::abs(out_mem[i])) { out_mem[i] = val; } } } } }