// 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 running_stat_vec //! @{ template inline running_stat_vec::~running_stat_vec() { arma_extra_debug_sigprint_this(this); } template inline running_stat_vec::running_stat_vec(const bool in_calc_cov) : calc_cov(in_calc_cov) { arma_extra_debug_sigprint_this(this); } template inline running_stat_vec::running_stat_vec(const running_stat_vec& in_rsv) : calc_cov (in_rsv.calc_cov) , counter (in_rsv.counter) , r_mean (in_rsv.r_mean) , r_var (in_rsv.r_var) , r_cov (in_rsv.r_cov) , min_val (in_rsv.min_val) , max_val (in_rsv.max_val) , min_val_norm(in_rsv.min_val_norm) , max_val_norm(in_rsv.max_val_norm) { arma_extra_debug_sigprint_this(this); } template inline running_stat_vec& running_stat_vec::operator=(const running_stat_vec& in_rsv) { arma_extra_debug_sigprint(); access::rw(calc_cov) = in_rsv.calc_cov; counter = in_rsv.counter; r_mean = in_rsv.r_mean; r_var = in_rsv.r_var; r_cov = in_rsv.r_cov; min_val = in_rsv.min_val; max_val = in_rsv.max_val; min_val_norm = in_rsv.min_val_norm; max_val_norm = in_rsv.max_val_norm; return *this; } //! update statistics to reflect new sample template template inline void running_stat_vec::operator() (const Base::T, T1>& X) { arma_extra_debug_sigprint(); const quasi_unwrap tmp(X.get_ref()); const Mat& sample = tmp.M; if( sample.is_empty() ) { return; } if( sample.internal_has_nonfinite() ) { arma_debug_warn_level(3, "running_stat_vec: sample ignored as it has non-finite elements"); return; } running_stat_vec_aux::update_stats(*this, sample); } template template inline void running_stat_vec::operator() (const Base< std::complex::T>, T1>& X) { arma_extra_debug_sigprint(); const quasi_unwrap tmp(X.get_ref()); const Mat< std::complex >& sample = tmp.M; if( sample.is_empty() ) { return; } if( sample.internal_has_nonfinite() ) { arma_debug_warn_level(3, "running_stat_vec: sample ignored as it has non-finite elements"); return; } running_stat_vec_aux::update_stats(*this, sample); } //! set all statistics to zero template inline void running_stat_vec::reset() { arma_extra_debug_sigprint(); counter.reset(); r_mean.reset(); r_var.reset(); r_cov.reset(); min_val.reset(); max_val.reset(); min_val_norm.reset(); max_val_norm.reset(); r_var_dummy.reset(); r_cov_dummy.reset(); tmp1.reset(); tmp2.reset(); } //! mean or average value template inline const typename running_stat_vec::return_type1& running_stat_vec::mean() const { arma_extra_debug_sigprint(); return r_mean; } //! variance template inline const typename running_stat_vec::return_type2& running_stat_vec::var(const uword norm_type) { arma_extra_debug_sigprint(); const T N = counter.value(); if(N > T(1)) { if(norm_type == 0) { return r_var; } else { const T N_minus_1 = counter.value_minus_1(); r_var_dummy = (N_minus_1/N) * r_var; return r_var_dummy; } } else { r_var_dummy.zeros(r_mean.n_rows, r_mean.n_cols); return r_var_dummy; } } //! standard deviation template inline typename running_stat_vec::return_type2 running_stat_vec::stddev(const uword norm_type) const { arma_extra_debug_sigprint(); const T N = counter.value(); if(N > T(1)) { if(norm_type == 0) { return sqrt(r_var); } else { const T N_minus_1 = counter.value_minus_1(); return sqrt( (N_minus_1/N) * r_var ); } } else { typedef typename running_stat_vec::return_type2 out_type; return out_type(); } } //! covariance template inline const Mat< typename running_stat_vec::eT >& running_stat_vec::cov(const uword norm_type) { arma_extra_debug_sigprint(); if(calc_cov) { const T N = counter.value(); if(N > T(1)) { if(norm_type == 0) { return r_cov; } else { const T N_minus_1 = counter.value_minus_1(); r_cov_dummy = (N_minus_1/N) * r_cov; return r_cov_dummy; } } else { const uword out_size = (std::max)(r_mean.n_rows, r_mean.n_cols); r_cov_dummy.zeros(out_size, out_size); return r_cov_dummy; } } else { r_cov_dummy.reset(); return r_cov_dummy; } } //! vector with minimum values template inline const typename running_stat_vec::return_type1& running_stat_vec::min() const { arma_extra_debug_sigprint(); return min_val; } //! vector with maximum values template inline const typename running_stat_vec::return_type1& running_stat_vec::max() const { arma_extra_debug_sigprint(); return max_val; } template inline typename running_stat_vec::return_type1 running_stat_vec::range() const { arma_extra_debug_sigprint(); return (max_val - min_val); } //! number of samples so far template inline typename running_stat_vec::T running_stat_vec::count() const { arma_extra_debug_sigprint(); return counter.value(); } // //! update statistics to reflect new sample (version for non-complex numbers) template inline void running_stat_vec_aux::update_stats ( running_stat_vec& x, const Mat::eT>& sample, const typename arma_not_cx::eT>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename running_stat_vec::eT eT; typedef typename running_stat_vec::T T; const T N = x.counter.value(); if(N > T(0)) { arma_debug_assert_same_size(x.r_mean, sample, "running_stat_vec(): dimensionality mismatch"); const uword n_elem = sample.n_elem; const eT* sample_mem = sample.memptr(); eT* r_mean_mem = x.r_mean.memptr(); T* r_var_mem = x.r_var.memptr(); eT* min_val_mem = x.min_val.memptr(); eT* max_val_mem = x.max_val.memptr(); const T N_plus_1 = x.counter.value_plus_1(); const T N_minus_1 = x.counter.value_minus_1(); if(x.calc_cov) { Mat& tmp1 = x.tmp1; Mat& tmp2 = x.tmp2; tmp1 = sample - x.r_mean; if(sample.n_cols == 1) { tmp2 = tmp1*trans(tmp1); } else { tmp2 = trans(tmp1)*tmp1; } x.r_cov *= (N_minus_1/N); x.r_cov += tmp2 / N_plus_1; } for(uword i=0; i max_val_mem[i]) { max_val_mem[i] = val; } const eT r_mean_val = r_mean_mem[i]; const eT tmp = val - r_mean_val; r_var_mem[i] = N_minus_1/N * r_var_mem[i] + (tmp*tmp)/N_plus_1; r_mean_mem[i] = r_mean_val + (val - r_mean_val)/N_plus_1; } } else { arma_debug_check( (sample.is_vec() == false), "running_stat_vec(): given sample must be a vector" ); x.r_mean.set_size(sample.n_rows, sample.n_cols); x.r_var.zeros(sample.n_rows, sample.n_cols); if(x.calc_cov) { x.r_cov.zeros(sample.n_elem, sample.n_elem); } x.min_val.set_size(sample.n_rows, sample.n_cols); x.max_val.set_size(sample.n_rows, sample.n_cols); const uword n_elem = sample.n_elem; const eT* sample_mem = sample.memptr(); eT* r_mean_mem = x.r_mean.memptr(); eT* min_val_mem = x.min_val.memptr(); eT* max_val_mem = x.max_val.memptr(); for(uword i=0; i inline void running_stat_vec_aux::update_stats ( running_stat_vec& x, const Mat::T > >& sample, const typename arma_not_cx::eT>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename running_stat_vec::eT eT; running_stat_vec_aux::update_stats(x, conv_to< Mat >::from(sample)); } //! update statistics to reflect new sample (version for complex numbers, non-complex sample) template inline void running_stat_vec_aux::update_stats ( running_stat_vec& x, const Mat::T >& sample, const typename arma_cx_only::eT>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename running_stat_vec::eT eT; running_stat_vec_aux::update_stats(x, conv_to< Mat >::from(sample)); } //! alter statistics to reflect new sample (version for complex numbers, complex sample) template inline void running_stat_vec_aux::update_stats ( running_stat_vec& x, const Mat::eT>& sample, const typename arma_cx_only::eT>::result* junk ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename running_stat_vec::eT eT; typedef typename running_stat_vec::T T; const T N = x.counter.value(); if(N > T(0)) { arma_debug_assert_same_size(x.r_mean, sample, "running_stat_vec(): dimensionality mismatch"); const uword n_elem = sample.n_elem; const eT* sample_mem = sample.memptr(); eT* r_mean_mem = x.r_mean.memptr(); T* r_var_mem = x.r_var.memptr(); eT* min_val_mem = x.min_val.memptr(); eT* max_val_mem = x.max_val.memptr(); T* min_val_norm_mem = x.min_val_norm.memptr(); T* max_val_norm_mem = x.max_val_norm.memptr(); const T N_plus_1 = x.counter.value_plus_1(); const T N_minus_1 = x.counter.value_minus_1(); if(x.calc_cov) { Mat& tmp1 = x.tmp1; Mat& tmp2 = x.tmp2; tmp1 = sample - x.r_mean; if(sample.n_cols == 1) { tmp2 = arma::conj(tmp1)*strans(tmp1); } else { tmp2 = trans(tmp1)*tmp1; //tmp2 = strans(conj(tmp1))*tmp1; } x.r_cov *= (N_minus_1/N); x.r_cov += tmp2 / N_plus_1; } for(uword i=0; i max_val_norm_mem[i]) { max_val_norm_mem[i] = val_norm; max_val_mem[i] = val; } const eT& r_mean_val = r_mean_mem[i]; r_var_mem[i] = N_minus_1/N * r_var_mem[i] + std::norm(val - r_mean_val)/N_plus_1; r_mean_mem[i] = r_mean_val + (val - r_mean_val)/N_plus_1; } } else { arma_debug_check( (sample.is_vec() == false), "running_stat_vec(): given sample must be a vector" ); x.r_mean.set_size(sample.n_rows, sample.n_cols); x.r_var.zeros(sample.n_rows, sample.n_cols); if(x.calc_cov) { x.r_cov.zeros(sample.n_elem, sample.n_elem); } x.min_val.set_size(sample.n_rows, sample.n_cols); x.max_val.set_size(sample.n_rows, sample.n_cols); x.min_val_norm.set_size(sample.n_rows, sample.n_cols); x.max_val_norm.set_size(sample.n_rows, sample.n_cols); const uword n_elem = sample.n_elem; const eT* sample_mem = sample.memptr(); eT* r_mean_mem = x.r_mean.memptr(); eT* min_val_mem = x.min_val.memptr(); eT* max_val_mem = x.max_val.memptr(); T* min_val_norm_mem = x.min_val_norm.memptr(); T* max_val_norm_mem = x.max_val_norm.memptr(); for(uword i=0; i