]>
Commit | Line | Data |
---|---|---|
f3e91052 JW |
1 | // <bit> -*- C++ -*- |
2 | ||
a5544970 | 3 | // Copyright (C) 2018-2019 Free Software Foundation, Inc. |
f3e91052 JW |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // Under Section 7 of GPL version 3, you are granted additional | |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
24 | ||
25 | /** @file include/bit | |
26 | * This is a Standard C++ Library header. | |
27 | */ | |
28 | ||
29 | #ifndef _GLIBCXX_BIT | |
30 | #define _GLIBCXX_BIT 1 | |
31 | ||
32 | #pragma GCC system_header | |
33 | ||
34 | #if __cplusplus >= 201402L | |
35 | ||
36 | #include <type_traits> | |
37 | #include <limits> | |
38 | ||
39 | namespace std _GLIBCXX_VISIBILITY(default) | |
40 | { | |
41 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
42 | ||
43 | template<typename _Tp> | |
44 | constexpr _Tp | |
f35da524 | 45 | __rotl(_Tp __x, int __s) noexcept |
f3e91052 JW |
46 | { |
47 | constexpr auto _Nd = numeric_limits<_Tp>::digits; | |
f35da524 JW |
48 | const int __r = __s % _Nd; |
49 | if (__r == 0) | |
50 | return __x; | |
51 | else if (__r > 0) | |
52 | return (__x << __r) | (__x >> ((_Nd - __r) % _Nd)); | |
53 | else | |
54 | return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r) | |
f3e91052 JW |
55 | } |
56 | ||
57 | template<typename _Tp> | |
58 | constexpr _Tp | |
f35da524 | 59 | __rotr(_Tp __x, int __s) noexcept |
f3e91052 JW |
60 | { |
61 | constexpr auto _Nd = numeric_limits<_Tp>::digits; | |
f35da524 JW |
62 | const int __r = __s % _Nd; |
63 | if (__r == 0) | |
64 | return __x; | |
65 | else if (__r > 0) | |
66 | return (__x >> __r) | (__x << ((_Nd - __r) % _Nd)); | |
67 | else | |
68 | return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r) | |
f3e91052 JW |
69 | } |
70 | ||
71 | template<typename _Tp> | |
72 | constexpr int | |
73 | __countl_zero(_Tp __x) noexcept | |
74 | { | |
337dc307 | 75 | constexpr auto _Nd = numeric_limits<_Tp>::digits; |
f3e91052 JW |
76 | |
77 | if (__x == 0) | |
337dc307 | 78 | return _Nd; |
f3e91052 | 79 | |
337dc307 JW |
80 | constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits; |
81 | constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits; | |
82 | constexpr auto _Nd_u = numeric_limits<unsigned>::digits; | |
f3e91052 | 83 | |
337dc307 | 84 | if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) |
f3e91052 | 85 | { |
337dc307 | 86 | constexpr int __diff = _Nd_u - _Nd; |
f3e91052 JW |
87 | return __builtin_clz(__x) - __diff; |
88 | } | |
337dc307 | 89 | else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) |
f3e91052 | 90 | { |
337dc307 | 91 | constexpr int __diff = _Nd_ul - _Nd; |
f3e91052 JW |
92 | return __builtin_clzl(__x) - __diff; |
93 | } | |
337dc307 | 94 | else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) |
f3e91052 | 95 | { |
337dc307 | 96 | constexpr int __diff = _Nd_ull - _Nd; |
f3e91052 JW |
97 | return __builtin_clzll(__x) - __diff; |
98 | } | |
337dc307 | 99 | else // (_Nd > _Nd_ull) |
f3e91052 | 100 | { |
337dc307 | 101 | static_assert(_Nd <= (2 * _Nd_ull), |
f3e91052 JW |
102 | "Maximum supported integer size is 128-bit"); |
103 | ||
337dc307 | 104 | unsigned long long __high = __x >> _Nd_ull; |
f3e91052 JW |
105 | if (__high != 0) |
106 | { | |
337dc307 | 107 | constexpr int __diff = (2 * _Nd_ull) - _Nd; |
f3e91052 JW |
108 | return __builtin_clzll(__high) - __diff; |
109 | } | |
337dc307 JW |
110 | constexpr auto __max_ull = numeric_limits<unsigned long long>::max(); |
111 | unsigned long long __low = __x & __max_ull; | |
112 | return (_Nd - _Nd_ull) + __builtin_clzll(__low); | |
f3e91052 JW |
113 | } |
114 | } | |
115 | ||
116 | template<typename _Tp> | |
117 | constexpr int | |
118 | __countl_one(_Tp __x) noexcept | |
119 | { | |
120 | if (__x == numeric_limits<_Tp>::max()) | |
121 | return numeric_limits<_Tp>::digits; | |
122 | return std::__countl_zero<_Tp>((_Tp)~__x); | |
123 | } | |
124 | ||
125 | template<typename _Tp> | |
126 | constexpr int | |
127 | __countr_zero(_Tp __x) noexcept | |
128 | { | |
337dc307 | 129 | constexpr auto _Nd = numeric_limits<_Tp>::digits; |
f3e91052 JW |
130 | |
131 | if (__x == 0) | |
337dc307 | 132 | return _Nd; |
f3e91052 | 133 | |
337dc307 JW |
134 | constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits; |
135 | constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits; | |
136 | constexpr auto _Nd_u = numeric_limits<unsigned>::digits; | |
f3e91052 | 137 | |
337dc307 | 138 | if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) |
f3e91052 | 139 | return __builtin_ctz(__x); |
337dc307 | 140 | else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) |
f3e91052 | 141 | return __builtin_ctzl(__x); |
337dc307 | 142 | else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) |
f3e91052 | 143 | return __builtin_ctzll(__x); |
337dc307 | 144 | else // (_Nd > _Nd_ull) |
f3e91052 | 145 | { |
337dc307 | 146 | static_assert(_Nd <= (2 * _Nd_ull), |
f3e91052 JW |
147 | "Maximum supported integer size is 128-bit"); |
148 | ||
337dc307 JW |
149 | constexpr auto __max_ull = numeric_limits<unsigned long long>::max(); |
150 | unsigned long long __low = __x & __max_ull; | |
f3e91052 JW |
151 | if (__low != 0) |
152 | return __builtin_ctzll(__low); | |
337dc307 JW |
153 | unsigned long long __high = __x >> _Nd_ull; |
154 | return __builtin_ctzll(__high) + _Nd_ull; | |
f3e91052 JW |
155 | } |
156 | } | |
157 | ||
158 | template<typename _Tp> | |
159 | constexpr int | |
160 | __countr_one(_Tp __x) noexcept | |
161 | { | |
162 | if (__x == numeric_limits<_Tp>::max()) | |
163 | return numeric_limits<_Tp>::digits; | |
164 | return std::__countr_zero((_Tp)~__x); | |
165 | } | |
166 | ||
167 | template<typename _Tp> | |
168 | constexpr int | |
169 | __popcount(_Tp __x) noexcept | |
170 | { | |
337dc307 | 171 | constexpr auto _Nd = numeric_limits<_Tp>::digits; |
f3e91052 JW |
172 | |
173 | if (__x == 0) | |
174 | return 0; | |
175 | ||
337dc307 JW |
176 | constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits; |
177 | constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits; | |
178 | constexpr auto _Nd_u = numeric_limits<unsigned>::digits; | |
f3e91052 | 179 | |
337dc307 | 180 | if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) |
f3e91052 | 181 | return __builtin_popcount(__x); |
337dc307 | 182 | else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) |
f3e91052 | 183 | return __builtin_popcountl(__x); |
337dc307 | 184 | else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) |
f3e91052 | 185 | return __builtin_popcountll(__x); |
337dc307 | 186 | else // (_Nd > _Nd_ull) |
f3e91052 | 187 | { |
337dc307 | 188 | static_assert(_Nd <= (2 * _Nd_ull), |
f3e91052 JW |
189 | "Maximum supported integer size is 128-bit"); |
190 | ||
337dc307 JW |
191 | constexpr auto __max_ull = numeric_limits<unsigned long long>::max(); |
192 | unsigned long long __low = __x & __max_ull; | |
193 | unsigned long long __high = __x >> _Nd_ull; | |
f3e91052 JW |
194 | return __builtin_popcountll(__low) + __builtin_popcountll(__high); |
195 | } | |
196 | } | |
197 | ||
198 | template<typename _Tp> | |
199 | constexpr bool | |
200 | __ispow2(_Tp __x) noexcept | |
201 | { return std::__popcount(__x) == 1; } | |
202 | ||
203 | template<typename _Tp> | |
204 | constexpr _Tp | |
205 | __ceil2(_Tp __x) noexcept | |
206 | { | |
207 | constexpr auto _Nd = numeric_limits<_Tp>::digits; | |
2fb17d2d | 208 | if (__x == 0 || __x == 1) |
f3e91052 | 209 | return 1; |
281ab2fb JW |
210 | auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u)); |
211 | // If the shift exponent equals _Nd then the correct result is not | |
212 | // representable as a value of _Tp, and so the result is undefined. | |
213 | // Want that undefined behaviour to be detected in constant expressions, | |
214 | // by UBSan, and by debug assertions. | |
215 | #ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED | |
216 | if (!__builtin_is_constant_evaluated()) | |
217 | __glibcxx_assert( __shift_exponent != numeric_limits<_Tp>::digits ); | |
218 | #endif | |
219 | using __promoted_type = decltype(__x << 1); | |
220 | if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) | |
221 | { | |
222 | // If __x undergoes integral promotion then shifting by _Nd is | |
223 | // not undefined. In order to make the shift undefined, so that | |
224 | // it is diagnosed in constant expressions and by UBsan, we also | |
225 | // need to "promote" the shift exponent to be too large for the | |
226 | // promoted type. | |
227 | const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2; | |
228 | __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp; | |
229 | } | |
230 | return (_Tp)1u << __shift_exponent; | |
f3e91052 JW |
231 | } |
232 | ||
233 | template<typename _Tp> | |
234 | constexpr _Tp | |
235 | __floor2(_Tp __x) noexcept | |
236 | { | |
237 | constexpr auto _Nd = numeric_limits<_Tp>::digits; | |
238 | if (__x == 0) | |
239 | return 0; | |
240 | return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x >> 1))); | |
241 | } | |
242 | ||
243 | template<typename _Tp> | |
244 | constexpr _Tp | |
245 | __log2p1(_Tp __x) noexcept | |
246 | { | |
247 | constexpr auto _Nd = numeric_limits<_Tp>::digits; | |
f3e91052 JW |
248 | return _Nd - std::__countl_zero(__x); |
249 | } | |
250 | ||
251 | #if __cplusplus > 201703L | |
252 | ||
f3e91052 JW |
253 | template<typename _Tp, typename _Up = _Tp> |
254 | using _If_is_unsigned_integer | |
47f79054 | 255 | = enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>; |
f3e91052 | 256 | |
f35da524 | 257 | // [bit.rot], rotating |
f3e91052 JW |
258 | |
259 | template<typename _Tp> | |
f35da524 JW |
260 | [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> |
261 | rotl(_Tp __x, int __s) noexcept | |
f3e91052 JW |
262 | { return std::__rotl(__x, __s); } |
263 | ||
264 | template<typename _Tp> | |
f35da524 JW |
265 | [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> |
266 | rotr(_Tp __x, int __s) noexcept | |
f3e91052 JW |
267 | { return std::__rotr(__x, __s); } |
268 | ||
f35da524 | 269 | // [bit.count], counting |
f3e91052 JW |
270 | |
271 | template<typename _Tp> | |
272 | constexpr _If_is_unsigned_integer<_Tp, int> | |
273 | countl_zero(_Tp __x) noexcept | |
274 | { return std::__countl_zero(__x); } | |
275 | ||
276 | template<typename _Tp> | |
277 | constexpr _If_is_unsigned_integer<_Tp, int> | |
278 | countl_one(_Tp __x) noexcept | |
279 | { return std::__countl_one(__x); } | |
280 | ||
281 | template<typename _Tp> | |
282 | constexpr _If_is_unsigned_integer<_Tp, int> | |
283 | countr_zero(_Tp __x) noexcept | |
284 | { return std::__countr_zero(__x); } | |
285 | ||
286 | template<typename _Tp> | |
287 | constexpr _If_is_unsigned_integer<_Tp, int> | |
288 | countr_one(_Tp __x) noexcept | |
289 | { return std::__countr_one(__x); } | |
290 | ||
291 | template<typename _Tp> | |
292 | constexpr _If_is_unsigned_integer<_Tp, int> | |
293 | popcount(_Tp __x) noexcept | |
294 | { return std::__popcount(__x); } | |
f3e91052 | 295 | |
f35da524 | 296 | // [bit.pow.two], integral powers of 2 |
f3e91052 JW |
297 | |
298 | template<typename _Tp> | |
299 | constexpr _If_is_unsigned_integer<_Tp, bool> | |
300 | ispow2(_Tp __x) noexcept | |
301 | { return std::__ispow2(__x); } | |
302 | ||
303 | template<typename _Tp> | |
304 | constexpr _If_is_unsigned_integer<_Tp> | |
305 | ceil2(_Tp __x) noexcept | |
306 | { return std::__ceil2(__x); } | |
307 | ||
308 | template<typename _Tp> | |
309 | constexpr _If_is_unsigned_integer<_Tp> | |
310 | floor2(_Tp __x) noexcept | |
311 | { return std::__floor2(__x); } | |
312 | ||
313 | template<typename _Tp> | |
314 | constexpr _If_is_unsigned_integer<_Tp> | |
315 | log2p1(_Tp __x) noexcept | |
316 | { return std::__log2p1(__x); } | |
317 | ||
45c7215c JW |
318 | /// Byte order |
319 | enum class endian | |
320 | { | |
321 | little = __ORDER_LITTLE_ENDIAN__, | |
322 | big = __ORDER_BIG_ENDIAN__, | |
323 | native = __BYTE_ORDER__ | |
324 | }; | |
f3e91052 JW |
325 | #endif // C++2a |
326 | ||
327 | _GLIBCXX_END_NAMESPACE_VERSION | |
328 | } // namespace std | |
329 | ||
330 | #endif // C++14 | |
331 | #endif // _GLIBCXX_BIT |