Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions libc/src/__support/big_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -1383,8 +1383,9 @@ first_trailing_zero(T value) {
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
first_trailing_one(T value) {
return value == cpp::numeric_limits<T>::max() ? 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be just value == 0. When value is not 0, cpp::countr_zero(value) + 1 should be correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will fail with inputs like USHRT_MAX because we need it to return 0, but cpp::countr_zero(USHRT_MAX) + 1 = 1.

: cpp::countr_zero(value) + 1;
return (value == 0 || value == cpp::numeric_limits<T>::max())
? 0
: cpp::countr_zero(value) + 1;
}

} // namespace LIBC_NAMESPACE_DECL
Expand Down
5 changes: 3 additions & 2 deletions libc/src/__support/math_extras.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,9 @@ first_trailing_zero(T value) {
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
first_trailing_one(T value) {
return value == cpp::numeric_limits<T>::max() ? 0
: cpp::countr_zero(value) + 1;
return (value == 0 || value == cpp::numeric_limits<T>::max())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be just value == 0, the other case is cpp::countr_zero(value) + 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will fail with inputs like USHRT_MAX because we need it to return 0, but cpp::countr_zero(USHRT_MAX) + 1 = 1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should it return 0 with USHRT_MAX? The least significant index of the first bit 1 of USHRT_MAX is 0, so according to the spec, stdc_first_trailing_one_us(USHRT_MAX) should be 1. Hence cpp::countr_zero(USHRT_MAX) + 1 is the correct. If our tests do not reflect that, then the tests also need to be updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it finally. Sorry for being careless. I'll update this tonight.

? 0
: cpp::countr_zero(value) + 1;
}

template <typename T>
Expand Down
1 change: 1 addition & 0 deletions libc/test/src/__support/math_extras_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypesNoBigInt) {
}

TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypesNoBigInt) {
EXPECT_EQ(first_trailing_one<T>(static_cast<T>(0)), 0);
EXPECT_EQ(first_trailing_one<T>(cpp::numeric_limits<T>::max()), 0);
for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) {
auto lhs = T(T(1) << size_t(i));
Expand Down
Loading