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