From eda5bc26f44ee9a6f83dcf8c91f17296d7fc509d Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Mon, 12 Feb 2024 14:52:43 +0100 Subject: Move into version control --- .../include/armadillo_bits/spop_min_meat.hpp | 722 +++++++++++++++++++++ 1 file changed, 722 insertions(+) create mode 100644 src/armadillo/include/armadillo_bits/spop_min_meat.hpp (limited to 'src/armadillo/include/armadillo_bits/spop_min_meat.hpp') diff --git a/src/armadillo/include/armadillo_bits/spop_min_meat.hpp b/src/armadillo/include/armadillo_bits/spop_min_meat.hpp new file mode 100644 index 0000000..b47c33c --- /dev/null +++ b/src/armadillo/include/armadillo_bits/spop_min_meat.hpp @@ -0,0 +1,722 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au) +// Copyright 2008-2016 National ICT Australia (NICTA) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------ + + +//! \addtogroup spop_min +//! @{ + + + +template +inline +void +spop_min::apply(SpMat& out, const SpOp& in) + { + arma_extra_debug_sigprint(); + + const uword dim = in.aux_uword_a; + arma_debug_check( (dim > 1), "min(): parameter 'dim' must be 0 or 1" ); + + const SpProxy p(in.m); + + const uword p_n_rows = p.get_n_rows(); + const uword p_n_cols = p.get_n_cols(); + + if( (p_n_rows == 0) || (p_n_cols == 0) || (p.get_n_nonzero() == 0) ) + { + if(dim == 0) { out.zeros((p_n_rows > 0) ? 1 : 0, p_n_cols); } + if(dim == 1) { out.zeros(p_n_rows, (p_n_cols > 0) ? 1 : 0); } + + return; + } + + spop_min::apply_proxy(out, p, dim); + } + + + +template +inline +void +spop_min::apply_proxy + ( + SpMat& out, + const SpProxy& p, + const uword dim, + const typename arma_not_cx::result* junk + ) + { + arma_extra_debug_sigprint(); + arma_ignore(junk); + + typedef typename T1::elem_type eT; + + typename SpProxy::const_iterator_type it = p.begin(); + typename SpProxy::const_iterator_type it_end = p.end(); + + const uword p_n_cols = p.get_n_cols(); + const uword p_n_rows = p.get_n_rows(); + + if(dim == 0) // find the minimum in each column + { + Row value(p_n_cols, arma_zeros_indicator()); + urowvec count(p_n_cols, arma_zeros_indicator()); + + while(it != it_end) + { + const uword col = it.col(); + + value[col] = (count[col] == 0) ? (*it) : (std::min)(value[col], (*it)); + count[col]++; + ++it; + } + + for(uword col=0; col value(p_n_rows, arma_zeros_indicator()); + ucolvec count(p_n_rows, arma_zeros_indicator()); + + while(it != it_end) + { + const uword row = it.row(); + + value[row] = (count[row] == 0) ? (*it) : (std::min)(value[row], (*it)); + count[row]++; + ++it; + } + + for(uword row=0; row +inline +typename T1::elem_type +spop_min::vector_min + ( + const T1& x, + const typename arma_not_cx::result* junk + ) + { + arma_extra_debug_sigprint(); + arma_ignore(junk); + + typedef typename T1::elem_type eT; + + const SpProxy p(x); + + if(p.get_n_elem() == 0) + { + arma_debug_check(true, "min(): object has no elements"); + + return Datum::nan; + } + + if(p.get_n_nonzero() == 0) { return eT(0); } + + if(SpProxy::use_iterator == false) + { + // direct access of values + if(p.get_n_nonzero() == p.get_n_elem()) + { + return op_min::direct_min(p.get_values(), p.get_n_nonzero()); + } + else + { + return (std::min)(eT(0), op_min::direct_min(p.get_values(), p.get_n_nonzero())); + } + } + else + { + // use iterator + typename SpProxy::const_iterator_type it = p.begin(); + typename SpProxy::const_iterator_type it_end = p.end(); + + eT result = (*it); + ++it; + + while(it != it_end) + { + if((*it) < result) { result = (*it); } + + ++it; + } + + if(p.get_n_nonzero() == p.get_n_elem()) + { + return result; + } + else + { + return (std::min)(eT(0), result); + } + } + } + + + +template +inline +typename arma_not_cx::result +spop_min::min(const SpBase& X) + { + arma_extra_debug_sigprint(); + + typedef typename T1::elem_type eT; + + const SpProxy P(X.get_ref()); + + const uword n_elem = P.get_n_elem(); + const uword n_nonzero = P.get_n_nonzero(); + + if(n_elem == 0) + { + arma_debug_check(true, "min(): object has no elements"); + + return Datum::nan; + } + + eT min_val = priv::most_pos(); + + if(SpProxy::use_iterator) + { + // We have to iterate over the elements. + typedef typename SpProxy::const_iterator_type it_type; + + it_type it = P.begin(); + it_type it_end = P.end(); + + while(it != it_end) + { + if((*it) < min_val) { min_val = *it; } + + ++it; + } + } + else + { + // We can do direct access of the values, row_indices, and col_ptrs. + // We don't need the location of the min value, so we can just call out to + // other functions... + min_val = op_min::direct_min(P.get_values(), n_nonzero); + } + + if(n_elem == n_nonzero) + { + return min_val; + } + else + { + return (std::min)(eT(0), min_val); + } + } + + + +template +inline +typename arma_not_cx::result +spop_min::min_with_index(const SpProxy& P, uword& index_of_min_val) + { + arma_extra_debug_sigprint(); + + typedef typename T1::elem_type eT; + + const uword n_elem = P.get_n_elem(); + const uword n_nonzero = P.get_n_nonzero(); + const uword n_rows = P.get_n_rows(); + + if(n_elem == 0) + { + arma_debug_check(true, "min(): object has no elements"); + + index_of_min_val = uword(0); + + return Datum::nan; + } + + eT min_val = priv::most_pos(); + + if(SpProxy::use_iterator) + { + // We have to iterate over the elements. + typedef typename SpProxy::const_iterator_type it_type; + + it_type it = P.begin(); + it_type it_end = P.end(); + + while(it != it_end) + { + if((*it) < min_val) + { + min_val = *it; + index_of_min_val = it.row() + it.col() * n_rows; + } + + ++it; + } + } + else + { + // We can do direct access. + min_val = op_min::direct_min(P.get_values(), n_nonzero, index_of_min_val); + + // Convert to actual position in matrix. + const uword row = P.get_row_indices()[index_of_min_val]; + uword col = 0; + while(P.get_col_ptrs()[++col] < index_of_min_val + 1) { } + index_of_min_val = (col - 1) * n_rows + row; + } + + + if(n_elem != n_nonzero) + { + min_val = (std::min)(eT(0), min_val); + + // If the min_val is a nonzero element, we need its actual position in the matrix. + if(min_val == eT(0)) + { + // Find first zero element. + uword last_row = 0; + uword last_col = 0; + + typedef typename SpProxy::const_iterator_type it_type; + + it_type it = P.begin(); + it_type it_end = P.end(); + + while(it != it_end) + { + // Have we moved more than one position from the last place? + if((it.col() == last_col) && (it.row() - last_row > 1)) + { + index_of_min_val = it.col() * n_rows + last_row + 1; + break; + } + else if((it.col() >= last_col + 1) && (last_row < n_rows - 1)) + { + index_of_min_val = last_col * n_rows + last_row + 1; + break; + } + else if((it.col() == last_col + 1) && (it.row() > 0)) + { + index_of_min_val = it.col() * n_rows; + break; + } + else if(it.col() > last_col + 1) + { + index_of_min_val = (last_col + 1) * n_rows; + break; + } + + last_row = it.row(); + last_col = it.col(); + ++it; + } + } + } + + return min_val; + } + + + +template +inline +void +spop_min::apply_proxy + ( + SpMat& out, + const SpProxy& p, + const uword dim, + const typename arma_cx_only::result* junk + ) + { + arma_extra_debug_sigprint(); + arma_ignore(junk); + + typedef typename T1::elem_type eT; + typedef typename get_pod_type::result T; + + typename SpProxy::const_iterator_type it = p.begin(); + typename SpProxy::const_iterator_type it_end = p.end(); + + const uword p_n_cols = p.get_n_cols(); + const uword p_n_rows = p.get_n_rows(); + + if(dim == 0) // find the minimum in each column + { + Row rawval(p_n_cols, arma_zeros_indicator()); + Row< T> absval(p_n_cols, arma_zeros_indicator()); + urowvec count(p_n_cols, arma_zeros_indicator()); + + while(it != it_end) + { + const uword col = it.col(); + + const eT& v = (*it); + const T a = std::abs(v); + + if(count[col] == 0) + { + absval[col] = a; + rawval[col] = v; + } + else + { + if(a < absval[col]) + { + absval[col] = a; + rawval[col] = v; + } + } + + count[col]++; + ++it; + } + + for(uword col=0; col < p_n_cols; ++col) + { + if(count[col] < p_n_rows) + { + if(T(0) < absval[col]) { rawval[col] = eT(0); } + } + } + + out = rawval; + } + else + if(dim == 1) // find the minimum in each row + { + Col rawval(p_n_rows, arma_zeros_indicator()); + Col< T> absval(p_n_rows, arma_zeros_indicator()); + ucolvec count(p_n_rows, arma_zeros_indicator()); + + while(it != it_end) + { + const uword row = it.row(); + + const eT& v = (*it); + const T a = std::abs(v); + + if(count[row] == 0) + { + absval[row] = a; + rawval[row] = v; + } + else + { + if(a < absval[row]) + { + absval[row] = a; + rawval[row] = v; + } + } + + count[row]++; + ++it; + } + + for(uword row=0; row < p_n_rows; ++row) + { + if(count[row] < p_n_cols) + { + if(T(0) < absval[row]) { rawval[row] = eT(0); } + } + } + + out = rawval; + } + } + + + +template +inline +typename T1::elem_type +spop_min::vector_min + ( + const T1& x, + const typename arma_cx_only::result* junk + ) + { + arma_extra_debug_sigprint(); + arma_ignore(junk); + + typedef typename T1::elem_type eT; + typedef typename get_pod_type::result T; + + const SpProxy p(x); + + if(p.get_n_elem() == 0) + { + arma_debug_check(true, "min(): object has no elements"); + + return Datum::nan; + } + + if(p.get_n_nonzero() == 0) { return eT(0); } + + if(SpProxy::use_iterator == false) + { + // direct access of values + if(p.get_n_nonzero() == p.get_n_elem()) + { + return op_min::direct_min(p.get_values(), p.get_n_nonzero()); + } + else + { + const eT val1 = eT(0); + const eT val2 = op_min::direct_min(p.get_values(), p.get_n_nonzero()); + + return ( std::abs(val1) < std::abs(val2) ) ? val1 : val2; + } + } + else + { + // use iterator + typename SpProxy::const_iterator_type it = p.begin(); + typename SpProxy::const_iterator_type it_end = p.end(); + + eT best_val_orig = *it; + T best_val_abs = std::abs(best_val_orig); + + ++it; + + while(it != it_end) + { + eT val_orig = *it; + T val_abs = std::abs(val_orig); + + if(val_abs < best_val_abs) + { + best_val_abs = val_abs; + best_val_orig = val_orig; + } + + ++it; + } + + if(p.get_n_nonzero() == p.get_n_elem()) + { + return best_val_orig; + } + else + { + const eT val1 = eT(0); + + return ( std::abs(val1) < best_val_abs ) ? val1 : best_val_orig; + } + } + } + + + +template +inline +typename arma_cx_only::result +spop_min::min(const SpBase& X) + { + arma_extra_debug_sigprint(); + + typedef typename T1::elem_type eT; + typedef typename get_pod_type::result T; + + const SpProxy P(X.get_ref()); + + const uword n_elem = P.get_n_elem(); + const uword n_nonzero = P.get_n_nonzero(); + + if(n_elem == 0) + { + arma_debug_check(true, "min(): object has no elements"); + + return Datum::nan; + } + + T min_val = priv::most_pos(); + eT ret_val; + + if(SpProxy::use_iterator) + { + // We have to iterate over the elements. + typedef typename SpProxy::const_iterator_type it_type; + + it_type it = P.begin(); + it_type it_end = P.end(); + + while(it != it_end) + { + const T tmp_val = std::abs(*it); + + if(tmp_val < min_val) + { + min_val = tmp_val; + ret_val = *it; + } + + ++it; + } + } + else + { + // We can do direct access of the values, row_indices, and col_ptrs. + // We don't need the location of the min value, so we can just call out to + // other functions... + ret_val = op_min::direct_min(P.get_values(), n_nonzero); + min_val = std::abs(ret_val); + } + + if(n_elem == n_nonzero) + { + return ret_val; + } + else + { + return (T(0) < min_val) ? eT(0) : ret_val; + } + } + + + +template +inline +typename arma_cx_only::result +spop_min::min_with_index(const SpProxy& P, uword& index_of_min_val) + { + arma_extra_debug_sigprint(); + + typedef typename T1::elem_type eT; + typedef typename get_pod_type::result T; + + const uword n_elem = P.get_n_elem(); + const uword n_nonzero = P.get_n_nonzero(); + const uword n_rows = P.get_n_rows(); + + if(n_elem == 0) + { + arma_debug_check(true, "min(): object has no elements"); + + index_of_min_val = uword(0); + + return Datum::nan; + } + + T min_val = priv::most_pos(); + + if(SpProxy::use_iterator) + { + // We have to iterate over the elements. + typedef typename SpProxy::const_iterator_type it_type; + + it_type it = P.begin(); + it_type it_end = P.end(); + + while(it != it_end) + { + const T tmp_val = std::abs(*it); + + if(tmp_val < min_val) + { + min_val = tmp_val; + index_of_min_val = it.row() + it.col() * n_rows; + } + + ++it; + } + } + else + { + // We can do direct access. + min_val = std::abs(op_min::direct_min(P.get_values(), n_nonzero, index_of_min_val)); + + // Convert to actual position in matrix. + const uword row = P.get_row_indices()[index_of_min_val]; + uword col = 0; + while(P.get_col_ptrs()[++col] < index_of_min_val + 1) { } + index_of_min_val = (col - 1) * n_rows + row; + } + + + if(n_elem != n_nonzero) + { + min_val = (std::min)(T(0), min_val); + + // If the min_val is a nonzero element, we need its actual position in the matrix. + if(min_val == T(0)) + { + // Find first zero element. + uword last_row = 0; + uword last_col = 0; + + typedef typename SpProxy::const_iterator_type it_type; + + it_type it = P.begin(); + it_type it_end = P.end(); + + while(it != it_end) + { + // Have we moved more than one position from the last place? + if((it.col() == last_col) && (it.row() - last_row > 1)) + { + index_of_min_val = it.col() * n_rows + last_row + 1; + break; + } + else if((it.col() >= last_col + 1) && (last_row < n_rows - 1)) + { + index_of_min_val = last_col * n_rows + last_row + 1; + break; + } + else if((it.col() == last_col + 1) && (it.row() > 0)) + { + index_of_min_val = it.col() * n_rows; + break; + } + else if(it.col() > last_col + 1) + { + index_of_min_val = (last_col + 1) * n_rows; + break; + } + + last_row = it.row(); + last_col = it.col(); + ++it; + } + } + } + + return P[index_of_min_val]; + } + + + +//! @} -- cgit v1.2.1