inline void glue_min::apply(Cube<eT>& out, const ProxyCube<T1>& PA, const ProxyCube<T2>& PB) { arma_extra_debug_sigprint(); const uword n_rows = PA.get_n_rows(); const uword n_cols = PA.get_n_cols(); const uword n_slices = PA.get_n_slices(); arma_debug_assert_same_size(n_rows, n_cols, n_slices, PB.get_n_rows(), PB.get_n_cols(), PB.get_n_slices(), "min(): given cubes must have the same size"); out.set_size(n_rows, n_cols, n_slices); eT* out_mem = out.memptr(); if( (ProxyCube<T1>::use_at == false) && (ProxyCube<T2>::use_at == false) ) { typename ProxyCube<T1>::ea_type A = PA.get_ea(); typename ProxyCube<T2>::ea_type B = PB.get_ea(); const uword N = PA.get_n_elem(); for(uword i=0; i<N; ++i) { out_mem[i] = (std::min)(A[i], B[i]); } } else { for(uword slice=0; slice < n_slices; ++slice) for(uword col=0; col < n_cols; ++col ) for(uword row=0; row < n_rows; ++row ) { *out_mem = (std::min)( PA.at(row,col,slice), PB.at(row,col,slice) ); ++out_mem; } } }
inline void subview_cube<eT>::operator/= (const Base<eT,T1>& in) { arma_extra_debug_sigprint(); const unwrap<T1> tmp(in.get_ref()); const Mat<eT>& x = tmp.M; subview_cube<eT>& t = *this; arma_debug_assert_same_size(t, x, "element-wise cube division"); const u32 t_n_rows = t.n_rows; const u32 t_n_cols = t.n_cols; const u32 t_aux_slice1 = t.aux_slice1; for(u32 col = 0; col < t_n_cols; ++col) { arrayops::inplace_div( t.slice_colptr(t_aux_slice1, col), x.colptr(col), t_n_rows ); } }
inline void spglue_minus_mixed::dense_minus_sparse(Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type >::result>& out, const T1& X, const T2& Y) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT1; typedef typename T2::elem_type eT2; typedef typename promote_type<eT1,eT2>::result out_eT; promote_type<eT1,eT2>::check(); if(is_same_type<eT1,out_eT>::no) { out = conv_to< Mat<out_eT> >::from(X); } else { const quasi_unwrap<T1> UA(X); const Mat<eT1>& A = UA.M; out = reinterpret_cast< const Mat<out_eT>& >(A); } const SpProxy<T2> pb(Y); arma_debug_assert_same_size( out.n_rows, out.n_cols, pb.get_n_rows(), pb.get_n_cols(), "subtraction" ); typename SpProxy<T2>::const_iterator_type it = pb.begin(); typename SpProxy<T2>::const_iterator_type it_end = pb.end(); while(it != it_end) { out.at(it.row(), it.col()) -= out_eT(*it); ++it; } }
inline void subview_cube<eT>::operator= (const Base<eT,T1>& in) { arma_extra_debug_sigprint(); const unwrap<T1> tmp(in.get_ref()); const Mat<eT>& x = tmp.M; subview_cube<eT>& t = *this; arma_debug_assert_same_size(t, x, "copy into subcube"); const u32 t_n_rows = t.n_rows; const u32 t_n_cols = t.n_cols; const u32 t_aux_slice1 = t.aux_slice1; for(u32 col = 0; col < t_n_cols; ++col) { syslib:copy_elem( t.slice_colptr(t_aux_slice1, col), x.colptr(col), t_n_rows ); } }
inline void subview_cube<eT>::operator/= (const subview_cube<eT>& x_in) { arma_extra_debug_sigprint(); const bool overlap = check_overlap(x_in); Cube<eT>* tmp_cube = overlap ? new Cube<eT>(x_in.m) : 0; const subview_cube<eT>* tmp_subview_cube = overlap ? new subview_cube<eT>(*tmp_cube, x_in.aux_row1, x_in.aux_col1, x_in.aux_slice1, x_in.aux_row2, x_in.aux_col2, x_in.aux_slice2) : 0; const subview_cube<eT>& x = overlap ? (*tmp_subview_cube) : x_in; subview_cube<eT>& t = *this; arma_debug_assert_same_size(t, x, "element-wise cube division"); for(u32 slice = 0; slice < t.n_slices; ++slice) { for(u32 col = 0; col < t.n_cols; ++col) { eT* t_coldata = t.slice_colptr(slice,col); const eT* x_coldata = x.slice_colptr(slice,col); for(u32 row = 0; row < t.n_rows; ++row) { t_coldata[row] /= x_coldata[row]; } } } if(overlap) { delete tmp_subview_cube; delete tmp_cube; } }
inline void glue_min::apply(Mat<eT>& out, const Proxy<T1>& PA, const Proxy<T2>& PB) { arma_extra_debug_sigprint(); const uword n_rows = PA.get_n_rows(); const uword n_cols = PA.get_n_cols(); arma_debug_assert_same_size(n_rows, n_cols, PB.get_n_rows(), PB.get_n_cols(), "element-wise minimum"); out.set_size(n_rows, n_cols); eT* out_mem = out.memptr(); if( (Proxy<T1>::use_at == false) && (Proxy<T2>::use_at == false) ) { typename Proxy<T1>::ea_type A = PA.get_ea(); typename Proxy<T2>::ea_type B = PB.get_ea(); const uword N = PA.get_n_elem(); for(uword i=0; i<N; ++i) { out_mem[i] = (std::min)(A[i], B[i]); } } else { for(uword col=0; col < n_cols; ++col) for(uword row=0; row < n_rows; ++row) { *out_mem = (std::min)( PA.at(row,col), PB.at(row,col) ); ++out_mem; } } }
arma_warn_unused arma_hot inline typename enable_if2 <(is_arma_type<T1>::value) && (is_arma_sparse_type<T2>::value) && (is_same_type<typename T1::elem_type, typename T2::elem_type>::value), typename T1::elem_type >::result dot ( const T1& x, const T2& y ) { arma_extra_debug_sigprint(); const Proxy<T1> pa(x); const SpProxy<T2> pb(y); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "dot()"); typedef typename T1::elem_type eT; eT result = eT(0); typename SpProxy<T2>::const_iterator_type it = pb.begin(); typename SpProxy<T2>::const_iterator_type it_end = pb.end(); // prefer_at_accessor won't save us operations while(it != it_end) { result += (*it) * pa.at(it.row(), it.col()); ++it; } return result; }
inline void subview_cube<eT>::operator%= (const Base<eT,T1>& in) { arma_extra_debug_sigprint(); const unwrap<T1> tmp(in.get_ref()); const Mat<eT>& x = tmp.M; subview_cube<eT>& t = *this; arma_debug_assert_same_size(t, x, "cube schur product"); for(u32 col = 0; col<t.n_cols; ++col) { eT* t_coldata = t.slice_colptr(t.aux_slice1, col); const eT* x_coldata = x.colptr(col); for(u32 row = 0; row<t.n_rows; ++row) { t_coldata[row] *= x_coldata[row]; } } }
arma_hot inline void spglue_minus::apply_noalias(SpMat<eT>& out, const SpProxy<T1>& pa, const SpProxy<T2>& pb) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "subtraction"); if(pa.get_n_nonzero() == 0) { out = pb.Q; out *= eT(-1); return; } if(pb.get_n_nonzero() == 0) { out = pa.Q; return; } const uword max_n_nonzero = spglue_elem_helper::max_n_nonzero_plus(pa, pb); // Resize memory to upper bound out.reserve(pa.get_n_rows(), pa.get_n_cols(), max_n_nonzero); // Now iterate across both matrices. typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); typename SpProxy<T1>::const_iterator_type x_end = pa.end(); typename SpProxy<T2>::const_iterator_type y_it = pb.begin(); typename SpProxy<T2>::const_iterator_type y_end = pb.end(); uword count = 0; while( (x_it != x_end) || (y_it != y_end) ) { eT out_val; const uword x_it_row = x_it.row(); const uword x_it_col = x_it.col(); const uword y_it_row = y_it.row(); const uword y_it_col = y_it.col(); bool use_y_loc = false; if(x_it == y_it) { out_val = (*x_it) - (*y_it); ++x_it; ++y_it; } else { if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end { out_val = (*x_it); ++x_it; } else { out_val = -(*y_it); // take the negative ++y_it; use_y_loc = true; } } if(out_val != eT(0)) { access::rw(out.values[count]) = out_val; const uword out_row = (use_y_loc == false) ? x_it_row : y_it_row; const uword out_col = (use_y_loc == false) ? x_it_col : y_it_col; access::rw(out.row_indices[count]) = out_row; access::rw(out.col_ptrs[out_col + 1])++; ++count; } } const uword out_n_cols = out.n_cols; uword* col_ptrs = access::rwp(out.col_ptrs); // Fix column pointers to be cumulative. for(uword c = 1; c <= out_n_cols; ++c) { col_ptrs[c] += col_ptrs[c - 1]; } if(count < max_n_nonzero) { if(count <= (max_n_nonzero/2)) { out.mem_resize(count); } else { // quick resize without reallocating memory and copying data access::rw( out.n_nonzero) = count; access::rw( out.values[count]) = eT(0); access::rw(out.row_indices[count]) = uword(0); } } }
inline typename enable_if2 < (is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value), SpMat<typename T1::elem_type> >::result operator% ( const SpBase<typename T1::elem_type, T1>& x, const SpBase<typename T2::elem_type, T2>& y ) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const SpProxy<T1> pa(x.get_ref()); const SpProxy<T2> pb(y.get_ref()); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise multiplication"); SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()); if( (pa.get_n_nonzero() != 0) && (pb.get_n_nonzero() != 0) ) { // Resize memory to correct size. result.mem_resize(n_unique(x, y, op_n_unique_mul())); // Now iterate across both matrices. typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); typename SpProxy<T2>::const_iterator_type y_it = pb.begin(); typename SpProxy<T1>::const_iterator_type x_end = pa.end(); typename SpProxy<T2>::const_iterator_type y_end = pb.end(); uword cur_val = 0; while((x_it != x_end) || (y_it != y_end)) { if(x_it == y_it) { const eT val = (*x_it) * (*y_it); if (val != eT(0)) { access::rw(result.values[cur_val]) = val; access::rw(result.row_indices[cur_val]) = x_it.row(); ++access::rw(result.col_ptrs[x_it.col() + 1]); ++cur_val; } ++x_it; ++y_it; } else { const uword x_it_row = x_it.row(); const uword x_it_col = x_it.col(); const uword y_it_row = y_it.row(); const uword y_it_col = y_it.col(); if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end { ++x_it; } else { ++y_it; } } } // Fix column pointers to be cumulative. for(uword c = 1; c <= result.n_cols; ++c) { access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; } } return result; }
inline typename enable_if2 < (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value), SpMat<typename T1::elem_type> >::result operator% ( const T1& x, const T2& y ) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const Proxy<T1> pa(x); const SpProxy<T2> pb(y); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise multiplication"); SpMat<eT> result(pa.get_n_rows(), pa.get_n_cols()); // count new size uword new_n_nonzero = 0; typename SpProxy<T2>::const_iterator_type it = pb.begin(); typename SpProxy<T2>::const_iterator_type it_end = pb.end(); while(it != it_end) { if( ((*it) * pa.at(it.row(), it.col())) != eT(0) ) { ++new_n_nonzero; } ++it; } // Resize memory accordingly. result.mem_resize(new_n_nonzero); uword cur_val = 0; typename SpProxy<T2>::const_iterator_type it2 = pb.begin(); while(it2 != it_end) { const uword it2_row = it2.row(); const uword it2_col = it2.col(); const eT val = (*it2) * pa.at(it2_row, it2_col); if(val != eT(0)) { access::rw(result.values[cur_val]) = val; access::rw(result.row_indices[cur_val]) = it2_row; ++access::rw(result.col_ptrs[it2_col + 1]); ++cur_val; } ++it2; } // Fix column pointers. for(uword c = 1; c <= result.n_cols; ++c) { access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; } return result; }
inline const SpSubview<eT>& SpSubview<eT>::operator_equ_common(const SpBase<eT, T1>& in) { arma_extra_debug_sigprint(); // algorithm: // instead of directly inserting values into the matrix underlying the subview, // create a new matrix by merging the underlying matrix with the input object, // and then replacing the underlying matrix with the created matrix. // // the merging process requires pretending that the input object // has the same size as the underlying matrix. // while iterating through the elements of the input object, // this requires adjusting the row and column locations of each element, // as well as providing fake zero elements. // in effect there is a proxy for a proxy. const SpProxy< SpMat<eT> > pa((*this).m ); const SpProxy< T1 > pb(in.get_ref()); arma_debug_assert_same_size(n_rows, n_cols, pb.get_n_rows(), pb.get_n_cols(), "insertion into sparse submatrix"); const uword pa_start_row = (*this).aux_row1; const uword pa_start_col = (*this).aux_col1; const uword pa_end_row = pa_start_row + (*this).n_rows - 1; const uword pa_end_col = pa_start_col + (*this).n_cols - 1; const uword pa_n_rows = pa.get_n_rows(); SpMat<eT> out(pa.get_n_rows(), pa.get_n_cols()); const uword alt_count = pa.get_n_nonzero() - (*this).n_nonzero + pb.get_n_nonzero(); // Resize memory to correct size. out.mem_resize(alt_count); typename SpProxy< SpMat<eT> >::const_iterator_type x_it = pa.begin(); typename SpProxy< SpMat<eT> >::const_iterator_type x_end = pa.end(); typename SpProxy<T1>::const_iterator_type y_it = pb.begin(); typename SpProxy<T1>::const_iterator_type y_end = pb.end(); bool x_it_ok = (x_it != x_end); bool y_it_ok = (y_it != y_end); uword x_it_row = (x_it_ok) ? x_it.row() : 0; uword x_it_col = (x_it_ok) ? x_it.col() : 0; uword y_it_row = (y_it_ok) ? y_it.row() + pa_start_row : 0; uword y_it_col = (y_it_ok) ? y_it.col() + pa_start_col : 0; uword cur_val = 0; while(x_it_ok || y_it_ok) { const bool x_inside_box = (x_it_row >= pa_start_row) && (x_it_row <= pa_end_row) && (x_it_col >= pa_start_col) && (x_it_col <= pa_end_col); const bool y_inside_box = (y_it_row >= pa_start_row) && (y_it_row <= pa_end_row) && (y_it_col >= pa_start_col) && (y_it_col <= pa_end_col); const eT x_val = x_inside_box ? eT(0) : ( x_it_ok ? (*x_it) : eT(0) ); const eT y_val = y_inside_box ? ( y_it_ok ? (*y_it) : eT(0) ) : eT(0); if( (x_it_row == y_it_row) && (x_it_col == y_it_col) ) { if( (x_val != eT(0)) || (y_val != eT(0)) ) { access::rw(out.values[cur_val]) = (x_val != eT(0)) ? x_val : y_val; access::rw(out.row_indices[cur_val]) = x_it_row; ++access::rw(out.col_ptrs[x_it_col + 1]); ++cur_val; } if(x_it_ok) { ++x_it; if(x_it == x_end) { x_it_ok = false; } } if(x_it_ok) { x_it_row = x_it.row(); x_it_col = x_it.col(); } else { x_it_row++; if(x_it_row >= pa_n_rows) { x_it_row = 0; x_it_col++; } } if(y_it_ok) { ++y_it; if(y_it == y_end) { y_it_ok = false; } } if(y_it_ok) { y_it_row = y_it.row() + pa_start_row; y_it_col = y_it.col() + pa_start_col; } else { y_it_row++; if(y_it_row >= pa_n_rows) { y_it_row = 0; y_it_col++; } } } else { if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end { if(x_val != eT(0)) { access::rw(out.values[cur_val]) = x_val; access::rw(out.row_indices[cur_val]) = x_it_row; ++access::rw(out.col_ptrs[x_it_col + 1]); ++cur_val; } if(x_it_ok) { ++x_it; if(x_it == x_end) { x_it_ok = false; } } if(x_it_ok) { x_it_row = x_it.row(); x_it_col = x_it.col(); } else { x_it_row++; if(x_it_row >= pa_n_rows) { x_it_row = 0; x_it_col++; } } } else { if(y_val != eT(0)) { access::rw(out.values[cur_val]) = y_val; access::rw(out.row_indices[cur_val]) = y_it_row; ++access::rw(out.col_ptrs[y_it_col + 1]); ++cur_val; } if(y_it_ok) { ++y_it; if(y_it == y_end) { y_it_ok = false; } } if(y_it_ok) { y_it_row = y_it.row() + pa_start_row; y_it_col = y_it.col() + pa_start_col; } else { y_it_row++; if(y_it_row >= pa_n_rows) { y_it_row = 0; y_it_col++; } } } } } const uword out_n_cols = out.n_cols; uword* col_ptrs = access::rwp(out.col_ptrs); // Fix column pointers to be cumulative. for(uword c = 1; c <= out_n_cols; ++c) { col_ptrs[c] += col_ptrs[c - 1]; } access::rw((*this).m).steal_mem(out); access::rw(n_nonzero) = pb.get_n_nonzero(); return *this; }
inline void glue_mixed_plus::apply(Mat<typename eT_promoter<T1,T2>::eT>& out, const mtGlue<typename eT_promoter<T1,T2>::eT, T1, T2, glue_mixed_plus>& X) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT1; typedef typename T2::elem_type eT2; typedef typename promote_type<eT1,eT2>::result out_eT; promote_type<eT1,eT2>::check(); const Proxy<T1> A(X.A); const Proxy<T2> B(X.B); arma_debug_assert_same_size(A, B, "addition"); const uword n_rows = A.get_n_rows(); const uword n_cols = A.get_n_cols(); out.set_size(n_rows, n_cols); out_eT* out_mem = out.memptr(); const uword n_elem = out.n_elem; const bool prefer_at_accessor = (Proxy<T1>::prefer_at_accessor || Proxy<T2>::prefer_at_accessor); if(prefer_at_accessor == false) { typename Proxy<T1>::ea_type AA = A.get_ea(); typename Proxy<T2>::ea_type BB = B.get_ea(); if(memory::is_aligned(out_mem)) { memory::mark_as_aligned(out_mem); for(uword i=0; i<n_elem; ++i) { out_mem[i] = upgrade_val<eT1,eT2>::apply(AA[i]) + upgrade_val<eT1,eT2>::apply(BB[i]); } } else { for(uword i=0; i<n_elem; ++i) { out_mem[i] = upgrade_val<eT1,eT2>::apply(AA[i]) + upgrade_val<eT1,eT2>::apply(BB[i]); } } } else { uword i = 0; for(uword col=0; col < n_cols; ++col) for(uword row=0; row < n_rows; ++row) { out_mem[i] = upgrade_val<eT1,eT2>::apply(A.at(row,col)) + upgrade_val<eT1,eT2>::apply(B.at(row,col)); ++i; } } }
inline void running_stat_vec_aux::update_stats(running_stat_vec< std::complex<T> >& x, const Mat< std::complex<T> >& sample) { arma_extra_debug_sigprint(); typedef typename std::complex<T> eT; 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 u32 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 = conj(tmp1)*trans(tmp1); } else { tmp2 = trans(conj(tmp1))*tmp1; } x.r_cov *= (N_minus_1/N); x.r_cov += tmp2 / N_plus_1; } for(u32 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 u32 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(u32 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 const SpSubview<eT>& SpSubview<eT>::operator=(const Base<eT, T1>& in) { arma_extra_debug_sigprint(); // this is a modified version of SpSubview::operator_equ_common(const SpBase) const SpProxy< SpMat<eT> > pa((*this).m); const unwrap<T1> b_tmp(in.get_ref()); const Mat<eT>& b = b_tmp.M; arma_debug_assert_same_size(n_rows, n_cols, b.n_rows, b.n_cols, "insertion into sparse submatrix"); const uword pa_start_row = (*this).aux_row1; const uword pa_start_col = (*this).aux_col1; const uword pa_end_row = pa_start_row + (*this).n_rows - 1; const uword pa_end_col = pa_start_col + (*this).n_cols - 1; const uword pa_n_rows = pa.get_n_rows(); const uword b_n_elem = b.n_elem; const eT* b_mem = b.memptr(); uword box_count = 0; for(uword i=0; i<b_n_elem; ++i) { box_count += (b_mem[i] != eT(0)) ? uword(1) : uword(0); } SpMat<eT> out(pa.get_n_rows(), pa.get_n_cols()); const uword alt_count = pa.get_n_nonzero() - (*this).n_nonzero + box_count; // Resize memory to correct size. out.mem_resize(alt_count); typename SpProxy< SpMat<eT> >::const_iterator_type x_it = pa.begin(); typename SpProxy< SpMat<eT> >::const_iterator_type x_end = pa.end(); uword b_row = 0; uword b_col = 0; bool x_it_ok = (x_it != x_end); bool y_it_ok = ( (b_row < b.n_rows) && (b_col < b.n_cols) ); uword x_it_row = (x_it_ok) ? x_it.row() : 0; uword x_it_col = (x_it_ok) ? x_it.col() : 0; uword y_it_row = (y_it_ok) ? b_row + pa_start_row : 0; uword y_it_col = (y_it_ok) ? b_col + pa_start_col : 0; uword cur_val = 0; while(x_it_ok || y_it_ok) { const bool x_inside_box = (x_it_row >= pa_start_row) && (x_it_row <= pa_end_row) && (x_it_col >= pa_start_col) && (x_it_col <= pa_end_col); const bool y_inside_box = (y_it_row >= pa_start_row) && (y_it_row <= pa_end_row) && (y_it_col >= pa_start_col) && (y_it_col <= pa_end_col); const eT x_val = x_inside_box ? eT(0) : ( x_it_ok ? (*x_it) : eT(0) ); const eT y_val = y_inside_box ? ( y_it_ok ? b.at(b_row,b_col) : eT(0) ) : eT(0); if( (x_it_row == y_it_row) && (x_it_col == y_it_col) ) { if( (x_val != eT(0)) || (y_val != eT(0)) ) { access::rw(out.values[cur_val]) = (x_val != eT(0)) ? x_val : y_val; access::rw(out.row_indices[cur_val]) = x_it_row; ++access::rw(out.col_ptrs[x_it_col + 1]); ++cur_val; } if(x_it_ok) { ++x_it; if(x_it == x_end) { x_it_ok = false; } } if(x_it_ok) { x_it_row = x_it.row(); x_it_col = x_it.col(); } else { x_it_row++; if(x_it_row >= pa_n_rows) { x_it_row = 0; x_it_col++; } } if(y_it_ok) { b_row++; if(b_row >= b.n_rows) { b_row = 0; b_col++; } if( (b_row > b.n_rows) || (b_col > b.n_cols) ) { y_it_ok = false; } } if(y_it_ok) { y_it_row = b_row + pa_start_row; y_it_col = b_col + pa_start_col; } else { y_it_row++; if(y_it_row >= pa_n_rows) { y_it_row = 0; y_it_col++; } } } else { if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end { if(x_val != eT(0)) { access::rw(out.values[cur_val]) = x_val; access::rw(out.row_indices[cur_val]) = x_it_row; ++access::rw(out.col_ptrs[x_it_col + 1]); ++cur_val; } if(x_it_ok) { ++x_it; if(x_it == x_end) { x_it_ok = false; } } if(x_it_ok) { x_it_row = x_it.row(); x_it_col = x_it.col(); } else { x_it_row++; if(x_it_row >= pa_n_rows) { x_it_row = 0; x_it_col++; } } } else { if(y_val != eT(0)) { access::rw(out.values[cur_val]) = y_val; access::rw(out.row_indices[cur_val]) = y_it_row; ++access::rw(out.col_ptrs[y_it_col + 1]); ++cur_val; } if(y_it_ok) { b_row++; if(b_row >= b.n_rows) { b_row = 0; b_col++; } if( (b_row > b.n_rows) || (b_col > b.n_cols) ) { y_it_ok = false; } } if(y_it_ok) { y_it_row = b_row + pa_start_row; y_it_col = b_col + pa_start_col; } else { y_it_row++; if(y_it_row >= pa_n_rows) { y_it_row = 0; y_it_col++; } } } } } const uword out_n_cols = out.n_cols; uword* col_ptrs = access::rwp(out.col_ptrs); // Fix column pointers to be cumulative. for(uword c = 1; c <= out_n_cols; ++c) { col_ptrs[c] += col_ptrs[c - 1]; } access::rw((*this).m).steal_mem(out); access::rw(n_nonzero) = box_count; return *this; }
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 void subview_elem2<eT,T1,T2>::inplace_op(const Base<eT,expr>& x) { arma_extra_debug_sigprint(); Mat<eT>& m_local = const_cast< Mat<eT>& >(m); const uword m_n_rows = m_local.n_rows; const uword m_n_cols = m_local.n_cols; const unwrap_check<expr> tmp(x.get_ref(), m_local); const Mat<eT>& X = tmp.M; if( (all_rows == false) && (all_cols == false) ) { const unwrap_check_mixed<T1> tmp1(base_ri.get_ref(), m_local); const unwrap_check_mixed<T2> tmp2(base_ci.get_ref(), m_local); const umat& ri = tmp1.M; const umat& ci = tmp2.M; arma_debug_check ( ( ri.is_vec() == false ) || ( ci.is_vec() == false ), "Mat::elem(): given object is not a vector" ); const uword* ri_mem = ri.memptr(); const uword ri_n_elem = ri.n_elem; const uword* ci_mem = ci.memptr(); const uword ci_n_elem = ci.n_elem; arma_debug_assert_same_size( ri_n_elem, ci_n_elem, X.n_rows, X.n_cols, "Mat::elem()" ); for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword col = ci_mem[ci_count]; arma_debug_check( (col > m_n_cols), "Mat::elem(): index out of bounds" ); for(uword ri_count=0; ri_count < ri_n_elem; ++ri_count) { const uword row = ri_mem[ri_count]; arma_debug_check( (row > m_n_rows), "Mat::elem(): index out of bounds" ); if(is_same_type<op_type, op_subview_elem_equ >::value == true) { m_local.at(row,col) = X.at(ri_count, ci_count); } else if(is_same_type<op_type, op_subview_elem_inplace_plus >::value == true) { m_local.at(row,col) += X.at(ri_count, ci_count); } else if(is_same_type<op_type, op_subview_elem_inplace_minus>::value == true) { m_local.at(row,col) -= X.at(ri_count, ci_count); } else if(is_same_type<op_type, op_subview_elem_inplace_schur>::value == true) { m_local.at(row,col) *= X.at(ri_count, ci_count); } else if(is_same_type<op_type, op_subview_elem_inplace_div >::value == true) { m_local.at(row,col) /= X.at(ri_count, ci_count); } } } } else if( (all_rows == true) && (all_cols == false) ) { const unwrap_check_mixed<T2> tmp2(base_ci.get_ref(), m_local); const umat& ci = tmp2.M; arma_debug_check ( ( ci.is_vec() == false ), "Mat::elem(): given object is not a vector" ); const uword* ci_mem = ci.memptr(); const uword ci_n_elem = ci.n_elem; arma_debug_assert_same_size( m_n_rows, ci_n_elem, X.n_rows, X.n_cols, "Mat::elem()" ); for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword col = ci_mem[ci_count]; arma_debug_check( (col > m_n_cols), "Mat::elem(): index out of bounds" ); eT* m_colptr = m_local.colptr(col); const eT* X_colptr = X.colptr(ci_count); if(is_same_type<op_type, op_subview_elem_equ >::value == true) { arrayops::copy (m_colptr, X_colptr, m_n_rows); } else if(is_same_type<op_type, op_subview_elem_inplace_plus >::value == true) { arrayops::inplace_plus (m_colptr, X_colptr, m_n_rows); } else if(is_same_type<op_type, op_subview_elem_inplace_minus>::value == true) { arrayops::inplace_minus(m_colptr, X_colptr, m_n_rows); } else if(is_same_type<op_type, op_subview_elem_inplace_schur>::value == true) { arrayops::inplace_mul (m_colptr, X_colptr, m_n_rows); } else if(is_same_type<op_type, op_subview_elem_inplace_div >::value == true) { arrayops::inplace_div (m_colptr, X_colptr, m_n_rows); } } } else if( (all_rows == false) && (all_cols == true) ) { const unwrap_check_mixed<T1> tmp1(base_ri.get_ref(), m_local); const umat& ri = tmp1.M; arma_debug_check ( ( ri.is_vec() == false ), "Mat::elem(): given object is not a vector" ); const uword* ri_mem = ri.memptr(); const uword ri_n_elem = ri.n_elem; arma_debug_assert_same_size( ri_n_elem, m_n_cols, X.n_rows, X.n_cols, "Mat::elem()" ); for(uword col=0; col < m_n_cols; ++col) { for(uword ri_count=0; ri_count < ri_n_elem; ++ri_count) { const uword row = ri_mem[ri_count]; arma_debug_check( (row > m_n_rows), "Mat::elem(): index out of bounds" ); if(is_same_type<op_type, op_subview_elem_equ >::value == true) { m_local.at(row,col) = X.at(ri_count, col); } else if(is_same_type<op_type, op_subview_elem_inplace_plus >::value == true) { m_local.at(row,col) += X.at(ri_count, col); } else if(is_same_type<op_type, op_subview_elem_inplace_minus>::value == true) { m_local.at(row,col) -= X.at(ri_count, col); } else if(is_same_type<op_type, op_subview_elem_inplace_schur>::value == true) { m_local.at(row,col) *= X.at(ri_count, col); } else if(is_same_type<op_type, op_subview_elem_inplace_div >::value == true) { m_local.at(row,col) /= X.at(ri_count, col); } } } } }
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_not_cx<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(); 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 = tmp1*trans(tmp1); } else { tmp2 = trans(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]; if(val < min_val_mem[i]) { min_val_mem[i] = val; } if(val > max_val_mem[i]) { max_val_mem[i] = val; } const eT r_mean_val = r_mean_mem[i]; const eT tmp = val - r_mean_val; r_var_mem[i] = N_minus_1/N * r_var_mem[i] + (tmp*tmp)/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); 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(); for(uword i=0; i<n_elem; ++i) { const eT val = sample_mem[i]; r_mean_mem[i] = val; min_val_mem[i] = val; max_val_mem[i] = val; } } x.counter++; }
inline typename enable_if2 < (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value), SpMat<typename T1::elem_type> >::result operator% ( const Base<typename T1::elem_type, T1>& x, const SpBase<typename T2::elem_type, T2>& y ) { arma_extra_debug_sigprint(); const Proxy<T1> pa(x.get_ref()); const SpProxy<T2> pb(y.get_ref()); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise multiplication"); SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()); if(Proxy<T1>::prefer_at_accessor == false) { // use direct operator[] access // count new size uword new_n_nonzero = 0; typename SpProxy<T2>::const_iterator_type it = pb.begin(); while(it.pos() < pb.get_n_nonzero()) { if(((*it) * pa[(it.col() * pa.get_n_rows()) + it.row()]) != 0) { ++new_n_nonzero; } ++it; } // Resize memory accordingly. result.mem_resize(new_n_nonzero); uword cur_val = 0; typename SpProxy<T2>::const_iterator_type it2 = pb.begin(); while(it2.pos() < pb.get_n_nonzero()) { const typename T1::elem_type val = (*it2) * pa[(it2.col() * pa.get_n_rows()) + it2.row()]; if(val != 0) { access::rw(result.values[cur_val]) = val; access::rw(result.row_indices[cur_val]) = it2.row(); ++access::rw(result.col_ptrs[it2.col() + 1]); ++cur_val; } ++it2; } } else { // use at() access // count new size uword new_n_nonzero = 0; typename SpProxy<T2>::const_iterator_type it = pb.begin(); while(it.pos() < pb.get_n_nonzero()) { if(((*it) * pa.at(it.row(), it.col())) != 0) { ++new_n_nonzero; } ++it; } // Resize memory accordingly. result.mem_resize(new_n_nonzero); uword cur_val = 0; typename SpProxy<T2>::const_iterator_type it2 = pb.begin(); while(it2.pos() < pb.get_n_nonzero()) { const typename T1::elem_type val = (*it2) * pa.at(it2.row(), it2.col()); if(val != 0) { access::rw(result.values[cur_val]) = val; access::rw(result.row_indices[cur_val]) = it2.row(); ++access::rw(result.col_ptrs[it2.col() + 1]); ++cur_val; } ++it2; } } // Fix column pointers. for(uword c = 1; c <= result.n_cols; ++c) { access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; } return result; }
arma_hot inline void spglue_minus::apply_noalias(SpMat<eT>& result, const SpProxy<T1>& pa, const SpProxy<T2>& pb) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "subtraction"); result.set_size(pa.get_n_rows(), pa.get_n_cols()); // Resize memory to correct size. result.mem_resize(n_unique(pa, pb, op_n_unique_sub())); // Now iterate across both matrices. typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); typename SpProxy<T2>::const_iterator_type y_it = pb.begin(); uword cur_val = 0; while((x_it.pos() < pa.get_n_nonzero()) || (y_it.pos() < pb.get_n_nonzero())) { if(x_it == y_it) { const typename T1::elem_type val = (*x_it) - (*y_it); if (val != 0) { access::rw(result.values[cur_val]) = val; access::rw(result.row_indices[cur_val]) = x_it.row(); ++access::rw(result.col_ptrs[x_it.col() + 1]); ++cur_val; } ++x_it; ++y_it; } else { if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.row() < y_it.row()))) // if y is closer to the end { access::rw(result.values[cur_val]) = (*x_it); access::rw(result.row_indices[cur_val]) = x_it.row(); ++access::rw(result.col_ptrs[x_it.col() + 1]); ++cur_val; ++x_it; } else { access::rw(result.values[cur_val]) = -(*y_it); access::rw(result.row_indices[cur_val]) = y_it.row(); ++access::rw(result.col_ptrs[y_it.col() + 1]); ++cur_val; ++y_it; } } } // Fix column pointers to be cumulative. for(uword c = 1; c <= result.n_cols; ++c) { access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; } }
arma_hot inline void spglue_plus::apply_noalias(SpMat<eT>& out, const SpProxy<T1>& pa, const SpProxy<T2>& pb) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "addition"); if( (pa.get_n_nonzero() != 0) && (pb.get_n_nonzero() != 0) ) { out.set_size(pa.get_n_rows(), pa.get_n_cols()); // Resize memory to correct size. out.mem_resize(n_unique(pa, pb, op_n_unique_add())); // Now iterate across both matrices. typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); typename SpProxy<T2>::const_iterator_type y_it = pb.begin(); typename SpProxy<T1>::const_iterator_type x_end = pa.end(); typename SpProxy<T2>::const_iterator_type y_end = pb.end(); uword cur_val = 0; while( (x_it != x_end) || (y_it != y_end) ) { if(x_it == y_it) { const eT val = (*x_it) + (*y_it); if (val != eT(0)) { access::rw(out.values[cur_val]) = val; access::rw(out.row_indices[cur_val]) = x_it.row(); ++access::rw(out.col_ptrs[x_it.col() + 1]); ++cur_val; } ++x_it; ++y_it; } else { const uword x_it_row = x_it.row(); const uword x_it_col = x_it.col(); const uword y_it_row = y_it.row(); const uword y_it_col = y_it.col(); if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end { access::rw(out.values[cur_val]) = (*x_it); access::rw(out.row_indices[cur_val]) = x_it_row; ++access::rw(out.col_ptrs[x_it_col + 1]); ++cur_val; ++x_it; } else { access::rw(out.values[cur_val]) = (*y_it); access::rw(out.row_indices[cur_val]) = y_it_row; ++access::rw(out.col_ptrs[y_it_col + 1]); ++cur_val; ++y_it; } } } const uword out_n_cols = out.n_cols; uword* col_ptrs = access::rwp(out.col_ptrs); // Fix column pointers to be cumulative. for(uword c = 1; c <= out_n_cols; ++c) { col_ptrs[c] += col_ptrs[c - 1]; } } else { if(pa.get_n_nonzero() == 0) { out = pb.Q; return; } if(pb.get_n_nonzero() == 0) { out = pa.Q; return; } } }
inline typename enable_if2 < (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value), SpMat<typename T1::elem_type> >::result operator/ ( const SpBase<typename T1::elem_type, T1>& x, const Base<typename T2::elem_type, T2>& y ) { arma_extra_debug_sigprint(); const SpProxy<T1> pa(x.get_ref()); const Proxy<T2> pb(y.get_ref()); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise division"); SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()); // The compiler should be smart enough to optimize out the inner if/else statement entirely typename SpProxy<T1>::const_iterator_type it = pa.begin(); uword new_n_nonzero; while(it.pos() < pa.get_n_nonzero()) { if(Proxy<T2>::prefer_at_accessor == false) { const typename T1::elem_type val = (*it) / pb[(it.col() * pb.get_n_rows()) + it.row()]; if(val != 0) { ++new_n_nonzero; } } else { const typename T1::elem_type val = (*it) / pb.at(it.row(), it.col()); if(val != 0) { ++new_n_nonzero; } } ++it; } result.mem_resize(new_n_nonzero); typename SpProxy<T1>::const_iterator_type it2 = pa.begin(); uword cur_pos = 0; while(it2.pos() < pa.get_n_nonzero()) { if(Proxy<T2>::prefer_at_accessor == false) { const typename T1::elem_type val = (*it2) / pb[(it2.col() * pb.get_n_rows()) + it2.row()]; if(val != 0) { access::rw(result.values[cur_pos]) = val; access::rw(result.row_indices[cur_pos]) = it2.row(); ++access::rw(result.col_ptrs[it2.col() + 1]); ++cur_pos; } } else { const typename T1::elem_type val = (*it2) / pb.at(it2.row(), it2.col()); if(val != 0) { access::rw(result.values[cur_pos]) = val; access::rw(result.row_indices[cur_pos]) = it2.row(); ++access::rw(result.col_ptrs[it2.col() + 1]); ++cur_pos; } } ++it2; } // Fix column pointers for(uword col = 1; col <= result.n_cols; ++col) { access::rw(result.col_ptrs[col]) += result.col_ptrs[col - 1]; } return result; }