blob: f7e7183f8f36d63dbae2a1ca80b03dae44dd979d [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_LIB_WLAN_COMMON_INCLUDE_WLAN_COMMON_MOVING_AVERAGE_H_
#define GARNET_LIB_WLAN_COMMON_INCLUDE_WLAN_COMMON_MOVING_AVERAGE_H_
#include <limits>
#include <type_traits>
#include <zircon/assert.h>
#include "energy.h"
namespace wlan {
namespace common {
template <typename ValueType, typename SumType, uint32_t N> class MovingAverage {
static_assert(std::numeric_limits<ValueType>::max() * N < std::numeric_limits<SumType>::max(),
"'SumType' too small and cannot hold the maximum sum.");
static_assert(std::is_arithmetic<ValueType>::value, "'ValueType' must be numeric.");
static_assert(std::is_arithmetic<SumType>::value, "'SumType' must be numeric.");
public:
ValueType avg() const { return (n == 0 ? 0 : sum / n); }
void add(ValueType item) {
if (n < N) {
n++;
} else {
sum -= items[i];
}
sum += item;
items[i] = item;
i = (i + 1) % N;
}
void reset() { i = n = sum = 0; }
private:
ValueType items[N];
SumType sum = 0;
uint32_t i = 0;
uint32_t n = 0;
};
template <size_t N> class MovingAverageDbm {
static_assert(N <= 256, "Adding more than 256 samples can cause overflow");
public:
FemtoWatt avg() const { return FemtoWatt(n == 0 ? 0 : sum.val / n); }
void add(dBm sample) {
if (n < N) {
n++;
} else {
FemtoWatt to_subtract = to_femtoWatt_approx(samples[i]);
ZX_DEBUG_ASSERT(sum >= to_subtract);
sum -= to_subtract;
}
sum += to_femtoWatt_approx(sample);
samples[i] = sample;
i = (i + 1) % N;
}
void reset() {
n = 0;
sum = FemtoWatt(0);
}
private:
FemtoWatt sum{};
dBm samples[N];
uint16_t i = 0;
uint16_t n = 0;
};
} // namespace common
} // namespace wlan
#endif // GARNET_LIB_WLAN_COMMON_INCLUDE_WLAN_COMMON_MOVING_AVERAGE_H_