Skip to content

Commit 71a1599

Browse files
committed
implement faster count_ones count_zeros, add documentation
1 parent ccabea0 commit 71a1599

File tree

1 file changed

+10
-9
lines changed

1 file changed

+10
-9
lines changed

libc/src/__support/UInt.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,15 +1000,15 @@ countl_zero(const T &value) {
10001000
template <typename T>
10011001
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int>
10021002
countl_one(T value) {
1003-
// TODO : Implement a faster version.
1003+
// TODO : Implement a faster version not involving operator~.
10041004
return cpp::countl_zero<T>(~value);
10051005
}
10061006

10071007
// Specialization of cpp::countr_one ('bit.h') for BigInt.
10081008
template <typename T>
10091009
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int>
10101010
countr_one(T value) {
1011-
// TODO : Implement a faster version.
1011+
// TODO : Implement a faster version not involving operator~.
10121012
return cpp::countr_zero<T>(~value);
10131013
}
10141014

@@ -1028,7 +1028,6 @@ rotr(T value, int rotate);
10281028
template <typename T>
10291029
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, T>
10301030
rotl(T value, int rotate) {
1031-
// TODO : Implement a faster version.
10321031
constexpr unsigned N = cpp::numeric_limits<T>::digits;
10331032
rotate = rotate % N;
10341033
if (!rotate)
@@ -1042,7 +1041,6 @@ rotl(T value, int rotate) {
10421041
template <typename T>
10431042
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, T>
10441043
rotr(T value, int rotate) {
1045-
// TODO : Implement a faster version.
10461044
constexpr unsigned N = cpp::numeric_limits<T>::digits;
10471045
rotate = rotate % N;
10481046
if (!rotate)
@@ -1063,13 +1061,15 @@ first_leading_zero(T value) {
10631061
template <typename T>
10641062
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int>
10651063
first_leading_one(T value) {
1064+
// TODO : Implement a faster version not involving operator~.
10661065
return first_leading_zero(static_cast<T>(~value));
10671066
}
10681067

10691068
// Specialization of cpp::first_trailing_zero ('bit.h') for BigInt.
10701069
template <typename T>
10711070
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int>
10721071
first_trailing_zero(T value) {
1072+
// TODO : Implement a faster version not involving operator~.
10731073
return value == cpp::numeric_limits<T>::max()
10741074
? 0
10751075
: countr_zero(static_cast<T>(~value)) + 1;
@@ -1086,19 +1086,20 @@ first_trailing_one(T value) {
10861086
template <typename T>
10871087
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int>
10881088
count_ones(T value) {
1089-
// TODO : Implement a faster version.
10901089
int count = 0;
1091-
for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i)
1092-
if ((value >> i) & 0x1)
1093-
++count;
1090+
for (auto word : value.val)
1091+
count += count_ones(word);
10941092
return count;
10951093
}
10961094

10971095
// Specialization of cpp::count_zeros ('bit.h') for BigInt.
10981096
template <typename T>
10991097
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int>
11001098
count_zeros(T value) {
1101-
return count_ones<T>(static_cast<T>(~value));
1099+
int count = 0;
1100+
for (auto word : value.val)
1101+
count += count_zeros(word);
1102+
return count;
11021103
}
11031104

11041105
} // namespace LIBC_NAMESPACE::cpp

0 commit comments

Comments
 (0)