Skip to content

Commit 27844cb

Browse files
authored
1 parent 84f483d commit 27844cb

File tree

12 files changed

+125
-272
lines changed

12 files changed

+125
-272
lines changed

libc/src/__support/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ add_header_library(
9595
HDRS
9696
integer_to_string.h
9797
DEPENDS
98-
.uint
9998
libc.src.__support.common
10099
libc.src.__support.CPP.algorithm
101100
libc.src.__support.CPP.limits

libc/src/__support/CPP/bit.h

Lines changed: 43 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,13 @@ namespace LIBC_NAMESPACE::cpp {
2727

2828
// This implementation of bit_cast requires trivially-constructible To, to avoid
2929
// 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) {
3837
MSAN_UNPOISON(&from, sizeof(From));
3938
#if LIBC_HAS_BUILTIN(__builtin_bit_cast)
4039
return __builtin_bit_cast(To, from);
@@ -52,10 +51,8 @@ bit_cast(const From &from) {
5251
#endif // LIBC_HAS_BUILTIN(__builtin_bit_cast)
5352
}
5453

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) {
5956
return (value != 0) && ((value & (value - 1)) == 0);
6057
}
6158

@@ -73,9 +70,8 @@ has_single_bit(T value) {
7370
/// Only unsigned integral types are allowed.
7471
///
7572
/// 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) {
7975
if (!value)
8076
return cpp::numeric_limits<T>::digits;
8177
if (value & 0x1)
@@ -107,9 +103,8 @@ ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll)
107103
/// Only unsigned integral types are allowed.
108104
///
109105
/// 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) {
113108
if (!value)
114109
return cpp::numeric_limits<T>::digits;
115110
// Bisection method.
@@ -140,9 +135,8 @@ ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll)
140135
/// Only unsigned integral types are allowed.
141136
///
142137
/// 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) {
146140
return cpp::countl_zero<T>(~value);
147141
}
148142

@@ -153,29 +147,26 @@ countl_one(T value) {
153147
/// Only unsigned integral types are allowed.
154148
///
155149
/// 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) {
159152
return cpp::countr_zero<T>(~value);
160153
}
161154

162155
/// Returns the number of bits needed to represent value if value is nonzero.
163156
/// Returns 0 otherwise.
164157
///
165158
/// 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) {
169161
return cpp::numeric_limits<T>::digits - cpp::countl_zero(value);
170162
}
171163

172164
/// Returns the largest integral power of two no greater than value if value is
173165
/// nonzero. Returns 0 otherwise.
174166
///
175167
/// 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) {
179170
if (!value)
180171
return 0;
181172
return T(1) << (cpp::bit_width(value) - 1);
@@ -188,9 +179,8 @@ bit_floor(T value) {
188179
///
189180
/// The return value is undefined if the input is larger than the largest power
190181
/// 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) {
194184
if (value < 2)
195185
return 1;
196186
return T(1) << cpp::bit_width<T>(value - 1u);
@@ -200,31 +190,28 @@ bit_ceil(T value) {
200190
// from https://blog.regehr.org/archives/1063.
201191

202192
// 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);
206195

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) {
210198
constexpr unsigned N = cpp::numeric_limits<T>::digits;
211199
rotate = rotate % N;
212200
if (!rotate)
213201
return value;
214202
if (rotate < 0)
215-
return cpp::rotr<T>(value, -rotate);
203+
return cpp::rotr(value, -rotate);
216204
return (value << rotate) | (value >> (N - rotate));
217205
}
218206

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) {
222209
constexpr unsigned N = cpp::numeric_limits<T>::digits;
223210
rotate = rotate % N;
224211
if (!rotate)
225212
return value;
226213
if (rotate < 0)
227-
return cpp::rotl<T>(value, -rotate);
214+
return cpp::rotl(value, -rotate);
228215
return (value >> rotate) | (value << (N - rotate));
229216
}
230217

@@ -239,44 +226,33 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) {
239226
}
240227
}
241228

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) {
246231
return value == cpp::numeric_limits<T>::max() ? 0 : countl_one(value) + 1;
247232
}
248233

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) {
253236
return first_leading_zero(static_cast<T>(~value));
254237
}
255238

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) {
260241
return value == cpp::numeric_limits<T>::max()
261242
? 0
262243
: countr_zero(static_cast<T>(~value)) + 1;
263244
}
264245

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) {
269248
return value == cpp::numeric_limits<T>::max() ? 0 : countr_zero(value) + 1;
270249
}
271250

272251
/// Count number of 1's aka population count or hamming weight.
273252
///
274253
/// 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) {
280256
int count = 0;
281257
for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i)
282258
if ((value >> i) & 0x1)
@@ -296,10 +272,8 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll)
296272
// TODO: 128b specializations?
297273
#undef ADD_SPECIALIZATION
298274

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) {
303277
return count_ones<T>(static_cast<T>(~value));
304278
}
305279

0 commit comments

Comments
 (0)