@@ -27,14 +27,13 @@ namespace LIBC_NAMESPACE::cpp {
27
27
28
28
// This implementation of bit_cast requires trivially-constructible To, to avoid
29
29
// UB in the implementation.
30
- template <typename To, typename From>
31
- LIBC_INLINE constexpr cpp::enable_if_t <
32
- (sizeof (To) == sizeof (From)) &&
33
- cpp::is_trivially_constructible<To>::value &&
34
- cpp::is_trivially_copyable<To>::value &&
35
- cpp::is_trivially_copyable<From>::value,
36
- To>
37
- bit_cast (const From &from) {
30
+ template <
31
+ typename To, typename From,
32
+ typename = cpp::enable_if_t <sizeof (To) == sizeof (From) &&
33
+ cpp::is_trivially_constructible<To>::value &&
34
+ cpp::is_trivially_copyable<To>::value &&
35
+ cpp::is_trivially_copyable<From>::value>>
36
+ LIBC_INLINE constexpr To bit_cast (const From &from) {
38
37
MSAN_UNPOISON (&from, sizeof (From));
39
38
#if LIBC_HAS_BUILTIN(__builtin_bit_cast)
40
39
return __builtin_bit_cast (To, from);
@@ -52,10 +51,8 @@ bit_cast(const From &from) {
52
51
#endif // LIBC_HAS_BUILTIN(__builtin_bit_cast)
53
52
}
54
53
55
- template <typename T>
56
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>,
57
- bool >
58
- has_single_bit (T value) {
54
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
55
+ [[nodiscard]] LIBC_INLINE constexpr bool has_single_bit (T value) {
59
56
return (value != 0 ) && ((value & (value - 1 )) == 0 );
60
57
}
61
58
@@ -73,9 +70,8 @@ has_single_bit(T value) {
73
70
// / Only unsigned integral types are allowed.
74
71
// /
75
72
// / Returns cpp::numeric_limits<T>::digits on an input of 0.
76
- template <typename T>
77
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
78
- countr_zero (T value) {
73
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
74
+ [[nodiscard]] LIBC_INLINE constexpr int countr_zero (T value) {
79
75
if (!value)
80
76
return cpp::numeric_limits<T>::digits;
81
77
if (value & 0x1 )
@@ -107,9 +103,8 @@ ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll)
107
103
// / Only unsigned integral types are allowed.
108
104
// /
109
105
// / Returns cpp::numeric_limits<T>::digits on an input of 0.
110
- template <typename T>
111
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
112
- countl_zero (T value) {
106
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
107
+ [[nodiscard]] LIBC_INLINE constexpr int countl_zero (T value) {
113
108
if (!value)
114
109
return cpp::numeric_limits<T>::digits;
115
110
// Bisection method.
@@ -140,9 +135,8 @@ ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll)
140
135
// / Only unsigned integral types are allowed.
141
136
// /
142
137
// / Returns cpp::numeric_limits<T>::digits on an input of all ones.
143
- template <typename T>
144
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
145
- countl_one (T value) {
138
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
139
+ [[nodiscard]] LIBC_INLINE constexpr int countl_one (T value) {
146
140
return cpp::countl_zero<T>(~value);
147
141
}
148
142
@@ -153,29 +147,26 @@ countl_one(T value) {
153
147
// / Only unsigned integral types are allowed.
154
148
// /
155
149
// / Returns cpp::numeric_limits<T>::digits on an input of all ones.
156
- template <typename T>
157
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
158
- countr_one (T value) {
150
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
151
+ [[nodiscard]] LIBC_INLINE constexpr int countr_one (T value) {
159
152
return cpp::countr_zero<T>(~value);
160
153
}
161
154
162
155
// / Returns the number of bits needed to represent value if value is nonzero.
163
156
// / Returns 0 otherwise.
164
157
// /
165
158
// / Ex. bit_width(5) == 3.
166
- template <typename T>
167
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
168
- bit_width (T value) {
159
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
160
+ [[nodiscard]] LIBC_INLINE constexpr int bit_width (T value) {
169
161
return cpp::numeric_limits<T>::digits - cpp::countl_zero (value);
170
162
}
171
163
172
164
// / Returns the largest integral power of two no greater than value if value is
173
165
// / nonzero. Returns 0 otherwise.
174
166
// /
175
167
// / Ex. bit_floor(5) == 4.
176
- template <typename T>
177
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, T>
178
- bit_floor (T value) {
168
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
169
+ [[nodiscard]] LIBC_INLINE constexpr T bit_floor (T value) {
179
170
if (!value)
180
171
return 0 ;
181
172
return T (1 ) << (cpp::bit_width (value) - 1 );
@@ -188,9 +179,8 @@ bit_floor(T value) {
188
179
// /
189
180
// / The return value is undefined if the input is larger than the largest power
190
181
// / of two representable in T.
191
- template <typename T>
192
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, T>
193
- bit_ceil (T value) {
182
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
183
+ [[nodiscard]] LIBC_INLINE constexpr T bit_ceil (T value) {
194
184
if (value < 2 )
195
185
return 1 ;
196
186
return T (1 ) << cpp::bit_width<T>(value - 1u );
@@ -200,31 +190,28 @@ bit_ceil(T value) {
200
190
// from https://blog.regehr.org/archives/1063.
201
191
202
192
// Forward-declare rotr so that rotl can use it.
203
- template <typename T>
204
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, T>
205
- rotr (T value, int rotate);
193
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
194
+ [[nodiscard]] LIBC_INLINE constexpr T rotr (T value, int rotate);
206
195
207
- template <typename T>
208
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, T>
209
- rotl (T value, int rotate) {
196
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
197
+ [[nodiscard]] LIBC_INLINE constexpr T rotl (T value, int rotate) {
210
198
constexpr unsigned N = cpp::numeric_limits<T>::digits;
211
199
rotate = rotate % N;
212
200
if (!rotate)
213
201
return value;
214
202
if (rotate < 0 )
215
- return cpp::rotr<T> (value, -rotate);
203
+ return cpp::rotr (value, -rotate);
216
204
return (value << rotate) | (value >> (N - rotate));
217
205
}
218
206
219
- template <typename T>
220
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, T>
221
- rotr (T value, int rotate) {
207
+ template <typename T, typename >
208
+ [[nodiscard]] LIBC_INLINE constexpr T rotr (T value, int rotate) {
222
209
constexpr unsigned N = cpp::numeric_limits<T>::digits;
223
210
rotate = rotate % N;
224
211
if (!rotate)
225
212
return value;
226
213
if (rotate < 0 )
227
- return cpp::rotl<T> (value, -rotate);
214
+ return cpp::rotl (value, -rotate);
228
215
return (value >> rotate) | (value << (N - rotate));
229
216
}
230
217
@@ -239,44 +226,33 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) {
239
226
}
240
227
}
241
228
242
- // TODO: remove from 'bit.h' as it is not a standard function.
243
- template <typename T>
244
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
245
- first_leading_zero (T value) {
229
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
230
+ [[nodiscard]] LIBC_INLINE constexpr int first_leading_zero (T value) {
246
231
return value == cpp::numeric_limits<T>::max () ? 0 : countl_one (value) + 1 ;
247
232
}
248
233
249
- // TODO: remove from 'bit.h' as it is not a standard function.
250
- template <typename T>
251
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
252
- first_leading_one (T value) {
234
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
235
+ [[nodiscard]] LIBC_INLINE constexpr int first_leading_one (T value) {
253
236
return first_leading_zero (static_cast <T>(~value));
254
237
}
255
238
256
- // TODO: remove from 'bit.h' as it is not a standard function.
257
- template <typename T>
258
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
259
- first_trailing_zero (T value) {
239
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
240
+ [[nodiscard]] LIBC_INLINE constexpr int first_trailing_zero (T value) {
260
241
return value == cpp::numeric_limits<T>::max ()
261
242
? 0
262
243
: countr_zero (static_cast <T>(~value)) + 1 ;
263
244
}
264
245
265
- // TODO: remove from 'bit.h' as it is not a standard function.
266
- template <typename T>
267
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
268
- first_trailing_one (T value) {
246
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
247
+ [[nodiscard]] LIBC_INLINE constexpr int first_trailing_one (T value) {
269
248
return value == cpp::numeric_limits<T>::max () ? 0 : countr_zero (value) + 1 ;
270
249
}
271
250
272
251
// / Count number of 1's aka population count or hamming weight.
273
252
// /
274
253
// / Only unsigned integral types are allowed.
275
- // TODO: rename as 'popcount' to follow the standard
276
- // https://en.cppreference.com/w/cpp/numeric/popcount
277
- template <typename T>
278
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
279
- count_ones (T value) {
254
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
255
+ [[nodiscard]] LIBC_INLINE constexpr int count_ones (T value) {
280
256
int count = 0 ;
281
257
for (int i = 0 ; i != cpp::numeric_limits<T>::digits; ++i)
282
258
if ((value >> i) & 0x1 )
@@ -296,10 +272,8 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll)
296
272
// TODO: 128b specializations?
297
273
#undef ADD_SPECIALIZATION
298
274
299
- // TODO: remove from 'bit.h' as it is not a standard function.
300
- template <typename T>
301
- [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_unsigned_v<T>, int >
302
- count_zeros (T value) {
275
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
276
+ [[nodiscard]] LIBC_INLINE constexpr int count_zeros (T value) {
303
277
return count_ones<T>(static_cast <T>(~value));
304
278
}
305
279
0 commit comments