Skip to content

Commit a250c1b

Browse files
committed
Refactor
1 parent fefda16 commit a250c1b

File tree

6 files changed

+51
-44
lines changed

6 files changed

+51
-44
lines changed

libcxx/include/__algorithm/find.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ __find_bool(__bit_iterator<_Cp, _IsConst> __first, typename __size_difference_ty
106106
if (__first.__ctz_ != 0) {
107107
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
108108
__storage_type __dn = std::min(__clz_f, __n);
109-
__storage_type __m = std::__middle_mask<__storage_type>(__first.__ctz_, __clz_f - __dn);
109+
__storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_);
110110
__storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_) & __m;
111111
if (__b)
112112
return _It(__first.__seg_, static_cast<unsigned>(std::__countr_zero(__b)));

libcxx/include/__bit/countr.h

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,73 +40,63 @@ _LIBCPP_BEGIN_NAMESPACE_STD
4040
return __builtin_ctzll(__x);
4141
}
4242

43-
#if _LIBCPP_STD_VER >= 17
44-
// Implementation using constexpr if for C++ standards >= 17
43+
#ifndef _LIBCPP_CXX03_LANG
44+
// constexpr implementation for C++11 and later
4545

46-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero, which handles __t == 0 as a special case)
47-
template <class _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
48-
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int __countr_zero_impl(_Tp __t) _NOEXCEPT {
46+
// Precondition: __t != 0 (the caller __countr_zero handles __t == 0 as a special case)
47+
template <class _Tp>
48+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr int __countr_zero_impl(_Tp __t) _NOEXCEPT {
49+
static_assert(is_unsigned<_Tp>::value, "__countr_zero_impl only works with unsigned types");
4950
if constexpr (sizeof(_Tp) <= sizeof(unsigned int)) {
5051
return std::__libcpp_ctz(static_cast<unsigned int>(__t));
5152
} else if constexpr (sizeof(_Tp) <= sizeof(unsigned long)) {
5253
return std::__libcpp_ctz(static_cast<unsigned long>(__t));
5354
} else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) {
5455
return std::__libcpp_ctz(static_cast<unsigned long long>(__t));
5556
} else {
57+
# if _LIBCPP_STD_VER == 11
58+
// A recursive constexpr implementation for C++11
59+
unsigned long long __ull = static_cast<unsigned long long>(__t);
60+
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
61+
return __ull == 0ull ? __ulldigits + std::__countr_zero_impl<_Tp>(__t >> __ulldigits) : std::__libcpp_ctz(__ull);
62+
# else
5663
int __ret = 0;
5764
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
5865
while (static_cast<unsigned long long>(__t) == 0uLL) {
5966
__ret += __ulldigits;
6067
__t >>= __ulldigits;
6168
}
6269
return __ret + std::__libcpp_ctz(static_cast<unsigned long long>(__t));
70+
# endif
6371
}
6472
}
6573

6674
#else
67-
// Equivalent SFINAE-based implementation for older C++ standards < 17
75+
// implementation for C++03
6876

69-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero, which handles __t == 0 as a special case)
7077
template < class _Tp, __enable_if_t<is_unsigned<_Tp>::value && sizeof(_Tp) <= sizeof(unsigned int), int> = 0>
71-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero_impl(_Tp __t) _NOEXCEPT {
78+
_LIBCPP_HIDE_FROM_ABI int __countr_zero_impl(_Tp __t) {
7279
return std::__libcpp_ctz(static_cast<unsigned int>(__t));
7380
}
7481

75-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero)
7682
template < class _Tp,
7783
__enable_if_t<is_unsigned<_Tp>::value && (sizeof(_Tp) > sizeof(unsigned int)) &&
7884
sizeof(_Tp) <= sizeof(unsigned long),
7985
int> = 0 >
80-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero_impl(_Tp __t) _NOEXCEPT {
86+
_LIBCPP_HIDE_FROM_ABI int __countr_zero_impl(_Tp __t) {
8187
return std::__libcpp_ctz(static_cast<unsigned long>(__t));
8288
}
8389

84-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero)
8590
template < class _Tp,
8691
__enable_if_t<is_unsigned<_Tp>::value && (sizeof(_Tp) > sizeof(unsigned long)) &&
8792
sizeof(_Tp) <= sizeof(unsigned long long),
8893
int> = 0 >
89-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero_impl(_Tp __t) _NOEXCEPT {
94+
_LIBCPP_HIDE_FROM_ABI int __countr_zero_impl(_Tp __t) {
9095
return std::__libcpp_ctz(static_cast<unsigned long long>(__t));
9196
}
9297

93-
# if _LIBCPP_STD_VER == 11
94-
95-
// Recursive constexpr implementation for C++11 due to limited constexpr support
96-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero)
97-
template < class _Tp, __enable_if_t<is_unsigned<_Tp>::value && (sizeof(_Tp) > sizeof(unsigned long long)), int> = 0 >
98-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero_impl(_Tp __t) _NOEXCEPT {
99-
unsigned long long __ull = static_cast<unsigned long long>(__t);
100-
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
101-
return __ull == 0ull ? __ulldigits + std::__countr_zero_impl<_Tp>(__t >> __ulldigits) : std::__libcpp_ctz(__ull);
102-
}
103-
104-
# else
105-
106-
// Loop-based constexpr implementation for C++14 (and non-constexpr for C++03, 98)
107-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero)
10898
template < class _Tp, __enable_if_t<is_unsigned<_Tp>::value && (sizeof(_Tp) > sizeof(unsigned long long)), int> = 0 >
109-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countr_zero_impl(_Tp __t) _NOEXCEPT {
99+
_LIBCPP_HIDE_FROM_ABI int __countr_zero_impl(_Tp __t) {
110100
int __ret = 0;
111101
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
112102
while (static_cast<unsigned long long>(__t) == 0uLL) {
@@ -116,16 +106,15 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countr_zero_impl(_Tp _
116106
return __ret + std::__libcpp_ctz(static_cast<unsigned long long>(__t));
117107
}
118108

119-
# endif // _LIBCPP_STD_VER == 11
120-
121-
#endif // _LIBCPP_STD_VER >= 17
109+
#endif // _LIBCPP_CXX03_LANG
122110

123-
template <class _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
111+
template <class _Tp>
124112
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero(_Tp __t) _NOEXCEPT {
113+
static_assert(is_unsigned<_Tp>::value, "__countr_zero only works with unsigned types");
125114
#if __has_builtin(__builtin_ctzg)
126115
return __builtin_ctzg(__t, numeric_limits<_Tp>::digits);
127116
#else
128-
return __t != 0 ? __countr_zero_impl(__t) : numeric_limits<_Tp>::digits;
117+
return __t != 0 ? std::__countr_zero_impl(__t) : numeric_limits<_Tp>::digits;
129118
#endif
130119
}
131120

libcxx/include/__bit_reference

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <__algorithm/min.h>
1919
#include <__assert>
2020
#include <__bit/countr.h>
21+
#include <__bit/invert_if.h>
2122
#include <__compare/ordering.h>
2223
#include <__config>
2324
#include <__cstddef/ptrdiff_t.h>
@@ -67,6 +68,20 @@ struct __size_difference_type_traits<_Cp, __void_t<typename _Cp::difference_type
6768
using size_type = typename _Cp::size_type;
6869
};
6970

71+
template <class _StorageType>
72+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __trailing_mask(unsigned __clz) {
73+
static_assert(is_unsigned<_StorageType>::value, "__trailing_mask only works with unsigned types");
74+
return static_cast<_StorageType>(static_cast<_StorageType>(~static_cast<_StorageType>(0)) >> __clz);
75+
}
76+
77+
template <class _StorageType>
78+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __middle_mask(unsigned __clz, unsigned __ctz) {
79+
static_assert(is_unsigned<_StorageType>::value, "__middle_mask only works with unsigned types");
80+
return static_cast<_StorageType>(
81+
static_cast<_StorageType>(static_cast<_StorageType>(~static_cast<_StorageType>(0)) << __ctz) &
82+
std::__trailing_mask<_StorageType>(__clz));
83+
}
84+
7085
// This function is designed to operate correctly even for smaller integral types like `uint8_t`, `uint16_t`,
7186
// or `unsigned short`. Casting back to _StorageType is crucial to prevent undefined behavior that can arise
7287
// from integral promotions.

libcxx/include/__fwd/bit_reference.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
#define _LIBCPP___FWD_BIT_REFERENCE_H
1111

1212
#include <__config>
13-
#include <__memory/pointer_traits.h>
14-
#include <__type_traits/enable_if.h>
15-
#include <__type_traits/is_unsigned.h>
1613

1714
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1815
# pragma GCC system_header
@@ -30,6 +27,12 @@ template <class _StoragePointer>
3027
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
3128
__fill_masked_range(_StoragePointer __word, unsigned __ctz, unsigned __clz, bool __fill_val);
3229

30+
template <class _StorageType>
31+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __trailing_mask(unsigned __clz);
32+
33+
template <class _StorageType>
34+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __middle_mask(unsigned __clz, unsigned __ctz);
35+
3336
_LIBCPP_END_NAMESPACE_STD
3437

3538
#endif // _LIBCPP___FWD_BIT_REFERENCE_H

libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ struct TestIntegerPromotions {
211211
}
212212
};
213213

214-
TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
214+
TEST_CONSTEXPR_CXX20 void test_bit_iterator_with_custom_sized_types() {
215215
{
216216
using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
217217
std::vector<bool, Alloc> in(100, false, Alloc(1));
@@ -220,7 +220,7 @@ TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
220220
}
221221
{
222222
using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
223-
std::vector<bool, Alloc> in(200, false, Alloc(1));
223+
std::vector<bool, Alloc> in(199, false, Alloc(1));
224224
in[in.size() - 2] = true;
225225
assert(std::find(in.begin(), in.end(), true) == in.end() - 2);
226226
}
@@ -232,7 +232,7 @@ TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
232232
}
233233
{
234234
using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
235-
std::vector<bool, Alloc> in(200, false, Alloc(1));
235+
std::vector<bool, Alloc> in(257, false, Alloc(1));
236236
in[in.size() - 2] = true;
237237
assert(std::find(in.begin(), in.end(), true) == in.end() - 2);
238238
}
@@ -256,7 +256,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
256256
#endif
257257

258258
types::for_each(types::integral_types(), TestIntegerPromotions());
259-
test_bititer_with_custom_sized_types();
259+
test_bit_iterator_with_custom_sized_types();
260260

261261
{ // Test vector<bool>::iterator optimization
262262
std::vector<bool> vec(256 + 8);

libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class TriviallyComparable {
124124
bool operator==(const TriviallyComparable&) const = default;
125125
};
126126

127-
constexpr void test_bititer_with_custom_sized_types() {
127+
constexpr void test_bit_iterator_with_custom_sized_types() {
128128
{
129129
using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
130130
std::vector<bool, Alloc> in(100, false, Alloc(1));
@@ -133,7 +133,7 @@ constexpr void test_bititer_with_custom_sized_types() {
133133
}
134134
{
135135
using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
136-
std::vector<bool, Alloc> in(200, false, Alloc(1));
136+
std::vector<bool, Alloc> in(199, false, Alloc(1));
137137
in[in.size() - 2] = true;
138138
assert(std::ranges::find(in, true) == in.end() - 2);
139139
}
@@ -145,7 +145,7 @@ constexpr void test_bititer_with_custom_sized_types() {
145145
}
146146
{
147147
using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
148-
std::vector<bool, Alloc> in(200, false, Alloc(1));
148+
std::vector<bool, Alloc> in(257, false, Alloc(1));
149149
in[in.size() - 2] = true;
150150
assert(std::ranges::find(in, true) == in.end() - 2);
151151
}

0 commit comments

Comments
 (0)