Skip to content

Commit d78ca73

Browse files
Delta-dev-99ldionne
andcommitted
[libc++] Fix the rotate direction used in countl_zero()
This "bug" was probably not noticed because it doesn't affect any integer type we currently support. It requires integers with more than 2x the size of `unsigned long long`. However, with such types, the algorithm used to break down the large integer into groups of size `unsigned long long` didn't work because we rotated in the wrong direction. For example, the 256 bit number (1 << 255) would yield the wrong answer when used with the algorithm before this patch. In particular, note that the current rotation happens to work for 128 bit integers because it just swaps the halves in this case. Differential Revision: https://reviews.llvm.org/D134625 Co-authored-by: Louis Dionne <[email protected]>
1 parent da81b1b commit d78ca73

File tree

2 files changed

+7
-2
lines changed

2 files changed

+7
-2
lines changed

libcxx/include/__bit/countl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ int __countl_zero(_Tp __t) _NOEXCEPT
7474
int __iter = 0;
7575
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
7676
while (true) {
77-
__t = std::__rotr(__t, __ulldigits);
77+
__t = std::__rotl(__t, __ulldigits);
7878
if ((__iter = std::__countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits)
7979
break;
8080
__ret += __iter;

libcxx/include/__bit/rotate.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,16 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotr(_Tp __t, int __cn
3535
return (__t >> (__cnt % __dig)) | (__t << (__dig - (__cnt % __dig)));
3636
}
3737

38+
template <class _Tp>
39+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotl(_Tp __t, int __cnt) _NOEXCEPT {
40+
return std::__rotr(__t, -__cnt);
41+
}
42+
3843
#if _LIBCPP_STD_VER >= 20
3944

4045
template <__libcpp_unsigned_integer _Tp>
4146
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, int __cnt) noexcept {
42-
return std::__rotr(__t, -__cnt);
47+
return std::__rotl(__t, __cnt);
4348
}
4449

4550
template <__libcpp_unsigned_integer _Tp>

0 commit comments

Comments
 (0)