mfbt/RollingMean.h
author Bryce Van Dyk <bvandyk@mozilla.com>
Mon, 27 Aug 2018 16:25:54 +0000
changeset 488616 259675bd67f96acf1ae0f2ed6115de4331a94d32
parent 434354 b0e818e98bb51abf5336484a7cf47b10ddfb88fa
child 505383 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1486502 - Add widevine CDM headers to third party paths, clang-format ignore. r=sylvestre We wish to keep the widevine headers in the same formatting as upstream to ease comparison and as we do not modify these files. This patch adds the existing headers, as well as another we anticipate pulling down for our next bump (content_decryption_module_proxy.h) to the ignored paths. These files are ignored individually rather than the whole directory they're in, as we also have Mozilla code in that dir. Differential Revision: https://phabricator.services.mozilla.com/D4347

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

/* Calculate the rolling mean of a series of values. */

#ifndef mozilla_RollingMean_h_
#define mozilla_RollingMean_h_

#include "mozilla/Assertions.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Vector.h"

#include <stddef.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");

  explicit 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 / int64_t(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_