Skip to content

Commit c5c8107

Browse files
committed
Refactor
1 parent ff2d216 commit c5c8107

File tree

6 files changed

+64
-45
lines changed

6 files changed

+64
-45
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: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,25 @@ _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)
46+
// Precondition: __t != 0 (the caller __countr_zero handles __t == 0 as a special case)
4747
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 {
48+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr int __countr_zero_impl(_Tp __t) _NOEXCEPT {
4949
if constexpr (sizeof(_Tp) <= sizeof(unsigned int)) {
5050
return std::__libcpp_ctz(static_cast<unsigned int>(__t));
5151
} else if constexpr (sizeof(_Tp) <= sizeof(unsigned long)) {
5252
return std::__libcpp_ctz(static_cast<unsigned long>(__t));
5353
} else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) {
5454
return std::__libcpp_ctz(static_cast<unsigned long long>(__t));
5555
} else {
56+
# if _LIBCPP_STD_VER == 11
57+
// A recursive constexpr implementation for C++11
58+
unsigned long long __ull = static_cast<unsigned long long>(__t);
59+
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
60+
return __ull == 0ull ? __ulldigits + std::__countr_zero_impl<_Tp>(__t >> __ulldigits) : std::__libcpp_ctz(__ull);
61+
# else
5662
int __ret = 0;
5763
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
5864
while (static_cast<unsigned long long>(__t) == 0uLL) {
@@ -61,52 +67,35 @@ template <class _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
6167
}
6268
return __ret + std::__libcpp_ctz(static_cast<unsigned long long>(__t));
6369
}
70+
#endif // _LIBCPP_STD_VER == 11
6471
}
6572

6673
#else
67-
// Equivalent SFINAE-based implementation for older C++ standards < 17
74+
// Equivalent implementation using SFINAE-based overloading for C++03
6875

69-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero, which handles __t == 0 as a special case)
7076
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 {
77+
_LIBCPP_HIDE_FROM_ABI int __countr_zero_impl(_Tp __t) _NOEXCEPT {
7278
return std::__libcpp_ctz(static_cast<unsigned int>(__t));
7379
}
7480

75-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero)
7681
template < class _Tp,
7782
__enable_if_t<is_unsigned<_Tp>::value && (sizeof(_Tp) > sizeof(unsigned int)) &&
7883
sizeof(_Tp) <= sizeof(unsigned long),
7984
int> = 0 >
80-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero_impl(_Tp __t) _NOEXCEPT {
85+
_LIBCPP_HIDE_FROM_ABI int __countr_zero_impl(_Tp __t) _NOEXCEPT {
8186
return std::__libcpp_ctz(static_cast<unsigned long>(__t));
8287
}
8388

84-
// Precondition: __t != 0 (This is guaranteed by the caller __countr_zero)
8589
template < class _Tp,
8690
__enable_if_t<is_unsigned<_Tp>::value && (sizeof(_Tp) > sizeof(unsigned long)) &&
8791
sizeof(_Tp) <= sizeof(unsigned long long),
8892
int> = 0 >
89-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero_impl(_Tp __t) _NOEXCEPT {
93+
_LIBCPP_HIDE_FROM_ABI int __countr_zero_impl(_Tp __t) _NOEXCEPT {
9094
return std::__libcpp_ctz(static_cast<unsigned long long>(__t));
9195
}
9296

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)
10897
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 {
98+
_LIBCPP_HIDE_FROM_ABI int __countr_zero_impl(_Tp __t) _NOEXCEPT {
11099
int __ret = 0;
111100
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
112101
while (static_cast<unsigned long long>(__t) == 0uLL) {
@@ -116,16 +105,14 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countr_zero_impl(_Tp _
116105
return __ret + std::__libcpp_ctz(static_cast<unsigned long long>(__t));
117106
}
118107

119-
# endif // _LIBCPP_STD_VER == 11
120-
121-
#endif // _LIBCPP_STD_VER >= 17
108+
#endif // _LIBCPP_CXX03_LANG
122109

123110
template <class _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
124111
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero(_Tp __t) _NOEXCEPT {
125112
#if __has_builtin(__builtin_ctzg)
126113
return __builtin_ctzg(__t, numeric_limits<_Tp>::digits);
127114
#else
128-
return __t != 0 ? __countr_zero_impl(__t) : numeric_limits<_Tp>::digits;
115+
return __t != 0 ? std::__countr_zero_impl(__t) : numeric_limits<_Tp>::digits;
129116
#endif
130117
}
131118

libcxx/include/__bit_reference

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
#include <__algorithm/copy_backward.h>
1515
#include <__algorithm/copy_n.h>
1616
#include <__algorithm/min.h>
17+
#include <__assert>
1718
#include <__bit/countr.h>
19+
#include <__bit/invert_if.h>
1820
#include <__compare/ordering.h>
1921
#include <__config>
2022
#include <__cstddef/ptrdiff_t.h>
@@ -25,9 +27,11 @@
2527
#include <__memory/pointer_traits.h>
2628
#include <__type_traits/conditional.h>
2729
#include <__type_traits/is_constant_evaluated.h>
30+
#include <__type_traits/is_unsigned.h>
2831
#include <__type_traits/void_t.h>
2932
#include <__utility/pair.h>
3033
#include <__utility/swap.h>
34+
#include <climits>
3135

3236
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
3337
# pragma GCC system_header
@@ -58,6 +62,34 @@ struct __size_difference_type_traits<_Cp, __void_t<typename _Cp::difference_type
5862
using size_type = typename _Cp::size_type;
5963
};
6064

65+
template <class _StorageType>
66+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __trailing_mask(unsigned __clz) {
67+
static_assert(is_unsigned<_StorageType>::value, "__trailing_mask only works with unsigned types");
68+
return static_cast<_StorageType>(static_cast<_StorageType>(~static_cast<_StorageType>(0)) >> __clz);
69+
}
70+
71+
template <class _StorageType>
72+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __middle_mask(unsigned __clz, unsigned __ctz) {
73+
static_assert(is_unsigned<_StorageType>::value, "__middle_mask only works with unsigned types");
74+
return static_cast<_StorageType>(
75+
static_cast<_StorageType>(static_cast<_StorageType>(~static_cast<_StorageType>(0)) << __ctz) &
76+
std::__trailing_mask<_StorageType>(__clz));
77+
}
78+
79+
template <bool _ToFind, class _StoragePointer>
80+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unsigned
81+
__find_in_masked_range(_StoragePointer __word, unsigned __clz, unsigned __ctz) {
82+
static_assert(is_unsigned<typename pointer_traits<_StoragePointer>::element_type>::value,
83+
"__find_in_masked_range must be called with unsigned types");
84+
using _StorageType = typename pointer_traits<_StoragePointer>::element_type;
85+
_LIBCPP_ASSERT_VALID_INPUT_RANGE(
86+
__ctz + __clz < sizeof(_StorageType) * CHAR_BIT, "__find_in_masked_range called with invalid range");
87+
_StorageType __m = static_cast<_StorageType>(static_cast<_StorageType>(~static_cast<_StorageType>(0)) >> __clz) &
88+
static_cast<_StorageType>(static_cast<_StorageType>(~static_cast<_StorageType>(0)) << __ctz);
89+
_StorageType __b = std::__invert_if<!_ToFind>(*__word) & __m;
90+
return static_cast<unsigned>(std::__countr_zero(__b));
91+
}
92+
6193
template <class _Cp, bool = __has_storage_type<_Cp>::value>
6294
class __bit_reference {
6395
using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type;

libcxx/include/__fwd/bit_reference.h

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

1212
#include <__config>
13-
#include <__type_traits/enable_if.h>
14-
#include <__type_traits/is_unsigned.h>
1513

1614
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1715
# pragma GCC system_header
@@ -25,9 +23,11 @@ class __bit_iterator;
2523
template <class, class = void>
2624
struct __size_difference_type_traits;
2725

28-
template <class _StorageType, __enable_if_t<is_unsigned<_StorageType>::value, int> = 0>
29-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _StorageType
30-
__find_in_masked_range(_StorageType __word, unsigned __ctz, unsigned __clz, bool __find_val);
26+
template <class _StorageType>
27+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __trailing_mask(unsigned __clz);
28+
29+
template <class _StorageType>
30+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __middle_mask(unsigned __clz, unsigned __ctz);
3131

3232
_LIBCPP_END_NAMESPACE_STD
3333

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
@@ -208,7 +208,7 @@ struct TestIntegerPromotions {
208208
}
209209
};
210210

211-
TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
211+
TEST_CONSTEXPR_CXX20 void test_bit_iterator_with_custom_sized_types() {
212212
{
213213
using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
214214
std::vector<bool, Alloc> in(100, false, Alloc(1));
@@ -217,7 +217,7 @@ TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
217217
}
218218
{
219219
using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
220-
std::vector<bool, Alloc> in(200, false, Alloc(1));
220+
std::vector<bool, Alloc> in(199, false, Alloc(1));
221221
in[in.size() - 2] = true;
222222
assert(std::find(in.begin(), in.end(), true) == in.end() - 2);
223223
}
@@ -229,7 +229,7 @@ TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
229229
}
230230
{
231231
using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
232-
std::vector<bool, Alloc> in(200, false, Alloc(1));
232+
std::vector<bool, Alloc> in(257, false, Alloc(1));
233233
in[in.size() - 2] = true;
234234
assert(std::find(in.begin(), in.end(), true) == in.end() - 2);
235235
}
@@ -255,7 +255,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
255255
#endif
256256

257257
types::for_each(types::integral_types(), TestIntegerPromotions());
258-
test_bititer_with_custom_sized_types();
258+
test_bit_iterator_with_custom_sized_types();
259259

260260
return true;
261261
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ class TriviallyComparable {
121121
bool operator==(const TriviallyComparable&) const = default;
122122
};
123123

124-
constexpr void test_bititer_with_custom_sized_types() {
124+
constexpr void test_bit_iterator_with_custom_sized_types() {
125125
{
126126
using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
127127
std::vector<bool, Alloc> in(100, false, Alloc(1));
@@ -130,7 +130,7 @@ constexpr void test_bititer_with_custom_sized_types() {
130130
}
131131
{
132132
using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
133-
std::vector<bool, Alloc> in(200, false, Alloc(1));
133+
std::vector<bool, Alloc> in(199, false, Alloc(1));
134134
in[in.size() - 2] = true;
135135
assert(std::ranges::find(in, true) == in.end() - 2);
136136
}
@@ -142,7 +142,7 @@ constexpr void test_bititer_with_custom_sized_types() {
142142
}
143143
{
144144
using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
145-
std::vector<bool, Alloc> in(200, false, Alloc(1));
145+
std::vector<bool, Alloc> in(257, false, Alloc(1));
146146
in[in.size() - 2] = true;
147147
assert(std::ranges::find(in, true) == in.end() - 2);
148148
}
@@ -229,7 +229,7 @@ constexpr bool test() {
229229
}
230230
}
231231

232-
test_bititer_with_custom_sized_types();
232+
test_bit_iterator_with_custom_sized_types();
233233

234234
return true;
235235
}

0 commit comments

Comments
 (0)