summaryrefslogtreecommitdiff
path: root/chromium/ui/latency/fixed_point.cc
blob: fafcf9ee85ea867d7a3e5f543c91a3b99f1bbc69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 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 <cmath>
#include <limits>

#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<uint64_t>(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<uint64_t>(ls32b) + rhs.ls32b;
  DCHECK_LT((ls32b_temp >> 32),
            std::numeric_limits<decltype(ms64b)>::max() - rhs.ms64b)
      << "Accumulator96b overflow.";
  uint64_t ms64b_add = rhs.ms64b + (ls32b_temp >> 32);
  DCHECK_LT(ms64b_add, std::numeric_limits<decltype(ms64b)>::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<uint64_t>(rhs.ls32b))
      << "Accumulator96b underflow.";
  ms64b -= rhs.ms64b;
  ls32b = ls32b_temp - rhs.ls32b;
}

double Accumulator96b::ToDouble() const {
  return (static_cast<double>(ms64b) * k2Pow32) + ls32b;
}

}  // namespace frame_metrics
}  // namespace ui