// Copyright (C) 2009-2011 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 running_stat //! @{ template inline arma_counter::~arma_counter() { arma_extra_debug_sigprint_this(this); } template inline arma_counter::arma_counter() : d_count( eT(0)) , i_count(uword(0)) { arma_extra_debug_sigprint_this(this); } template inline const arma_counter& arma_counter::operator++() { if(i_count < ARMA_MAX_UWORD) { i_count++; } else { d_count += eT(ARMA_MAX_UWORD); i_count = 1; } return *this; } template inline void arma_counter::operator++(int) { operator++(); } template inline void arma_counter::reset() { d_count = eT(0); i_count = uword(0); } template inline eT arma_counter::value() const { return d_count + eT(i_count); } template inline eT arma_counter::value_plus_1() const { if(i_count < ARMA_MAX_UWORD) { return d_count + eT(i_count + 1); } else { return d_count + eT(ARMA_MAX_UWORD) + eT(1); } } template inline eT arma_counter::value_minus_1() const { if(i_count > 0) { return d_count + eT(i_count - 1); } else { return d_count - eT(1); } } // template inline running_stat::~running_stat() { arma_extra_debug_sigprint_this(this); } template inline running_stat::running_stat() : r_mean ( eT(0)) , r_var (typename running_stat::T(0)) , min_val ( eT(0)) , max_val ( eT(0)) , min_val_norm(typename running_stat::T(0)) , max_val_norm(typename running_stat::T(0)) { arma_extra_debug_sigprint_this(this); } //! update statistics to reflect new sample template inline void running_stat::operator() (const typename running_stat::T sample) { arma_extra_debug_sigprint(); if( arma_isfinite(sample) == false ) { arma_debug_warn("running_stat: sample ignored as it is non-finite" ); return; } running_stat_aux::update_stats(*this, sample); } //! update statistics to reflect new sample (version for complex numbers) template inline void running_stat::operator() (const std::complex< typename running_stat::T >& sample) { arma_extra_debug_sigprint(); if( arma_isfinite(sample) == false ) { arma_debug_warn("running_stat: sample ignored as it is non-finite" ); return; } running_stat_aux::update_stats(*this, sample); } //! set all statistics to zero template inline void running_stat::reset() { arma_extra_debug_sigprint(); // typedef typename running_stat::T T; counter.reset(); r_mean = eT(0); r_var = T(0); min_val = eT(0); max_val = eT(0); min_val_norm = T(0); max_val_norm = T(0); } //! mean or average value template inline eT running_stat::mean() const { arma_extra_debug_sigprint(); return r_mean; } //! variance template inline typename running_stat::T running_stat::var(const uword norm_type) const { 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(); return (N_minus_1/N) * r_var; } } else { return T(0); } } //! standard deviation template inline typename running_stat::T running_stat::stddev(const uword norm_type) const { arma_extra_debug_sigprint(); return std::sqrt( (*this).var(norm_type) ); } //! minimum value template inline eT running_stat::min() const { arma_extra_debug_sigprint(); return min_val; } //! maximum value template inline eT running_stat::max() const { arma_extra_debug_sigprint(); return max_val; } //! number of samples so far template inline typename get_pod_type::result running_stat::count() const { arma_extra_debug_sigprint(); return counter.value(); } //! update statistics to reflect new sample (version for non-complex numbers, non-complex sample) template inline void running_stat_aux::update_stats(running_stat& x, const eT sample, const typename arma_not_cx::result* junk) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename running_stat::T T; const T N = x.counter.value(); if(N > T(0)) { if(sample < x.min_val) { x.min_val = sample; } if(sample > x.max_val) { x.max_val = sample; } const T N_plus_1 = x.counter.value_plus_1(); const T N_minus_1 = x.counter.value_minus_1(); // note: variance has to be updated before the mean const eT tmp = sample - x.r_mean; x.r_var = N_minus_1/N * x.r_var + (tmp*tmp)/N_plus_1; x.r_mean = x.r_mean + (sample - x.r_mean)/N_plus_1; //x.r_mean = (N/N_plus_1)*x.r_mean + sample/N_plus_1; //x.r_mean = (x.r_mean + sample/N) * N/N_plus_1; } else { x.r_mean = sample; x.min_val = sample; x.max_val = sample; // r_var is initialised to zero // in the constructor and reset() } x.counter++; } //! update statistics to reflect new sample (version for non-complex numbers, complex sample) template inline void running_stat_aux::update_stats(running_stat& x, const std::complex& sample, const typename arma_not_cx::result* junk) { arma_extra_debug_sigprint(); arma_ignore(junk); running_stat_aux::update_stats(x, std::real(sample)); } //! update statistics to reflect new sample (version for complex numbers, non-complex sample) template inline void running_stat_aux::update_stats(running_stat& x, const typename eT::value_type sample, const typename arma_cx_only::result* junk) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename eT::value_type T; running_stat_aux::update_stats(x, std::complex(sample)); } //! alter statistics to reflect new sample (version for complex numbers, complex sample) template inline void running_stat_aux::update_stats(running_stat& x, const eT& sample, const typename arma_cx_only::result* junk) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename eT::value_type T; const T sample_norm = std::norm(sample); const T N = x.counter.value(); if(N > T(0)) { if(sample_norm < x.min_val_norm) { x.min_val_norm = sample_norm; x.min_val = sample; } if(sample_norm > x.max_val_norm) { x.max_val_norm = sample_norm; x.max_val = sample; } const T N_plus_1 = x.counter.value_plus_1(); const T N_minus_1 = x.counter.value_minus_1(); x.r_var = N_minus_1/N * x.r_var + std::norm(sample - x.r_mean)/N_plus_1; x.r_mean = x.r_mean + (sample - x.r_mean)/N_plus_1; //x.r_mean = (N/N_plus_1)*x.r_mean + sample/N_plus_1; //x.r_mean = (x.r_mean + sample/N) * N/N_plus_1; } else { x.r_mean = sample; x.min_val = sample; x.max_val = sample; x.min_val_norm = sample_norm; x.max_val_norm = sample_norm; // r_var is initialised to zero // in the constructor and reset() } x.counter++; } //! @}