/** * Copyright 2013-2021 Software Radio Systems Limited * * This file is part of srsRAN. * * srsRAN is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * srsRAN is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #ifndef SRSRAN_ACCUMULATORS_H #define SRSRAN_ACCUMULATORS_H #include #include #include #include #include namespace srsran { template struct rolling_average { void push(T sample) { avg_ += (sample - avg_) / (count_ + 1); ++count_; } T value() const { return count_ == 0 ? 0 : avg_; } uint32_t count() const { return count_; } private: T avg_ = 0; uint32_t count_ = 0; }; template struct exp_average_fast_start { exp_average_fast_start(T alpha_, uint32_t start_size = 100) : alpha(alpha_), start_count_size(start_size) { assert(start_size > 0); } void push(T sample) { if (count < start_count_size) { avg_ += (sample - avg_) / (count + 1); count++; } else { avg_ = (1 - alpha) * avg_ + alpha * sample; } } T value() const { return count == 0 ? 0 : avg_; } private: T avg_ = 0; uint32_t count = 0; uint32_t start_count_size; T alpha; }; namespace detail { template struct sliding_window { sliding_window(uint32_t N, T val = 0) : window(N, val) {} void push(T sample) { window[next_idx++] = sample; if (next_idx >= window.size()) { next_idx -= window.size(); } } std::size_t size() const { return window.size(); } const T& oldest() const { return window[next_idx % size()]; } T& operator[](std::size_t i) { return window[i]; } const T& operator[](std::size_t i) const { return window[i]; } std::vector window; std::size_t next_idx = 0; }; } // namespace detail template struct sliding_sum : private detail::sliding_window { using base_t = detail::sliding_window; using base_t::oldest; using base_t::push; using base_t::size; using base_t::sliding_window; T value() const { T ret = 0; for (std::size_t i = 0; i < size(); ++i) { ret += (*this)[i]; } return ret; } }; template struct sliding_average { sliding_average(uint32_t N) : window(N, 0) {} void push(T sample) { window.push(sample); } T value() const { return window.value() / window.size(); } private: sliding_sum window; }; template struct null_sliding_average { null_sliding_average(uint32_t N) : window(N, null_value()) {} void push(T sample) { window.push(sample); } void push_hole() { window.push(null_value()); } T value() const { T ret = 0; uint32_t count = 0; for (std::size_t i = 0; i < window.size(); ++i) { if (window[i] != null_value()) { ret += window[i]; count++; } } return (count == 0) ? null_value() : ret / count; } static constexpr T null_value() { return std::numeric_limits::max(); } private: detail::sliding_window window; }; template struct exp_average_irreg_sampling { // an exp_average has the formula y_n = alpha*x + (1-alpha)*y_n-1 <=> y_n += alpha(x - y_n-1) // alpha can be thought as 1-exp^{-dt/T} where dt is the sample period and T is the time-constant of a LP filter // for variable dt, alpha[dt] = 1-exp^{-dt/T} = 1-(exp^{-1/T})^dt = 1 - (1-alpha[1])^dt exp_average_irreg_sampling(T alpha_, T init_val) : avg_(init_val) { assert(alpha_ < 1 and alpha_ > 0 and "Invalid alpha parameter."); coeff = 1 - alpha_; } void push(T sample, uint32_t sample_jump) { avg_ += (1 - pow(coeff, sample_jump)) * (sample - avg_); } T value() const { return avg_; } private: T avg_ = 0; T coeff; }; } // namespace srsran #endif // SRSRAN_ACCUMULATORS_H