mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 888084 - Rolling mean for MFBT; r=waldo
This commit is contained in:
parent
b225f3dffe
commit
bb4129b621
109
mfbt/RollingMean.h
Normal file
109
mfbt/RollingMean.h
Normal file
@ -0,0 +1,109 @@
|
||||
/* -*- Mode: C++; tab-w idth: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/* A set abstraction for enumeration values. */
|
||||
|
||||
#ifndef mozilla_RollingMean_h_
|
||||
#define mozilla_RollingMean_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* RollingMean<T> calculates a rolling mean of the values it is given. It
|
||||
* accumulates the total as values are added and removed. The second type
|
||||
* argument S specifies the type of the total. This may need to be a bigger
|
||||
* type in order to maintain that the sum of all values in the average doesn't
|
||||
* exceed the maximum input value.
|
||||
*
|
||||
* WARNING: Float types are not supported due to rounding errors.
|
||||
*/
|
||||
template<typename T, typename S>
|
||||
class RollingMean
|
||||
{
|
||||
private:
|
||||
size_t mInsertIndex;
|
||||
size_t mMaxValues;
|
||||
Vector<T> mValues;
|
||||
S mTotal;
|
||||
|
||||
public:
|
||||
static_assert(!IsFloatingPoint<T>::value,
|
||||
"floating-point types are unsupported due to rounding "
|
||||
"errors");
|
||||
|
||||
RollingMean(size_t aMaxValues)
|
||||
: mInsertIndex(0),
|
||||
mMaxValues(aMaxValues),
|
||||
mTotal(0)
|
||||
{
|
||||
MOZ_ASSERT(aMaxValues > 0);
|
||||
}
|
||||
|
||||
RollingMean& operator=(RollingMean&& aOther) {
|
||||
MOZ_ASSERT(this != &aOther, "self-assignment is forbidden");
|
||||
this->~RollingMean();
|
||||
new(this) RollingMean(aOther.mMaxValues);
|
||||
mInsertIndex = aOther.mInsertIndex;
|
||||
mTotal = aOther.mTotal;
|
||||
mValues.swap(aOther.mValues);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a value into the rolling mean.
|
||||
*/
|
||||
bool insert(T aValue) {
|
||||
MOZ_ASSERT(mValues.length() <= mMaxValues);
|
||||
|
||||
if (mValues.length() == mMaxValues) {
|
||||
mTotal = mTotal - mValues[mInsertIndex] + aValue;
|
||||
mValues[mInsertIndex] = aValue;
|
||||
} else {
|
||||
if (!mValues.append(aValue))
|
||||
return false;
|
||||
mTotal = mTotal + aValue;
|
||||
}
|
||||
|
||||
mInsertIndex = (mInsertIndex + 1) % mMaxValues;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the rolling mean.
|
||||
*/
|
||||
T mean() {
|
||||
MOZ_ASSERT(!empty());
|
||||
return T(mTotal / mValues.length());
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
return mValues.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all values from the rolling mean.
|
||||
*/
|
||||
void clear() {
|
||||
mValues.clear();
|
||||
mInsertIndex = 0;
|
||||
mTotal = T(0);
|
||||
}
|
||||
|
||||
size_t maxValues() {
|
||||
return mMaxValues;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_RollingMean_h_
|
@ -969,7 +969,7 @@ VectorBase<T, N, AP, TV>::erase(T* it)
|
||||
*it = *(it + 1);
|
||||
++it;
|
||||
}
|
||||
popBack();
|
||||
popBack();
|
||||
}
|
||||
|
||||
template<typename T, size_t N, class AP, class TV>
|
||||
|
@ -48,6 +48,7 @@ mfbt_headers = [
|
||||
'RangedPtr.h',
|
||||
'ReentrancyGuard.h',
|
||||
'RefPtr.h',
|
||||
'RollingMean.h',
|
||||
'Scoped.h',
|
||||
'SHA1.h',
|
||||
'SplayTree.h',
|
||||
|
121
mfbt/tests/TestRollingMean.cpp
Normal file
121
mfbt/tests/TestRollingMean.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/RollingMean.h"
|
||||
|
||||
using mozilla::RollingMean;
|
||||
|
||||
class MyClass
|
||||
{
|
||||
public:
|
||||
uint32_t value;
|
||||
|
||||
MyClass(uint32_t val = 0) : value(val) {
|
||||
}
|
||||
|
||||
bool operator==(const MyClass& other) const {
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
MyClass operator+(const MyClass& other) const {
|
||||
return MyClass(value + other.value);
|
||||
}
|
||||
|
||||
MyClass operator-(const MyClass& other) const {
|
||||
return MyClass(value - other.value);
|
||||
}
|
||||
|
||||
MyClass operator/(uint32_t div) const {
|
||||
return MyClass(value / div);
|
||||
}
|
||||
};
|
||||
|
||||
class RollingMeanSuite
|
||||
{
|
||||
public:
|
||||
RollingMeanSuite()
|
||||
{ }
|
||||
|
||||
void runTests() {
|
||||
testZero();
|
||||
testClear();
|
||||
testRolling();
|
||||
testClass();
|
||||
testMove();
|
||||
}
|
||||
|
||||
private:
|
||||
void testZero() {
|
||||
RollingMean<uint32_t, uint64_t> mean(3);
|
||||
MOZ_ASSERT(mean.empty());
|
||||
}
|
||||
|
||||
void testClear() {
|
||||
RollingMean<uint32_t, uint64_t> mean(3);
|
||||
|
||||
mean.insert(4);
|
||||
MOZ_ASSERT(mean.mean() == 4);
|
||||
|
||||
mean.clear();
|
||||
MOZ_ASSERT(mean.empty());
|
||||
|
||||
mean.insert(3);
|
||||
MOZ_ASSERT(mean.mean() == 3);
|
||||
}
|
||||
|
||||
void testRolling() {
|
||||
RollingMean<uint32_t, uint64_t> mean(3);
|
||||
|
||||
mean.insert(10);
|
||||
MOZ_ASSERT(mean.mean() == 10);
|
||||
|
||||
mean.insert(20);
|
||||
MOZ_ASSERT(mean.mean() == 15);
|
||||
|
||||
mean.insert(35);
|
||||
MOZ_ASSERT(mean.mean() == 21);
|
||||
|
||||
mean.insert(5);
|
||||
MOZ_ASSERT(mean.mean() == 20);
|
||||
|
||||
mean.insert(10);
|
||||
MOZ_ASSERT(mean.mean() == 16);
|
||||
}
|
||||
|
||||
void testClass() {
|
||||
RollingMean<MyClass, MyClass> mean(3);
|
||||
|
||||
mean.insert(MyClass(4));
|
||||
MOZ_ASSERT(mean.mean() == MyClass(4));
|
||||
|
||||
mean.clear();
|
||||
MOZ_ASSERT(mean.empty());
|
||||
}
|
||||
|
||||
void testMove() {
|
||||
RollingMean<uint32_t, uint64_t> mean(3);
|
||||
mean = RollingMean<uint32_t, uint64_t>(4);
|
||||
MOZ_ASSERT(mean.maxValues() == 4);
|
||||
|
||||
mean.insert(10);
|
||||
MOZ_ASSERT(mean.mean() == 10);
|
||||
|
||||
mean = RollingMean<uint32_t, uint64_t>(3);
|
||||
mean.insert(30);
|
||||
mean.insert(40);
|
||||
mean.insert(50);
|
||||
mean.insert(60);
|
||||
MOZ_ASSERT(mean.mean() == 50);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
RollingMeanSuite suite;
|
||||
suite.runTests();
|
||||
return 0;
|
||||
}
|
@ -15,6 +15,7 @@ CPP_UNIT_TESTS += [
|
||||
'TestEnumSet.cpp',
|
||||
'TestFloatingPoint.cpp',
|
||||
'TestIntegerPrintfMacros.cpp',
|
||||
'TestRollingMean.cpp',
|
||||
'TestSHA1.cpp',
|
||||
'TestTypedEnum.cpp',
|
||||
'TestTypeTraits.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user