blob: 52013ad49bb972d18ecc0fd2fb5e076fd8484b43 [file] [log] [blame]
Austin Schuhb4691e92020-12-31 12:37:18 -08001// Copyright 2020 The Abseil Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// -----------------------------------------------------------------------------
16// File: bits.h
17// -----------------------------------------------------------------------------
18//
19// This file contains implementations of C++20's bitwise math functions, as
20// defined by:
21//
22// P0553R4:
23// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html
24// P0556R3:
25// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html
26// P1355R2:
27// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html
28// P1956R1:
29// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf
30//
31// When using a standard library that implements these functions, we use the
32// standard library's implementation.
33
34#ifndef ABSL_NUMERIC_BITS_H_
35#define ABSL_NUMERIC_BITS_H_
36
37#include <cstdint>
38#include <limits>
39#include <type_traits>
40
41#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) || \
42 (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
43#include <bit>
44#endif
45
46#include "absl/base/attributes.h"
47#include "absl/base/config.h"
48#include "absl/numeric/internal/bits.h"
49
50namespace absl {
51ABSL_NAMESPACE_BEGIN
52
53#if !(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
54// rotating
55template <class T>
56ABSL_MUST_USE_RESULT constexpr
57 typename std::enable_if<std::is_unsigned<T>::value, T>::type
58 rotl(T x, int s) noexcept {
59 return numeric_internal::RotateLeft(x, s);
60}
61
62template <class T>
63ABSL_MUST_USE_RESULT constexpr
64 typename std::enable_if<std::is_unsigned<T>::value, T>::type
65 rotr(T x, int s) noexcept {
66 return numeric_internal::RotateRight(x, s);
67}
68
69// Counting functions
70//
71// While these functions are typically constexpr, on some platforms, they may
72// not be marked as constexpr due to constraints of the compiler/available
73// intrinsics.
74template <class T>
75ABSL_INTERNAL_CONSTEXPR_CLZ inline
76 typename std::enable_if<std::is_unsigned<T>::value, int>::type
77 countl_zero(T x) noexcept {
78 return numeric_internal::CountLeadingZeroes(x);
79}
80
81template <class T>
82ABSL_INTERNAL_CONSTEXPR_CLZ inline
83 typename std::enable_if<std::is_unsigned<T>::value, int>::type
84 countl_one(T x) noexcept {
85 // Avoid integer promotion to a wider type
86 return countl_zero(static_cast<T>(~x));
87}
88
89template <class T>
90ABSL_INTERNAL_CONSTEXPR_CTZ inline
91 typename std::enable_if<std::is_unsigned<T>::value, int>::type
92 countr_zero(T x) noexcept {
93 return numeric_internal::CountTrailingZeroes(x);
94}
95
96template <class T>
97ABSL_INTERNAL_CONSTEXPR_CTZ inline
98 typename std::enable_if<std::is_unsigned<T>::value, int>::type
99 countr_one(T x) noexcept {
100 // Avoid integer promotion to a wider type
101 return countr_zero(static_cast<T>(~x));
102}
103
104template <class T>
105ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline
106 typename std::enable_if<std::is_unsigned<T>::value, int>::type
107 popcount(T x) noexcept {
108 return numeric_internal::Popcount(x);
109}
110#else // defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
111
112using std::countl_one;
113using std::countl_zero;
114using std::countr_one;
115using std::countr_zero;
116using std::popcount;
117using std::rotl;
118using std::rotr;
119
120#endif
121
122#if !(defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L)
123// Returns: true if x is an integral power of two; false otherwise.
124template <class T>
125constexpr inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
126has_single_bit(T x) noexcept {
127 return x != 0 && (x & (x - 1)) == 0;
128}
129
130// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any
131// fractional part discarded.
132template <class T>
133ABSL_INTERNAL_CONSTEXPR_CLZ inline
134 typename std::enable_if<std::is_unsigned<T>::value, T>::type
135 bit_width(T x) noexcept {
136 return std::numeric_limits<T>::digits - countl_zero(x);
137}
138
139// Returns: If x == 0, 0; otherwise the maximal value y such that
140// has_single_bit(y) is true and y <= x.
141template <class T>
142ABSL_INTERNAL_CONSTEXPR_CLZ inline
143 typename std::enable_if<std::is_unsigned<T>::value, T>::type
144 bit_floor(T x) noexcept {
145 return x == 0 ? 0 : T{1} << (bit_width(x) - 1);
146}
147
148// Returns: N, where N is the smallest power of 2 greater than or equal to x.
149//
150// Preconditions: N is representable as a value of type T.
151template <class T>
152ABSL_INTERNAL_CONSTEXPR_CLZ inline
153 typename std::enable_if<std::is_unsigned<T>::value, T>::type
154 bit_ceil(T x) {
155 // If T is narrower than unsigned, T{1} << bit_width will be promoted. We
156 // want to force it to wraparound so that bit_ceil of an invalid value are not
157 // core constant expressions.
158 //
159 // BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would
160 // undergo promotion to unsigned but not fit the result into T without
161 // truncation.
162 return has_single_bit(x) ? T{1} << (bit_width(x) - 1)
163 : numeric_internal::BitCeilNonPowerOf2(x);
164}
165#else // defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
166
167using std::bit_ceil;
168using std::bit_floor;
169using std::bit_width;
170using std::has_single_bit;
171
172#endif
173
174ABSL_NAMESPACE_END
175} // namespace absl
176
177#endif // ABSL_NUMERIC_BITS_H_