xref: /third_party/node/deps/v8/src/base/bits.cc (revision 1cb0ef41)
1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/base/bits.h"
6
7#include <limits>
8
9#include "src/base/logging.h"
10
11namespace v8 {
12namespace base {
13namespace bits {
14
15uint32_t RoundUpToPowerOfTwo32(uint32_t value) {
16  DCHECK_LE(value, uint32_t{1} << 31);
17  if (value) --value;
18// Use computation based on leading zeros if we have compiler support for that.
19#if V8_HAS_BUILTIN_CLZ || V8_CC_MSVC
20  return 1u << (32 - CountLeadingZeros(value));
21#else
22  value |= value >> 1;
23  value |= value >> 2;
24  value |= value >> 4;
25  value |= value >> 8;
26  value |= value >> 16;
27  return value + 1;
28#endif
29}
30
31uint64_t RoundUpToPowerOfTwo64(uint64_t value) {
32  DCHECK_LE(value, uint64_t{1} << 63);
33  if (value) --value;
34// Use computation based on leading zeros if we have compiler support for that.
35#if V8_HAS_BUILTIN_CLZ
36  return uint64_t{1} << (64 - CountLeadingZeros(value));
37#else
38  value |= value >> 1;
39  value |= value >> 2;
40  value |= value >> 4;
41  value |= value >> 8;
42  value |= value >> 16;
43  value |= value >> 32;
44  return value + 1;
45#endif
46}
47
48
49int32_t SignedMulHigh32(int32_t lhs, int32_t rhs) {
50  int64_t const value = static_cast<int64_t>(lhs) * static_cast<int64_t>(rhs);
51  return bit_cast<int32_t, uint32_t>(bit_cast<uint64_t>(value) >> 32u);
52}
53
54
55int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc) {
56  return bit_cast<int32_t>(bit_cast<uint32_t>(acc) +
57                           bit_cast<uint32_t>(SignedMulHigh32(lhs, rhs)));
58}
59
60
61int32_t SignedDiv32(int32_t lhs, int32_t rhs) {
62  if (rhs == 0) return 0;
63  if (rhs == -1) return lhs == std::numeric_limits<int32_t>::min() ? lhs : -lhs;
64  return lhs / rhs;
65}
66
67
68int32_t SignedMod32(int32_t lhs, int32_t rhs) {
69  if (rhs == 0 || rhs == -1) return 0;
70  return lhs % rhs;
71}
72
73int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs) {
74  using limits = std::numeric_limits<int64_t>;
75  // Underflow if {lhs + rhs < min}. In that case, return {min}.
76  if (rhs < 0 && lhs < limits::min() - rhs) return limits::min();
77  // Overflow if {lhs + rhs > max}. In that case, return {max}.
78  if (rhs >= 0 && lhs > limits::max() - rhs) return limits::max();
79  return lhs + rhs;
80}
81
82int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs) {
83  using limits = std::numeric_limits<int64_t>;
84  // Underflow if {lhs - rhs < min}. In that case, return {min}.
85  if (rhs > 0 && lhs < limits::min() + rhs) return limits::min();
86  // Overflow if {lhs - rhs > max}. In that case, return {max}.
87  if (rhs <= 0 && lhs > limits::max() + rhs) return limits::max();
88  return lhs - rhs;
89}
90
91bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t* val) {
92  // Compute the result as {int64_t}, then check for overflow.
93  int64_t result = int64_t{lhs} * int64_t{rhs};
94  *val = static_cast<int32_t>(result);
95  using limits = std::numeric_limits<int32_t>;
96  return result < limits::min() || result > limits::max();
97}
98
99}  // namespace bits
100}  // namespace base
101}  // namespace v8
102