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