-
Notifications
You must be signed in to change notification settings - Fork 9
/
bits.h
154 lines (133 loc) · 5.35 KB
/
bits.h
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file defines some bit utilities.
#ifndef BASE_BITS_H_
#define BASE_BITS_H_
#include <stddef.h>
#include <stdint.h>
#include <bit>
#include <concepts>
#include "base/check.h"
#if defined(COMPILER_MSVC) && !defined(__clang__)
#include <intrin.h>
#endif
namespace base::bits {
// Bit functions in <bit> are restricted to a specific set of types of unsigned
// integer; restrict functions in this file that are related to those in that
// header to match for consistency.
template <typename T>
concept UnsignedInteger =
std::unsigned_integral<T> && !std::same_as<T, bool> &&
!std::same_as<T, char> && !std::same_as<T, char8_t> &&
!std::same_as<T, char16_t> && !std::same_as<T, char32_t> &&
!std::same_as<T, wchar_t>;
// We want to migrate all users of these functions to use the unsigned type
// versions of the functions, but until they are all moved over, create a
// concept that captures all the types that must be supported for compatibility
// but that we want to remove.
//
// TODO(https://crbug.com/1414634): Switch uses to supported functions and
// remove.
template <typename T>
concept SignedIntegerDeprecatedDoNotUse =
std::integral<T> && !UnsignedInteger<T>;
// Returns true iff |value| is a power of 2. DEPRECATED; use
// std::has_single_bit() instead.
//
// TODO(https://crbug.com/1414634): Switch uses and remove.
template <typename T>
requires SignedIntegerDeprecatedDoNotUse<T>
constexpr bool IsPowerOfTwoDeprecatedDoNotUse(T value) {
// From "Hacker's Delight": Section 2.1 Manipulating Rightmost Bits.
//
// Only positive integers with a single bit set are powers of two. If only one
// bit is set in x (e.g. 0b00000100000000) then |x-1| will have that bit set
// to zero and all bits to its right set to 1 (e.g. 0b00000011111111). Hence
// |x & (x-1)| is 0 iff x is a power of two.
return value > 0 && (value & (value - 1)) == 0;
}
// Round down |size| to a multiple of alignment, which must be a power of two.
template <typename T>
requires UnsignedInteger<T>
inline constexpr T AlignDown(T size, T alignment) {
DCHECK(std::has_single_bit(alignment));
return size & ~(alignment - 1);
}
// Round down |size| to a multiple of alignment, which must be a power of two.
// DEPRECATED; use the UnsignedInteger version.
//
// TODO(https://crbug.com/1414634): Switch uses and remove.
template <typename T>
requires SignedIntegerDeprecatedDoNotUse<T>
inline constexpr T AlignDownDeprecatedDoNotUse(T size, T alignment) {
DCHECK(IsPowerOfTwoDeprecatedDoNotUse(alignment));
return size & ~(alignment - 1);
}
// Move |ptr| back to the previous multiple of alignment, which must be a power
// of two. Defined for types where sizeof(T) is one byte.
template <typename T>
requires(sizeof(T) == 1)
inline T* AlignDown(T* ptr, uintptr_t alignment) {
return reinterpret_cast<T*>(
AlignDown(reinterpret_cast<uintptr_t>(ptr), alignment));
}
// Round up |size| to a multiple of alignment, which must be a power of two.
template <typename T>
requires UnsignedInteger<T>
inline constexpr T AlignUp(T size, T alignment) {
DCHECK(std::has_single_bit(alignment));
return (size + alignment - 1) & ~(alignment - 1);
}
// Round up |size| to a multiple of alignment, which must be a power of two.
// DEPRECATED; use the UnsignedInteger version.
//
// TODO(https://crbug.com/1414634): Switch uses and remove.
template <typename T>
requires SignedIntegerDeprecatedDoNotUse<T>
inline constexpr T AlignUpDeprecatedDoNotUse(T size, T alignment) {
DCHECK(IsPowerOfTwoDeprecatedDoNotUse(alignment));
return (size + alignment - 1) & ~(alignment - 1);
}
// Advance |ptr| to the next multiple of alignment, which must be a power of
// two. Defined for types where sizeof(T) is one byte.
template <typename T>
requires(sizeof(T) == 1)
inline T* AlignUp(T* ptr, uintptr_t alignment) {
return reinterpret_cast<T*>(
AlignUp(reinterpret_cast<uintptr_t>(ptr), alignment));
}
// Returns the integer i such as 2^i <= n < 2^(i+1).
//
// A common use for this function is to measure the number of bits required to
// contain a value; for that case use std::bit_width().
//
// A common use for this function is to take its result and use it to left-shift
// a bit; instead of doing so, use std::bit_floor().
inline int Log2Floor(uint32_t n) {
return 31 - std::countl_zero(n);
}
// Returns the integer i such as 2^(i-1) < n <= 2^i.
//
// A common use for this function is to measure the number of bits required to
// contain a value; for that case use std::bit_width().
//
// A common use for this function is to take its result and use it to left-shift
// a bit; instead of doing so, use std::bit_ceil().
inline int Log2Ceiling(uint32_t n) {
// When n == 0, we want the function to return -1.
// When n == 0, (n - 1) will underflow to 0xFFFFFFFF, which is
// why the statement below starts with (n ? 32 : -1).
return (n ? 32 : -1) - std::countl_zero(n - 1);
}
// Returns a value of type T with a single bit set in the left-most position.
// Can be used instead of manually shifting a 1 to the left. Unlike the other
// functions in this file, usable for any integral type.
template <typename T>
requires std::integral<T>
constexpr T LeftmostBit() {
T one(1u);
return one << (8 * sizeof(T) - 1);
}
} // namespace base::bits
#endif // BASE_BITS_H_