Chris@49: // Copyright (C) 2012 Ryan Curtin Chris@49: // Copyright (C) 2012 Conrad Sanderson Chris@49: // Chris@49: // This Source Code Form is subject to the terms of the Mozilla Public Chris@49: // License, v. 2.0. If a copy of the MPL was not distributed with this Chris@49: // file, You can obtain one at http://mozilla.org/MPL/2.0/. Chris@49: Chris@49: Chris@49: //! \addtogroup spop_min Chris@49: //! @{ Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: void Chris@49: spop_min::apply(SpMat& out, const SpOp& in) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: Chris@49: const uword dim = in.aux_uword_a; Chris@49: arma_debug_check((dim > 1), "min(): incorrect usage. dim must be 0 or 1"); Chris@49: Chris@49: const SpProxy p(in.m); Chris@49: Chris@49: if(p.is_alias(out) == false) Chris@49: { Chris@49: spop_min::apply_noalias(out, p, dim); Chris@49: } Chris@49: else Chris@49: { Chris@49: SpMat tmp; Chris@49: Chris@49: spop_min::apply_noalias(tmp, p, dim); Chris@49: Chris@49: out.steal_mem(tmp); Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: void Chris@49: spop_min::apply_noalias Chris@49: ( Chris@49: SpMat& result, Chris@49: const SpProxy& p, Chris@49: const uword dim, Chris@49: const typename arma_not_cx::result* junk Chris@49: ) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: Chris@49: if(dim == 0) Chris@49: { Chris@49: // minimum in each column Chris@49: result.set_size(1, p.get_n_cols()); Chris@49: Chris@49: if(p.get_n_nonzero() == 0) Chris@49: { Chris@49: return; Chris@49: } Chris@49: Chris@49: typename SpProxy::const_iterator_type it = p.begin(); Chris@49: Chris@49: uword cur_col = it.col(); Chris@49: uword elem_in_col = 1; Chris@49: eT cur_min = (*it); Chris@49: ++it; Chris@49: Chris@49: while(it != p.end()) Chris@49: { Chris@49: if(it.col() != cur_col) Chris@49: { Chris@49: // was the column full? Chris@49: if(elem_in_col == p.get_n_rows()) Chris@49: { Chris@49: result.at(0, cur_col) = cur_min; Chris@49: } Chris@49: else Chris@49: { Chris@49: result.at(0, cur_col) = std::min(eT(0), cur_min); Chris@49: } Chris@49: Chris@49: cur_col = it.col(); Chris@49: elem_in_col = 0; Chris@49: cur_min = (*it); Chris@49: } Chris@49: else Chris@49: { Chris@49: cur_min = std::min(cur_min, *it); Chris@49: } Chris@49: Chris@49: ++elem_in_col; Chris@49: ++it; Chris@49: } Chris@49: Chris@49: if(elem_in_col == p.get_n_rows()) Chris@49: { Chris@49: result.at(0, cur_col) = cur_min; Chris@49: } Chris@49: else Chris@49: { Chris@49: result.at(0, cur_col) = std::min(eT(0), cur_min); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: // minimum in each row Chris@49: result.set_size(p.get_n_rows(), 1); Chris@49: Chris@49: if(p.get_n_nonzero() == 0) Chris@49: { Chris@49: return; Chris@49: } Chris@49: Chris@49: typename SpProxy::const_row_iterator_type it = p.begin_row(); Chris@49: Chris@49: uword cur_row = it.row(); Chris@49: uword elem_in_row = 1; Chris@49: eT cur_min = (*it); Chris@49: ++it; Chris@49: Chris@49: while(it.pos() < p.get_n_nonzero()) Chris@49: { Chris@49: if(it.row() != cur_row) Chris@49: { Chris@49: // was the row full? Chris@49: if(elem_in_row == p.get_n_cols()) Chris@49: { Chris@49: result.at(cur_row, 0) = cur_min; Chris@49: } Chris@49: else Chris@49: { Chris@49: result.at(cur_row, 0) = std::min(eT(0), cur_min); Chris@49: } Chris@49: Chris@49: cur_row = it.row(); Chris@49: elem_in_row = 0; Chris@49: cur_min = (*it); Chris@49: } Chris@49: else Chris@49: { Chris@49: cur_min = std::min(cur_min, *it); Chris@49: } Chris@49: Chris@49: ++elem_in_row; Chris@49: ++it; Chris@49: } Chris@49: Chris@49: if(elem_in_row == p.get_n_cols()) Chris@49: { Chris@49: result.at(cur_row, 0) = cur_min; Chris@49: } Chris@49: else Chris@49: { Chris@49: result.at(cur_row, 0) = std::min(eT(0), cur_min); Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: void Chris@49: spop_min::apply_noalias Chris@49: ( Chris@49: SpMat& result, Chris@49: const SpProxy& p, Chris@49: const uword dim, Chris@49: const typename arma_cx_only::result* junk Chris@49: ) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: if(dim == 0) Chris@49: { Chris@49: // minimum in each column Chris@49: result.set_size(1, p.get_n_cols()); Chris@49: Chris@49: if(p.get_n_nonzero() == 0) Chris@49: { Chris@49: return; Chris@49: } Chris@49: Chris@49: typename SpProxy::const_iterator_type it = p.begin(); Chris@49: Chris@49: uword cur_col = it.col(); Chris@49: uword elem_in_col = 1; Chris@49: Chris@49: eT cur_min_orig = *it; Chris@49: T cur_min_abs = std::abs(cur_min_orig); Chris@49: Chris@49: ++it; Chris@49: Chris@49: while(it != p.end()) Chris@49: { Chris@49: if(it.col() != cur_col) Chris@49: { Chris@49: // was the column full? Chris@49: if(elem_in_col == p.get_n_rows()) Chris@49: { Chris@49: result.at(0, cur_col) = cur_min_orig; Chris@49: } Chris@49: else Chris@49: { Chris@49: eT val1 = eT(0); Chris@49: Chris@49: result.at(0, cur_col) = ( std::abs(val1) < cur_min_abs ) ? val1 : cur_min_orig; Chris@49: } Chris@49: Chris@49: cur_col = it.col(); Chris@49: elem_in_col = 0; Chris@49: Chris@49: cur_min_orig = *it; Chris@49: cur_min_abs = std::abs(cur_min_orig); Chris@49: } Chris@49: else Chris@49: { Chris@49: eT val1_orig = *it; Chris@49: T val1_abs = std::abs(val1_orig); Chris@49: Chris@49: if( val1_abs < cur_min_abs ) Chris@49: { Chris@49: cur_min_abs = val1_abs; Chris@49: cur_min_orig = val1_orig; Chris@49: } Chris@49: } Chris@49: Chris@49: ++elem_in_col; Chris@49: ++it; Chris@49: } Chris@49: Chris@49: if(elem_in_col == p.get_n_rows()) Chris@49: { Chris@49: result.at(0, cur_col) = cur_min_orig; Chris@49: } Chris@49: else Chris@49: { Chris@49: eT val1 = eT(0); Chris@49: Chris@49: result.at(0, cur_col) = ( std::abs(val1) < cur_min_abs ) ? val1 : cur_min_orig; Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: // minimum in each row Chris@49: result.set_size(p.get_n_rows(), 1); Chris@49: Chris@49: if(p.get_n_nonzero() == 0) Chris@49: { Chris@49: return; Chris@49: } Chris@49: Chris@49: typename SpProxy::const_row_iterator_type it = p.begin_row(); Chris@49: Chris@49: uword cur_row = it.row(); Chris@49: uword elem_in_row = 1; Chris@49: Chris@49: eT cur_min_orig = *it; Chris@49: T cur_min_abs = std::abs(cur_min_orig); Chris@49: Chris@49: ++it; Chris@49: Chris@49: while(it.pos() < p.get_n_nonzero()) Chris@49: { Chris@49: if(it.row() != cur_row) Chris@49: { Chris@49: // was the row full? Chris@49: if(elem_in_row == p.get_n_cols()) Chris@49: { Chris@49: result.at(cur_row, 0) = cur_min_orig; Chris@49: } Chris@49: else Chris@49: { Chris@49: eT val1 = eT(0); Chris@49: Chris@49: result.at(cur_row, 0) = ( std::abs(val1) < cur_min_abs ) ? val1 : cur_min_orig; Chris@49: } Chris@49: Chris@49: cur_row = it.row(); Chris@49: elem_in_row = 0; Chris@49: Chris@49: cur_min_orig = *it; Chris@49: cur_min_abs = std::abs(cur_min_orig); Chris@49: } Chris@49: else Chris@49: { Chris@49: eT val1_orig = *it; Chris@49: T val1_abs = std::abs(val1_orig); Chris@49: Chris@49: if( val1_abs < cur_min_abs ) Chris@49: { Chris@49: cur_min_abs = val1_abs; Chris@49: cur_min_orig = val1_orig; Chris@49: } Chris@49: } Chris@49: Chris@49: ++elem_in_row; Chris@49: ++it; Chris@49: } Chris@49: Chris@49: if(elem_in_row == p.get_n_cols()) Chris@49: { Chris@49: result.at(cur_row, 0) = cur_min_orig; Chris@49: } Chris@49: else Chris@49: { Chris@49: eT val1 = eT(0); Chris@49: Chris@49: result.at(cur_row, 0) = ( std::abs(val1) < cur_min_abs ) ? val1 : cur_min_orig; Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: typename T1::elem_type Chris@49: spop_min::vector_min Chris@49: ( Chris@49: const T1& x, Chris@49: const typename arma_not_cx::result* junk Chris@49: ) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: Chris@49: const SpProxy p(x); Chris@49: Chris@49: if(p.get_n_nonzero() == 0) Chris@49: { Chris@49: return eT(0); Chris@49: } Chris@49: Chris@49: if(SpProxy::must_use_iterator == false) Chris@49: { Chris@49: // direct access of values Chris@49: if(p.get_n_nonzero() == p.get_n_elem()) Chris@49: { Chris@49: return op_min::direct_min(p.get_values(), p.get_n_nonzero()); Chris@49: } Chris@49: else Chris@49: { Chris@49: return std::min(eT(0), op_min::direct_min(p.get_values(), p.get_n_nonzero())); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: // use iterator Chris@49: typename SpProxy::const_iterator_type it = p.begin(); Chris@49: Chris@49: eT result = (*it); Chris@49: ++it; Chris@49: Chris@49: while(it != p.end()) Chris@49: { Chris@49: if((*it) < result) Chris@49: { Chris@49: result = (*it); Chris@49: } Chris@49: Chris@49: ++it; Chris@49: } Chris@49: Chris@49: if(p.get_n_nonzero() == p.get_n_elem()) Chris@49: { Chris@49: return result; Chris@49: } Chris@49: else Chris@49: { Chris@49: return std::min(eT(0), result); Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: typename T1::elem_type Chris@49: spop_min::vector_min Chris@49: ( Chris@49: const T1& x, Chris@49: const typename arma_cx_only::result* junk Chris@49: ) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: const SpProxy p(x); Chris@49: Chris@49: if(p.get_n_nonzero() == 0) Chris@49: { Chris@49: return eT(0); Chris@49: } Chris@49: Chris@49: if(SpProxy::must_use_iterator == false) Chris@49: { Chris@49: // direct access of values Chris@49: if(p.get_n_nonzero() == p.get_n_elem()) Chris@49: { Chris@49: return op_min::direct_min(p.get_values(), p.get_n_nonzero()); Chris@49: } Chris@49: else Chris@49: { Chris@49: const eT val1 = eT(0); Chris@49: const eT val2 = op_min::direct_min(p.get_values(), p.get_n_nonzero()); Chris@49: Chris@49: return ( std::abs(val1) < std::abs(val2) ) ? val1 : val2; Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: // use iterator Chris@49: typename SpProxy::const_iterator_type it = p.begin(); Chris@49: Chris@49: eT best_val_orig = *it; Chris@49: T best_val_abs = std::abs(best_val_orig); Chris@49: Chris@49: ++it; Chris@49: Chris@49: while(it != p.end()) Chris@49: { Chris@49: eT val_orig = *it; Chris@49: T val_abs = std::abs(val_orig); Chris@49: Chris@49: if(val_abs < best_val_abs) Chris@49: { Chris@49: best_val_abs = val_abs; Chris@49: best_val_orig = val_orig; Chris@49: } Chris@49: Chris@49: ++it; Chris@49: } Chris@49: Chris@49: if(p.get_n_nonzero() == p.get_n_elem()) Chris@49: { Chris@49: return best_val_orig; Chris@49: } Chris@49: else Chris@49: { Chris@49: const eT val1 = eT(0); Chris@49: Chris@49: return ( std::abs(val1) < best_val_abs ) ? val1 : best_val_orig; Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: //! @}