op_median_meat.hpp (armadillo-10.8.2.tar.xz) | : | op_median_meat.hpp (armadillo-11.0.0.tar.xz) | ||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
// Unless required by applicable law or agreed to in writing, software | // Unless required by applicable law or agreed to in writing, software | |||
// distributed under the License is distributed on an "AS IS" BASIS, | // distributed under the License is distributed on an "AS IS" BASIS, | |||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
// See the License for the specific language governing permissions and | // See the License for the specific language governing permissions and | |||
// limitations under the License. | // limitations under the License. | |||
// ------------------------------------------------------------------------ | // ------------------------------------------------------------------------ | |||
//! \addtogroup op_median | //! \addtogroup op_median | |||
//! @{ | //! @{ | |||
//! \brief | template<typename T1> | |||
//! 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() func | ||||
tion. | ||||
template<typename eT, typename T1> | ||||
inline | inline | |||
void | void | |||
op_median::apply(Mat<eT>& out, const Op<T1,op_median>& in, const typename arma_n ot_cx<eT>::result* junk) | op_median::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_median>& expr) | |||
{ | { | |||
arma_extra_debug_sigprint(); | arma_extra_debug_sigprint(); | |||
arma_ignore(junk); | ||||
// typedef typename T1::elem_type eT; | 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<T1> P(in.m); | const quasi_unwrap<T1> U(expr.m); | |||
typedef typename Proxy<T1>::stored_type P_stored_type; | const uword dim = expr.aux_uword_a; | |||
const bool is_alias = P.is_alias(out); | arma_debug_check( U.M.has_nan(), "median(): detected NaN" ); | |||
arma_debug_check( (dim > 1), "median(): parameter 'dim' must be 0 or 1" ); | ||||
if(is_Mat<P_stored_type>::value || is_alias) | if(U.is_alias(out)) | |||
{ | { | |||
const unwrap_check<P_stored_type> tmp(P.Q, is_alias); | Mat<eT> tmp; | |||
const typename unwrap_check<P_stored_type>::stored_type& X = tmp.M; | op_median::apply_noalias(out, U.M, dim); | |||
const uword X_n_rows = X.n_rows; | out.steal_mem(tmp); | |||
const uword X_n_cols = X.n_cols; | } | |||
else | ||||
{ | ||||
op_median::apply_noalias(out, U.M, dim); | ||||
} | ||||
} | ||||
if(dim == 0) // in each column | template<typename eT> | |||
{ | inline | |||
arma_extra_debug_print("op_median::apply(): dim = 0"); | void | |||
op_median::apply_noalias(Mat<eT>& out, const Mat<eT>& X, const uword dim, const | ||||
typename arma_not_cx<eT>::result* junk) | ||||
{ | ||||
arma_extra_debug_sigprint(); | ||||
arma_ignore(junk); | ||||
out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols); | const uword X_n_rows = X.n_rows; | |||
const uword X_n_cols = X.n_cols; | ||||
if(X_n_rows > 0) | if(dim == 0) // in each column | |||
{ | { | |||
std::vector<eT> tmp_vec(X_n_rows); | arma_extra_debug_print("op_median::apply(): dim = 0"); | |||
for(uword col=0; col < X_n_cols; ++col) | out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols); | |||
{ | ||||
arrayops::copy( &(tmp_vec[0]), X.colptr(col), X_n_rows ); | ||||
out[col] = op_median::direct_median(tmp_vec); | if(X_n_rows > 0) | |||
} | ||||
} | ||||
} | ||||
else // in each row | ||||
{ | { | |||
arma_extra_debug_print("op_median::apply(): dim = 1"); | std::vector<eT> tmp_vec(X_n_rows); | |||
out.set_size(X_n_rows, (X_n_cols > 0) ? 1 : 0); | for(uword col=0; col < X_n_cols; ++col) | |||
if(X_n_cols > 0) | ||||
{ | { | |||
std::vector<eT> tmp_vec(X_n_cols); | arrayops::copy( &(tmp_vec[0]), X.colptr(col), X_n_rows ); | |||
for(uword row=0; row < X_n_rows; ++row) | out[col] = op_median::direct_median(tmp_vec); | |||
{ | ||||
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 | else | |||
if(dim == 1) // in each row | ||||
{ | { | |||
const uword P_n_rows = P.get_n_rows(); | arma_extra_debug_print("op_median::apply(): dim = 1"); | |||
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<eT> tmp_vec(P_n_rows); | ||||
for(uword col=0; col < P_n_cols; ++col) | out.set_size(X_n_rows, (X_n_cols > 0) ? 1 : 0); | |||
{ | ||||
for(uword row=0; row < P_n_rows; ++row) { tmp_vec[row] = P.at(row,col | ||||
); } | ||||
out[col] = op_median::direct_median(tmp_vec); | if(X_n_cols > 0) | |||
} | ||||
} | ||||
} | ||||
else // in each row | ||||
{ | { | |||
arma_extra_debug_print("op_median::apply(): dim = 1"); | std::vector<eT> tmp_vec(X_n_cols); | |||
out.set_size(P_n_rows, (P_n_cols > 0) ? 1 : 0); | for(uword row=0; row < X_n_rows; ++row) | |||
if(P_n_cols > 0) | ||||
{ | { | |||
std::vector<eT> tmp_vec(P_n_cols); | for(uword col=0; col < X_n_cols; ++col) { tmp_vec[col] = X.at(row,col); | |||
} | ||||
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); | out[row] = op_median::direct_median(tmp_vec); | |||
} | ||||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
//! Implementation for complex numbers | template<typename eT> | |||
template<typename eT, typename T1> | ||||
inline | inline | |||
void | void | |||
op_median::apply(Mat<eT>& out, const Op<T1,op_median>& in, const typename arma_c x_only<eT>::result* junk) | op_median::apply_noalias(Mat<eT>& out, const Mat<eT>& X, const uword dim, const typename arma_cx_only<eT>::result* junk) | |||
{ | { | |||
arma_extra_debug_sigprint(); | arma_extra_debug_sigprint(); | |||
arma_ignore(junk); | arma_ignore(junk); | |||
// typedef typename std::complex<T> eT; | ||||
typedef typename get_pod_type<eT>::result T; | typedef typename get_pod_type<eT>::result T; | |||
arma_type_check(( is_same_type<eT, typename T1::elem_type>::no )); | ||||
const unwrap_check<T1> tmp(in.m, out); | ||||
const Mat<eT>& X = tmp.M; | ||||
const uword X_n_rows = X.n_rows; | const uword X_n_rows = X.n_rows; | |||
const uword X_n_cols = X.n_cols; | 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 | if(dim == 0) // in each column | |||
{ | { | |||
arma_extra_debug_print("op_median::apply(): dim = 0"); | arma_extra_debug_print("op_median::apply(): dim = 0"); | |||
out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols); | out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols); | |||
if(X_n_rows > 0) | if(X_n_rows > 0) | |||
{ | { | |||
std::vector< arma_cx_median_packet<T> > tmp_vec(X_n_rows); | std::vector< arma_cx_median_packet<T> > tmp_vec(X_n_rows); | |||
for(uword col=0; col<X_n_cols; ++col) | for(uword col=0; col<X_n_cols; ++col) | |||
{ | { | |||
const eT* colmem = X.colptr(col); | const eT* colmem = X.colptr(col); | |||
for(uword row=0; row<X_n_rows; ++row) | for(uword row=0; row<X_n_rows; ++row) | |||
{ | { | |||
tmp_vec[row].val = std::abs(colmem[row]); | tmp_vec[row].val = std::abs(colmem[row]); | |||
tmp_vec[row].index = row; | tmp_vec[row].index = row; | |||
} | } | |||
uword index1; | uword index1 = 0; | |||
uword index2; | uword index2 = 0; | |||
op_median::direct_cx_median_index(index1, index2, tmp_vec); | op_median::direct_cx_median_index(index1, index2, tmp_vec); | |||
out[col] = op_mean::robust_mean(colmem[index1], colmem[index2]); | out[col] = op_mean::robust_mean(colmem[index1], colmem[index2]); | |||
} | } | |||
} | } | |||
} | } | |||
else | else | |||
if(dim == 1) // in each row | if(dim == 1) // in each row | |||
{ | { | |||
arma_extra_debug_print("op_median::apply(): dim = 1"); | arma_extra_debug_print("op_median::apply(): dim = 1"); | |||
skipping to change at line 204 | skipping to change at line 161 | |||
std::vector< arma_cx_median_packet<T> > tmp_vec(X_n_cols); | std::vector< arma_cx_median_packet<T> > tmp_vec(X_n_cols); | |||
for(uword row=0; row<X_n_rows; ++row) | for(uword row=0; row<X_n_rows; ++row) | |||
{ | { | |||
for(uword col=0; col<X_n_cols; ++col) | for(uword col=0; col<X_n_cols; ++col) | |||
{ | { | |||
tmp_vec[col].val = std::abs(X.at(row,col)); | tmp_vec[col].val = std::abs(X.at(row,col)); | |||
tmp_vec[col].index = col; | tmp_vec[col].index = col; | |||
} | } | |||
uword index1; | uword index1 = 0; | |||
uword index2; | uword index2 = 0; | |||
op_median::direct_cx_median_index(index1, index2, tmp_vec); | op_median::direct_cx_median_index(index1, index2, tmp_vec); | |||
out[row] = op_mean::robust_mean( X.at(row,index1), X.at(row,index2) ); | out[row] = op_mean::robust_mean( X.at(row,index1), X.at(row,index2) ); | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
template<typename T1> | template<typename T1> | |||
inline | inline | |||
skipping to change at line 228 | skipping to change at line 185 | |||
( | ( | |||
const T1& X, | const T1& X, | |||
const typename arma_not_cx<typename T1::elem_type>::result* junk | const typename arma_not_cx<typename T1::elem_type>::result* junk | |||
) | ) | |||
{ | { | |||
arma_extra_debug_sigprint(); | arma_extra_debug_sigprint(); | |||
arma_ignore(junk); | arma_ignore(junk); | |||
typedef typename T1::elem_type eT; | typedef typename T1::elem_type eT; | |||
typedef typename Proxy<T1>::stored_type P_stored_type; | const quasi_unwrap<T1> U(X); | |||
const Proxy<T1> P(X); | const uword n_elem = U.M.n_elem; | |||
const uword n_elem = P.get_n_elem(); | ||||
if(n_elem == 0) | if(n_elem == 0) | |||
{ | { | |||
arma_debug_check(true, "median(): object has no elements"); | arma_debug_check(true, "median(): object has no elements"); | |||
return Datum<eT>::nan; | return Datum<eT>::nan; | |||
} | } | |||
std::vector<eT> tmp_vec(n_elem); | arma_debug_check( U.M.has_nan(), "median(): detected NaN" ); | |||
if(is_Mat<P_stored_type>::value) | ||||
{ | ||||
const unwrap<P_stored_type> tmp(P.Q); | ||||
const typename unwrap<P_stored_type>::stored_type& Y = tmp.M; | ||||
arrayops::copy( &(tmp_vec[0]), Y.memptr(), n_elem ); | ||||
} | ||||
else | ||||
{ | ||||
if(Proxy<T1>::use_at == false) | ||||
{ | ||||
typedef typename Proxy<T1>::ea_type ea_type; | ||||
ea_type A = P.get_ea(); | ||||
for(uword i=0; i<n_elem; ++i) { tmp_vec[i] = A[i]; } | std::vector<eT> tmp_vec(n_elem); | |||
} | ||||
else | ||||
{ | ||||
const uword n_rows = P.get_n_rows(); | ||||
const uword n_cols = P.get_n_cols(); | ||||
if(n_cols == 1) | arrayops::copy( &(tmp_vec[0]), U.M.memptr(), n_elem ); | |||
{ | ||||
for(uword row=0; row < n_rows; ++row) { tmp_vec[row] = P.at(row,0); } | ||||
} | ||||
else | ||||
if(n_rows == 1) | ||||
{ | ||||
for(uword col=0; col < n_cols; ++col) { tmp_vec[col] = P.at(0,col); } | ||||
} | ||||
else | ||||
{ | ||||
arma_stop_logic_error("op_median::median_vec(): expected a vector" ); | ||||
} | ||||
} | ||||
} | ||||
return op_median::direct_median(tmp_vec); | return op_median::direct_median(tmp_vec); | |||
} | } | |||
template<typename T1> | template<typename T1> | |||
inline | inline | |||
typename T1::elem_type | typename T1::elem_type | |||
op_median::median_vec | op_median::median_vec | |||
( | ( | |||
const T1& X, | const T1& X, | |||
const typename arma_cx_only<typename T1::elem_type>::result* junk | const typename arma_cx_only<typename T1::elem_type>::result* junk | |||
) | ) | |||
{ | { | |||
arma_extra_debug_sigprint(); | arma_extra_debug_sigprint(); | |||
arma_ignore(junk); | arma_ignore(junk); | |||
typedef typename T1::elem_type eT; | typedef typename T1::elem_type eT; | |||
typedef typename T1::pod_type T; | typedef typename T1::pod_type T; | |||
const Proxy<T1> P(X); | const quasi_unwrap<T1> U(X); | |||
const uword n_elem = P.get_n_elem(); | const uword n_elem = U.M.n_elem; | |||
if(n_elem == 0) | if(n_elem == 0) | |||
{ | { | |||
arma_debug_check(true, "median(): object has no elements"); | arma_debug_check(true, "median(): object has no elements"); | |||
return Datum<eT>::nan; | return Datum<eT>::nan; | |||
} | } | |||
std::vector< arma_cx_median_packet<T> > tmp_vec(n_elem); | arma_debug_check( U.M.has_nan(), "median(): detected NaN" ); | |||
if(Proxy<T1>::use_at == false) | std::vector< arma_cx_median_packet<T> > tmp_vec(n_elem); | |||
{ | ||||
typedef typename Proxy<T1>::ea_type ea_type; | ||||
ea_type A = P.get_ea(); | ||||
for(uword i=0; i<n_elem; ++i) | ||||
{ | ||||
tmp_vec[i].val = std::abs( A[i] ); | ||||
tmp_vec[i].index = i; | ||||
} | ||||
uword index1; | const eT* A = U.M.memptr(); | |||
uword index2; | ||||
op_median::direct_cx_median_index(index1, index2, tmp_vec); | ||||
return op_mean::robust_mean( A[index1], A[index2] ); | for(uword i=0; i<n_elem; ++i) | |||
} | ||||
else | ||||
{ | { | |||
const uword n_rows = P.get_n_rows(); | tmp_vec[i].val = std::abs( A[i] ); | |||
const uword n_cols = P.get_n_cols(); | tmp_vec[i].index = i; | |||
} | ||||
if(n_cols == 1) | ||||
{ | ||||
for(uword row=0; row < n_rows; ++row) | ||||
{ | ||||
tmp_vec[row].val = std::abs( P.at(row,0) ); | ||||
tmp_vec[row].index = row; | ||||
} | ||||
uword index1; | ||||
uword index2; | ||||
op_median::direct_cx_median_index(index1, index2, tmp_vec); | ||||
return op_mean::robust_mean( P.at(index1,0), P.at(index2,0) ); | ||||
} | ||||
else | ||||
if(n_rows == 1) | ||||
{ | ||||
for(uword col=0; col < n_cols; ++col) | ||||
{ | ||||
tmp_vec[col].val = std::abs( P.at(0,col) ); | ||||
tmp_vec[col].index = col; | ||||
} | ||||
uword index1; | ||||
uword index2; | ||||
op_median::direct_cx_median_index(index1, index2, tmp_vec); | ||||
return op_mean::robust_mean( P.at(0,index1), P.at(0,index2) ); | uword index1 = 0; | |||
} | uword index2 = 0; | |||
else | op_median::direct_cx_median_index(index1, index2, tmp_vec); | |||
{ | ||||
arma_stop_logic_error("op_median::median_vec(): expected a vector" ); | ||||
return eT(0); | return op_mean::robust_mean( A[index1], A[index2] ); | |||
} | ||||
} | ||||
} | } | |||
//! find the median value of a std::vector (contents is modified) | ||||
template<typename eT> | template<typename eT> | |||
inline | inline | |||
eT | eT | |||
op_median::direct_median(std::vector<eT>& X) | op_median::direct_median(std::vector<eT>& X) | |||
{ | { | |||
arma_extra_debug_sigprint(); | arma_extra_debug_sigprint(); | |||
// TODO: if NaN is detected, return NaN | ||||
const uword n_elem = uword(X.size()); | const uword n_elem = uword(X.size()); | |||
const uword half = n_elem/2; | const uword half = n_elem/2; | |||
typename std::vector<eT>::iterator first = X.begin(); | typename std::vector<eT>::iterator first = X.begin(); | |||
typename std::vector<eT>::iterator nth = first + half; | typename std::vector<eT>::iterator nth = first + half; | |||
typename std::vector<eT>::iterator pastlast = X.end(); | typename std::vector<eT>::iterator pastlast = X.end(); | |||
std::nth_element(first, nth, pastlast); | std::nth_element(first, nth, pastlast); | |||
if((n_elem % 2) == 0) // even number of elements | if((n_elem % 2) == 0) // even number of elements | |||
skipping to change at line 423 | skipping to change at line 296 | |||
( | ( | |||
uword& out_index1, | uword& out_index1, | |||
uword& out_index2, | uword& out_index2, | |||
std::vector< arma_cx_median_packet<T> >& X | std::vector< arma_cx_median_packet<T> >& X | |||
) | ) | |||
{ | { | |||
arma_extra_debug_sigprint(); | arma_extra_debug_sigprint(); | |||
typedef arma_cx_median_packet<T> eT; | typedef arma_cx_median_packet<T> eT; | |||
// TODO: if NaN is detected, return bool set to false, indicating presence of | ||||
NaN | ||||
const uword n_elem = uword(X.size()); | const uword n_elem = uword(X.size()); | |||
const uword half = n_elem/2; | const uword half = n_elem/2; | |||
typename std::vector<eT>::iterator first = X.begin(); | typename std::vector<eT>::iterator first = X.begin(); | |||
typename std::vector<eT>::iterator nth = first + half; | typename std::vector<eT>::iterator nth = first + half; | |||
typename std::vector<eT>::iterator pastlast = X.end(); | typename std::vector<eT>::iterator pastlast = X.end(); | |||
std::nth_element(first, nth, pastlast); | std::nth_element(first, nth, pastlast); | |||
out_index1 = (*nth).index; | out_index1 = (*nth).index; | |||
End of changes. 52 change blocks. | ||||
202 lines changed or deleted | 69 lines changed or added |