// Copyright (C) 2009-2015 National ICT Australia (NICTA) // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------- // // Written by Conrad Sanderson - http://conradsanderson.id.au //! \addtogroup op_median //! @{ //! \brief //! For each row or for each column, find the median value. //! The result is stored in a dense matrix that has either one column or one row. //! The dimension, for which the medians are found, is set via the median() function. template inline void op_median::apply(Mat& out, const Op& in) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const uword dim = in.aux_uword_a; arma_debug_check( (dim > 1), "median(): parameter 'dim' must be 0 or 1" ); const Proxy P(in.m); typedef typename Proxy::stored_type P_stored_type; const bool is_alias = P.is_alias(out); if( (is_Mat::value == true) || is_alias ) { const unwrap_check tmp(P.Q, is_alias); const typename unwrap_check::stored_type& X = tmp.M; const uword X_n_rows = X.n_rows; const uword X_n_cols = X.n_cols; if(dim == 0) // in each column { arma_extra_debug_print("op_median::apply(): dim = 0"); out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols); if(X_n_rows > 0) { std::vector tmp_vec(X_n_rows); for(uword col=0; col < X_n_cols; ++col) { arrayops::copy( &(tmp_vec[0]), X.colptr(col), X_n_rows ); out[col] = op_median::direct_median(tmp_vec); } } } else // in each row { arma_extra_debug_print("op_median::apply(): dim = 1"); out.set_size(X_n_rows, (X_n_cols > 0) ? 1 : 0); if(X_n_cols > 0) { std::vector tmp_vec(X_n_cols); for(uword row=0; row < X_n_rows; ++row) { for(uword col=0; col < X_n_cols; ++col) { tmp_vec[col] = X.at(row,col); } out[row] = op_median::direct_median(tmp_vec); } } } } else { const uword P_n_rows = P.get_n_rows(); const uword P_n_cols = P.get_n_cols(); if(dim == 0) // in each column { arma_extra_debug_print("op_median::apply(): dim = 0"); out.set_size((P_n_rows > 0) ? 1 : 0, P_n_cols); if(P_n_rows > 0) { std::vector tmp_vec(P_n_rows); for(uword col=0; col < P_n_cols; ++col) { for(uword row=0; row < P_n_rows; ++row) { tmp_vec[row] = P.at(row,col); } out[col] = op_median::direct_median(tmp_vec); } } } else // in each row { arma_extra_debug_print("op_median::apply(): dim = 1"); out.set_size(P_n_rows, (P_n_cols > 0) ? 1 : 0); if(P_n_cols > 0) { std::vector tmp_vec(P_n_cols); for(uword row=0; row < P_n_rows; ++row) { for(uword col=0; col < P_n_cols; ++col) { tmp_vec[col] = P.at(row,col); } out[row] = op_median::direct_median(tmp_vec); } } } } } //! Implementation for complex numbers template inline void op_median::apply(Mat< std::complex >& out, const Op& in) { arma_extra_debug_sigprint(); typedef typename std::complex eT; arma_type_check(( is_same_type::no )); const unwrap_check tmp(in.m, out); const Mat& X = tmp.M; const uword X_n_rows = X.n_rows; const uword X_n_cols = X.n_cols; const uword dim = in.aux_uword_a; arma_debug_check( (dim > 1), "median(): parameter 'dim' must be 0 or 1" ); if(dim == 0) // in each column { arma_extra_debug_print("op_median::apply(): dim = 0"); out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols); if(X_n_rows > 0) { std::vector< arma_cx_median_packet > tmp_vec(X_n_rows); for(uword col=0; col 0) ? 1 : 0); if(X_n_cols > 0) { std::vector< arma_cx_median_packet > tmp_vec(X_n_cols); for(uword row=0; row inline typename T1::elem_type op_median::median_vec ( const T1& X, const typename arma_not_cx::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename Proxy::stored_type P_stored_type; const Proxy P(X); const uword n_elem = P.get_n_elem(); if(n_elem == 0) { arma_debug_check(true, "median(): object has no elements"); return Datum::nan; } std::vector tmp_vec(n_elem); if(is_Mat::value == true) { const unwrap tmp(P.Q); const typename unwrap::stored_type& Y = tmp.M; arrayops::copy( &(tmp_vec[0]), Y.memptr(), n_elem ); } else { if(Proxy::prefer_at_accessor == false) { typedef typename Proxy::ea_type ea_type; ea_type A = P.get_ea(); for(uword i=0; i inline typename T1::elem_type op_median::median_vec ( 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 T1::pod_type T; const Proxy P(X); const uword n_elem = P.get_n_elem(); if(n_elem == 0) { arma_debug_check(true, "median(): object has no elements"); return Datum::nan; } std::vector< arma_cx_median_packet > tmp_vec(n_elem); if(Proxy::prefer_at_accessor == false) { typedef typename Proxy::ea_type ea_type; ea_type A = P.get_ea(); for(uword i=0; i inline eT op_median::direct_median(std::vector& X) { arma_extra_debug_sigprint(); const uword n_elem = uword(X.size()); const uword half = n_elem/2; typename std::vector::iterator first = X.begin(); typename std::vector::iterator nth = first + half; typename std::vector::iterator pastlast = X.end(); std::nth_element(first, nth, pastlast); if((n_elem % 2) == 0) // even number of elements { typename std::vector::iterator start = X.begin(); typename std::vector::iterator pastend = start + half; const eT val1 = (*nth); const eT val2 = (*(std::max_element(start, pastend))); return op_mean::robust_mean(val1, val2); } else // odd number of elements { return (*nth); } } template inline void op_median::direct_cx_median_index ( uword& out_index1, uword& out_index2, std::vector< arma_cx_median_packet >& X ) { arma_extra_debug_sigprint(); typedef arma_cx_median_packet eT; const uword n_elem = uword(X.size()); const uword half = n_elem/2; typename std::vector::iterator first = X.begin(); typename std::vector::iterator nth = first + half; typename std::vector::iterator pastlast = X.end(); std::nth_element(first, nth, pastlast); out_index1 = (*nth).index; if((n_elem % 2) == 0) // even number of elements { typename std::vector::iterator start = X.begin(); typename std::vector::iterator pastend = start + half; out_index2 = (*(std::max_element(start, pastend))).index; } else // odd number of elements { out_index2 = out_index1; } } //! @}