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_mean Chris@49: //! @{ Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: void Chris@49: spop_mean::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), "mean(): incorrect usage. dim must be 0 or 1"); Chris@49: Chris@49: SpProxy p(in.m); Chris@49: Chris@49: if(p.is_alias(out) == false) Chris@49: { Chris@49: spop_mean::apply_noalias(out, p, dim); Chris@49: } Chris@49: else Chris@49: { Chris@49: SpMat tmp; Chris@49: Chris@49: spop_mean::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_mean::apply_noalias Chris@49: ( Chris@49: SpMat& out_ref, Chris@49: const SpProxy& p, Chris@49: const uword dim Chris@49: ) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: Chris@49: const uword p_n_rows = p.get_n_rows(); Chris@49: const uword p_n_cols = p.get_n_cols(); Chris@49: Chris@49: if (dim == 0) Chris@49: { Chris@49: arma_extra_debug_print("spop_mean::apply_noalias(), dim = 0"); Chris@49: Chris@49: out_ref.set_size((p_n_rows > 0) ? 1 : 0, p_n_cols); Chris@49: Chris@49: if(p_n_rows > 0) Chris@49: { Chris@49: for(uword col = 0; col < p_n_cols; ++col) Chris@49: { Chris@49: // Do we have to use an iterator or can we use memory directly? Chris@49: if(SpProxy::must_use_iterator == true) Chris@49: { Chris@49: typename SpProxy::const_iterator_type it = p.begin_col(col); Chris@49: typename SpProxy::const_iterator_type end = p.begin_col(col + 1); Chris@49: Chris@49: const uword n_zero = p.get_n_rows() - (end.pos() - it.pos()); Chris@49: Chris@49: out_ref.at(col) = spop_mean::iterator_mean(it, end, n_zero, eT(0)); Chris@49: } Chris@49: else Chris@49: { Chris@49: out_ref.at(col) = spop_mean::direct_mean Chris@49: ( Chris@49: &p.get_values()[p.get_col_ptrs()[col]], Chris@49: p.get_col_ptrs()[col + 1] - p.get_col_ptrs()[col], Chris@49: p.get_n_rows() Chris@49: ); Chris@49: } Chris@49: } Chris@49: } Chris@49: } Chris@49: else if (dim == 1) Chris@49: { Chris@49: arma_extra_debug_print("spop_mean::apply_noalias(), dim = 1"); Chris@49: Chris@49: out_ref.set_size(p_n_rows, (p_n_cols > 0) ? 1 : 0); Chris@49: Chris@49: if(p_n_cols > 0) Chris@49: { Chris@49: for(uword row = 0; row < p_n_rows; ++row) Chris@49: { Chris@49: // We must use an iterator regardless of how it is stored. Chris@49: typename SpProxy::const_row_iterator_type it = p.begin_row(row); Chris@49: typename SpProxy::const_row_iterator_type end = p.end_row(row); Chris@49: Chris@49: const uword n_zero = p.get_n_cols() - (end.pos() - it.pos()); Chris@49: Chris@49: out_ref.at(row) = spop_mean::iterator_mean(it, end, n_zero, eT(0)); Chris@49: } Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: eT Chris@49: spop_mean::direct_mean Chris@49: ( Chris@49: const eT* const X, Chris@49: const uword length, Chris@49: const uword N Chris@49: ) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: const eT result = arrayops::accumulate(X, length) / T(N); Chris@49: Chris@49: return arma_isfinite(result) ? result : spop_mean::direct_mean_robust(X, length, N); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: eT Chris@49: spop_mean::direct_mean_robust Chris@49: ( Chris@49: const eT* const X, Chris@49: const uword length, Chris@49: const uword N Chris@49: ) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: uword i, j; Chris@49: Chris@49: eT r_mean = eT(0); Chris@49: Chris@49: const uword diff = (N - length); // number of zeros Chris@49: Chris@49: for(i = 0, j = 1; j < length; i += 2, j += 2) Chris@49: { Chris@49: const eT Xi = X[i]; Chris@49: const eT Xj = X[j]; Chris@49: Chris@49: r_mean += (Xi - r_mean) / T(diff + j); Chris@49: r_mean += (Xj - r_mean) / T(diff + j + 1); Chris@49: } Chris@49: Chris@49: if(i < length) Chris@49: { Chris@49: const eT Xi = X[i]; Chris@49: Chris@49: r_mean += (Xi - r_mean) / T(diff + i + 1); Chris@49: } Chris@49: Chris@49: return r_mean; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: typename T1::elem_type Chris@49: spop_mean::mean_all(const SpBase& X) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: SpProxy p(X.get_ref()); Chris@49: Chris@49: if (SpProxy::must_use_iterator == true) Chris@49: { Chris@49: typename SpProxy::const_iterator_type it = p.begin(); Chris@49: typename SpProxy::const_iterator_type end = p.end(); Chris@49: Chris@49: return spop_mean::iterator_mean(it, end, p.get_n_elem() - p.get_n_nonzero(), typename T1::elem_type(0)); Chris@49: } Chris@49: else // must_use_iterator == false; that is, we can directly access the values array Chris@49: { Chris@49: return spop_mean::direct_mean(p.get_values(), p.get_n_nonzero(), p.get_n_elem()); Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: eT Chris@49: spop_mean::iterator_mean(T1& it, const T1& end, const uword n_zero, const eT junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: eT sum = eT(0); Chris@49: Chris@49: T1 backup_it(it); // in case we have to use robust iterator_mean Chris@49: Chris@49: const uword it_begin_pos = it.pos(); Chris@49: Chris@49: while (it != end) Chris@49: { Chris@49: sum += (*it); Chris@49: ++it; Chris@49: } Chris@49: Chris@49: const eT result = sum / T(n_zero + (it.pos() - it_begin_pos)); Chris@49: Chris@49: return arma_isfinite(result) ? result : spop_mean::iterator_mean_robust(backup_it, end, n_zero, eT(0)); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: inline Chris@49: eT Chris@49: spop_mean::iterator_mean_robust(T1& it, const T1& end, const uword n_zero, const eT junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: typedef typename get_pod_type::result T; Chris@49: Chris@49: eT r_mean = eT(0); Chris@49: Chris@49: const uword it_begin_pos = it.pos(); Chris@49: Chris@49: while (it != end) Chris@49: { Chris@49: r_mean += ((*it - r_mean) / T(n_zero + (it.pos() - it_begin_pos) + 1)); Chris@49: ++it; Chris@49: } Chris@49: Chris@49: return r_mean; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: //! @}