123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- // 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_max
- //! @{
- template<typename T1>
- inline
- void
- spop_max::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_max>& in)
- {
- arma_extra_debug_sigprint();
-
- const uword dim = in.aux_uword_a;
- arma_debug_check( (dim > 1), "max(): parameter 'dim' must be 0 or 1" );
-
- const SpProxy<T1> 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_max::apply_proxy(out, p, dim);
- }
- template<typename T1>
- inline
- void
- spop_max::apply_proxy
- (
- SpMat<typename T1::elem_type>& out,
- const SpProxy<T1>& p,
- const uword dim,
- const typename arma_not_cx<typename T1::elem_type>::result* junk
- )
- {
- arma_extra_debug_sigprint();
- arma_ignore(junk);
-
- typedef typename T1::elem_type eT;
-
- typename SpProxy<T1>::const_iterator_type it = p.begin();
- typename SpProxy<T1>::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 maximum in each column
- {
- Row<eT> value(p_n_cols, fill::zeros);
- urowvec count(p_n_cols, fill::zeros);
-
- while(it != it_end)
- {
- const uword col = it.col();
-
- value[col] = (count[col] == 0) ? (*it) : (std::max)(value[col], (*it));
- count[col]++;
- ++it;
- }
-
- for(uword col=0; col<p_n_cols; ++col)
- {
- if(count[col] < p_n_rows) { value[col] = (std::max)(value[col], eT(0)); }
- }
-
- out = value;
- }
- else
- if(dim == 1) // find the maximum in each row
- {
- Col<eT> value(p_n_rows, fill::zeros);
- ucolvec count(p_n_rows, fill::zeros);
-
- while(it != it_end)
- {
- const uword row = it.row();
-
- value[row] = (count[row] == 0) ? (*it) : (std::max)(value[row], (*it));
- count[row]++;
- ++it;
- }
-
- for(uword row=0; row<p_n_rows; ++row)
- {
- if(count[row] < p_n_cols) { value[row] = (std::max)(value[row], eT(0)); }
- }
-
- out = value;
- }
- }
- template<typename T1>
- inline
- typename T1::elem_type
- spop_max::vector_max
- (
- 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;
-
- const SpProxy<T1> p(x);
-
- if(p.get_n_elem() == 0)
- {
- arma_debug_check(true, "max(): object has no elements");
-
- return Datum<eT>::nan;
- }
-
- if(p.get_n_nonzero() == 0) { return eT(0); }
-
- if(SpProxy<T1>::use_iterator == false)
- {
- // direct access of values
- if(p.get_n_nonzero() == p.get_n_elem())
- {
- return op_max::direct_max(p.get_values(), p.get_n_nonzero());
- }
- else
- {
- return std::max(eT(0), op_max::direct_max(p.get_values(), p.get_n_nonzero()));
- }
- }
- else
- {
- // use iterator
- typename SpProxy<T1>::const_iterator_type it = p.begin();
- typename SpProxy<T1>::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::max(eT(0), result);
- }
- }
- }
- template<typename T1>
- inline
- typename arma_not_cx<typename T1::elem_type>::result
- spop_max::max(const SpBase<typename T1::elem_type, T1>& X)
- {
- arma_extra_debug_sigprint();
-
- typedef typename T1::elem_type eT;
-
- const SpProxy<T1> 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, "max(): object has no elements");
-
- return Datum<eT>::nan;
- }
-
- eT max_val = priv::most_neg<eT>();
-
- if(SpProxy<T1>::use_iterator)
- {
- // We have to iterate over the elements.
- typedef typename SpProxy<T1>::const_iterator_type it_type;
-
- it_type it = P.begin();
- it_type it_end = P.end();
-
- while (it != it_end)
- {
- if ((*it) > max_val) { max_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 max value, so we can just call out to
- // other functions...
- max_val = op_max::direct_max(P.get_values(), n_nonzero);
- }
-
- if(n_elem == n_nonzero)
- {
- return max_val;
- }
- else
- {
- return std::max(eT(0), max_val);
- }
- }
- template<typename T1>
- inline
- typename arma_not_cx<typename T1::elem_type>::result
- spop_max::max_with_index(const SpProxy<T1>& P, uword& index_of_max_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, "max(): object has no elements");
-
- index_of_max_val = uword(0);
-
- return Datum<eT>::nan;
- }
-
- eT max_val = priv::most_neg<eT>();
-
- if(SpProxy<T1>::use_iterator)
- {
- // We have to iterate over the elements.
- typedef typename SpProxy<T1>::const_iterator_type it_type;
-
- it_type it = P.begin();
- it_type it_end = P.end();
-
- while (it != it_end)
- {
- if ((*it) > max_val)
- {
- max_val = *it;
- index_of_max_val = it.row() + it.col() * n_rows;
- }
-
- ++it;
- }
- }
- else
- {
- // We can do direct access.
- max_val = op_max::direct_max(P.get_values(), n_nonzero, index_of_max_val);
-
- // Convert to actual position in matrix.
- const uword row = P.get_row_indices()[index_of_max_val];
- uword col = 0;
- while (P.get_col_ptrs()[++col] <= index_of_max_val) { }
- index_of_max_val = (col - 1) * n_rows + row;
- }
-
-
- if(n_elem != n_nonzero)
- {
- max_val = std::max(eT(0), max_val);
-
- // If the max_val is a nonzero element, we need its actual position in the matrix.
- if(max_val == eT(0))
- {
- // Find first zero element.
- uword last_row = 0;
- uword last_col = 0;
-
- typedef typename SpProxy<T1>::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_max_val = it.col() * n_rows + last_row + 1;
- break;
- }
- else if ((it.col() >= last_col + 1) && (last_row < n_rows - 1))
- {
- index_of_max_val = last_col * n_rows + last_row + 1;
- break;
- }
- else if ((it.col() == last_col + 1) && (it.row() > 0))
- {
- index_of_max_val = it.col() * n_rows;
- break;
- }
- else if (it.col() > last_col + 1)
- {
- index_of_max_val = (last_col + 1) * n_rows;
- break;
- }
-
- last_row = it.row();
- last_col = it.col();
- ++it;
- }
- }
- }
-
- return max_val;
- }
- template<typename T1>
- inline
- void
- spop_max::apply_proxy
- (
- SpMat<typename T1::elem_type>& out,
- const SpProxy<T1>& p,
- const uword dim,
- 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 get_pod_type<eT>::result T;
-
- typename SpProxy<T1>::const_iterator_type it = p.begin();
- typename SpProxy<T1>::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 maximum in each column
- {
- Row<eT> rawval(p_n_cols, fill::zeros);
- Row< T> absval(p_n_cols, fill::zeros);
-
- while(it != it_end)
- {
- const uword col = it.col();
-
- const eT& v = (*it);
- const T a = std::abs(v);
-
- if(a > absval[col])
- {
- absval[col] = a;
- rawval[col] = v;
- }
-
- ++it;
- }
-
- out = rawval;
- }
- else
- if(dim == 1) // find the maximum in each row
- {
- Col<eT> rawval(p_n_rows, fill::zeros);
- Col< T> absval(p_n_rows, fill::zeros);
-
- while(it != it_end)
- {
- const uword row = it.row();
-
- const eT& v = (*it);
- const T a = std::abs(v);
-
- if(a > absval[row])
- {
- absval[row] = a;
- rawval[row] = v;
- }
-
- ++it;
- }
-
- out = rawval;
- }
- }
- template<typename T1>
- inline
- typename T1::elem_type
- spop_max::vector_max
- (
- 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 get_pod_type<eT>::result T;
-
- const SpProxy<T1> p(x);
-
- if(p.get_n_elem() == 0)
- {
- arma_debug_check(true, "max(): object has no elements");
-
- return Datum<eT>::nan;
- }
-
- if(p.get_n_nonzero() == 0) { return eT(0); }
-
- if(SpProxy<T1>::use_iterator == false)
- {
- // direct access of values
- if(p.get_n_nonzero() == p.get_n_elem())
- {
- return op_max::direct_max(p.get_values(), p.get_n_nonzero());
- }
- else
- {
- const eT val1 = eT(0);
- const eT val2 = op_max::direct_max(p.get_values(), p.get_n_nonzero());
-
- return ( std::abs(val1) >= std::abs(val2) ) ? val1 : val2;
- }
- }
- else
- {
- // use iterator
- typename SpProxy<T1>::const_iterator_type it = p.begin();
- typename SpProxy<T1>::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<typename T1>
- inline
- typename arma_cx_only<typename T1::elem_type>::result
- spop_max::max(const SpBase<typename T1::elem_type, T1>& X)
- {
- arma_extra_debug_sigprint();
- typedef typename T1::elem_type eT;
- typedef typename get_pod_type<eT>::result T;
- const SpProxy<T1> 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, "max(): object has no elements");
-
- return Datum<eT>::nan;
- }
-
- T max_val = priv::most_neg<T>();
- eT ret_val;
-
- if(SpProxy<T1>::use_iterator)
- {
- // We have to iterate over the elements.
- typedef typename SpProxy<T1>::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 > max_val)
- {
- max_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 max value, so we can just call out to
- // other functions...
- ret_val = op_max::direct_max(P.get_values(), n_nonzero);
- max_val = std::abs(ret_val);
- }
-
- if(n_elem == n_nonzero)
- {
- return max_val;
- }
- else
- {
- return (T(0) > max_val) ? eT(0) : ret_val;
- }
- }
- template<typename T1>
- inline
- typename arma_cx_only<typename T1::elem_type>::result
- spop_max::max_with_index(const SpProxy<T1>& P, uword& index_of_max_val)
- {
- arma_extra_debug_sigprint();
-
- typedef typename T1::elem_type eT;
- typedef typename get_pod_type<eT>::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, "max(): object has no elements");
-
- index_of_max_val = uword(0);
-
- return Datum<eT>::nan;
- }
-
- T max_val = priv::most_neg<T>();
-
- if(SpProxy<T1>::use_iterator)
- {
- // We have to iterate over the elements.
- typedef typename SpProxy<T1>::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 > max_val)
- {
- max_val = tmp_val;
- index_of_max_val = it.row() + it.col() * n_rows;
- }
-
- ++it;
- }
- }
- else
- {
- // We can do direct access.
- max_val = std::abs(op_max::direct_max(P.get_values(), n_nonzero, index_of_max_val));
- // Convert to actual position in matrix.
- const uword row = P.get_row_indices()[index_of_max_val];
- uword col = 0;
- while (P.get_col_ptrs()[++col] <= index_of_max_val) { }
- index_of_max_val = (col - 1) * n_rows + row;
- }
-
-
- if(n_elem != n_nonzero)
- {
- max_val = std::max(T(0), max_val);
- // If the max_val is a nonzero element, we need its actual position in the matrix.
- if(max_val == T(0))
- {
- // Find first zero element.
- uword last_row = 0;
- uword last_col = 0;
-
- typedef typename SpProxy<T1>::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_max_val = it.col() * n_rows + last_row + 1;
- break;
- }
- else if ((it.col() >= last_col + 1) && (last_row < n_rows - 1))
- {
- index_of_max_val = last_col * n_rows + last_row + 1;
- break;
- }
- else if ((it.col() == last_col + 1) && (it.row() > 0))
- {
- index_of_max_val = it.col() * n_rows;
- break;
- }
- else if (it.col() > last_col + 1)
- {
- index_of_max_val = (last_col + 1) * n_rows;
- break;
- }
- last_row = it.row();
- last_col = it.col();
- ++it;
- }
- }
- }
- return P[index_of_max_val];
- }
- //! @}
|