// 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. #include "ui/latency/fixed_point.h" #include #include #include "base/logging.h" namespace ui { namespace frame_metrics { namespace { constexpr uint64_t k2Pow32{1ULL << 32}; constexpr uint64_t k32LsbMask{0xFFFFFFFF}; } // namespace Accumulator96b::Accumulator96b(uint32_t value_to_square, uint32_t weight) { uint64_t square = static_cast(value_to_square) * value_to_square; uint64_t ms64b_temp = (square >> 32) * weight; uint64_t ls32b_temp = (square & k32LsbMask) * weight; ms64b = ms64b_temp + (ls32b_temp >> 32); ls32b = ls32b_temp & k32LsbMask; } void Accumulator96b::Add(const Accumulator96b& rhs) { uint64_t ls32b_temp = static_cast(ls32b) + rhs.ls32b; DCHECK_LT((ls32b_temp >> 32), std::numeric_limits::max() - rhs.ms64b) << "Accumulator96b overflow."; uint64_t ms64b_add = rhs.ms64b + (ls32b_temp >> 32); DCHECK_LT(ms64b_add, std::numeric_limits::max() - ms64b) << "Accumulator96b overflow."; ms64b += ms64b_add; ls32b = ls32b_temp & k32LsbMask; } void Accumulator96b::Subtract(const Accumulator96b& rhs) { uint64_t ls32b_temp = ls32b; if (ls32b < rhs.ls32b) { // Borrow from ms64b to ls32b. ms64b--; ls32b_temp |= k2Pow32; } DCHECK_GE(ms64b, rhs.ms64b) << "Accumulator96b underflow."; DCHECK_GE(ls32b_temp, static_cast(rhs.ls32b)) << "Accumulator96b underflow."; ms64b -= rhs.ms64b; ls32b = ls32b_temp - rhs.ls32b; } double Accumulator96b::ToDouble() const { return (static_cast(ms64b) * k2Pow32) + ls32b; } } // namespace frame_metrics } // namespace ui