| // Copyright 2018 The Chromium 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 UI_FRAME_METRICS_FIXED_POINT_H_ |
| #define UI_FRAME_METRICS_FIXED_POINT_H_ |
| |
| #include <cstdint> |
| |
| #include "base/macros.h" |
| |
| namespace ui { |
| namespace frame_metrics { |
| |
| // Use fixed point math so we can manage our precision explicitly and avoid |
| // accumulating error in our windowed accumulators. |
| // The 64-bit accumulators reserve 32-bits for weights, and 32-bits for values. |
| // The 32-bit values reserve 16 bits before and after the radix point. |
| constexpr int kFixedPointShift = 16; |
| constexpr int64_t kFixedPointMultiplier{1LL << kFixedPointShift}; |
| |
| // kFixedPointRootMultiplier is used to shift the bits before taking the square |
| // root and undoing that shift after squaring in the SMR calculation. |
| constexpr int kFixedPointRootShift = 32; |
| constexpr int64_t kFixedPointRootMultiplier{1LL << kFixedPointRootShift}; |
| constexpr int64_t kFixedPointRootMultiplierSqrt{1LL |
| << (kFixedPointRootShift / 2)}; |
| |
| // We need a huge range to accumulate values for RMS calculations, which |
| // need double the range internally compared to the range we are targeting |
| // after taking the square root of the accumulation. |
| // This efficiently emulates a 96-bit unsigned integer with weighted |
| // accumulation operations. |
| // 32-bits are reserved for weights and 64-bits for squared values. |
| // Overflow or underflow indicates something is seriously wrong with the higher |
| // level metrics logic, so this class will DCHECK if it anticipates overflow |
| // or underflow: |
| // * It doesn't need to support OVERFLOW since the frame metric classes will |
| // always reset the entire accumulator before the accumulated weights |
| // overflow. The accumulated weights correspond to a maximum of the number of |
| // microseconds since the last reset, which for a 32-bit weight is about |
| // 1 hour. We will gather and reset results much more often than every hour. |
| // * It doesn't need to support UNDERFLOW since only the windowed metrics use |
| // Subtract, and those only subtract values it has already added. |
| class Accumulator96b { |
| public: |
| Accumulator96b() = default; |
| Accumulator96b(uint32_t value_to_square, uint32_t weight); |
| |
| void Add(const Accumulator96b& rhs); |
| void Subtract(const Accumulator96b& rhs); |
| double ToDouble() const; |
| |
| public: |
| uint64_t ms64b{0}; |
| uint32_t ls32b{0}; |
| }; |
| |
| // Convenience function overloads for AsDouble, to help with templated code. |
| inline double AsDouble(const Accumulator96b& value) { |
| return value.ToDouble(); |
| } |
| |
| inline double AsDouble(double value) { |
| return value; |
| } |
| |
| } // namespace frame_metrics |
| } // namespace ui |
| |
| #endif // UI_FRAME_METRICS_FIXED_POINT_H_ |