Skip to content

Commit 4ad230b

Browse files
authored
[libc++] Refactor bitset::{any, all} (#128445)
This patch refactors the `all()` and `any()` methods in `bitset` to eliminate redundant code while preserving the performance. Code generation remains unchanged, as verified on Compiler Explorer: https://godbolt.org/z/xx8hb4sPM.
1 parent 4608df5 commit 4ad230b

File tree

1 file changed

+30
-48
lines changed

1 file changed

+30
-48
lines changed

libcxx/include/bitset

Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ template <size_t N> struct hash<std::bitset<N>>;
144144
# include <__cstddef/ptrdiff_t.h>
145145
# include <__cstddef/size_t.h>
146146
# include <__functional/hash.h>
147+
# include <__functional/identity.h>
147148
# include <__functional/unary_function.h>
148149
# include <__type_traits/is_char_like_type.h>
149150
# include <climits>
@@ -226,8 +227,10 @@ protected:
226227
return to_ullong(integral_constant < bool, _Size< sizeof(unsigned long long) * CHAR_BIT>());
227228
}
228229

229-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT;
230-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT;
230+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return !__scan_bits(__bit_not()); }
231+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT {
232+
return __scan_bits(std::__identity());
233+
}
231234
_LIBCPP_HIDE_FROM_ABI size_t __hash_code() const _NOEXCEPT;
232235

233236
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
@@ -246,6 +249,12 @@ protected:
246249
}
247250

248251
private:
252+
struct __bit_not {
253+
template <class _Tp>
254+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp operator()(const _Tp& __x) const _NOEXCEPT {
255+
return ~__x;
256+
}
257+
};
249258
# ifdef _LIBCPP_CXX03_LANG
250259
void __init(unsigned long long __v, false_type) _NOEXCEPT;
251260
_LIBCPP_HIDE_FROM_ABI void __init(unsigned long long __v, true_type) _NOEXCEPT;
@@ -256,6 +265,23 @@ private:
256265
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type) const;
257266
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type, false_type) const;
258267
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type, true_type) const;
268+
269+
template <typename _Proj>
270+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __scan_bits(_Proj __proj) const _NOEXCEPT {
271+
size_t __n = _Size;
272+
__const_storage_pointer __p = __first_;
273+
// do middle whole words
274+
for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
275+
if (__proj(*__p))
276+
return true;
277+
// do last partial word
278+
if (__n > 0) {
279+
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
280+
if (__proj(*__p) & __m)
281+
return true;
282+
}
283+
return false;
284+
}
259285
};
260286

261287
template <size_t _N_words, size_t _Size>
@@ -395,40 +421,6 @@ __bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
395421
return __r;
396422
}
397423

398-
template <size_t _N_words, size_t _Size>
399-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool __bitset<_N_words, _Size>::all() const _NOEXCEPT {
400-
// do middle whole words
401-
size_t __n = _Size;
402-
__const_storage_pointer __p = __first_;
403-
for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
404-
if (~*__p)
405-
return false;
406-
// do last partial word
407-
if (__n > 0) {
408-
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
409-
if (~*__p & __m)
410-
return false;
411-
}
412-
return true;
413-
}
414-
415-
template <size_t _N_words, size_t _Size>
416-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool __bitset<_N_words, _Size>::any() const _NOEXCEPT {
417-
// do middle whole words
418-
size_t __n = _Size;
419-
__const_storage_pointer __p = __first_;
420-
for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
421-
if (*__p)
422-
return true;
423-
// do last partial word
424-
if (__n > 0) {
425-
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
426-
if (*__p & __m)
427-
return true;
428-
}
429-
return false;
430-
}
431-
432424
template <size_t _N_words, size_t _Size>
433425
inline size_t __bitset<_N_words, _Size>::__hash_code() const _NOEXCEPT {
434426
size_t __h = 0;
@@ -744,8 +736,8 @@ public:
744736
_LIBCPP_HIDE_FROM_ABI bool operator!=(const bitset& __rhs) const _NOEXCEPT;
745737
# endif
746738
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool test(size_t __pos) const;
747-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT;
748-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT;
739+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return __base::all(); }
740+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT { return __base::any(); }
749741
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool none() const _NOEXCEPT { return !any(); }
750742
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator<<(size_t __pos) const _NOEXCEPT;
751743
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator>>(size_t __pos) const _NOEXCEPT;
@@ -930,16 +922,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool bitset<_Size>::test(siz
930922
return (*this)[__pos];
931923
}
932924

933-
template <size_t _Size>
934-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool bitset<_Size>::all() const _NOEXCEPT {
935-
return __base::all();
936-
}
937-
938-
template <size_t _Size>
939-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool bitset<_Size>::any() const _NOEXCEPT {
940-
return __base::any();
941-
}
942-
943925
template <size_t _Size>
944926
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size>
945927
bitset<_Size>::operator<<(size_t __pos) const _NOEXCEPT {

0 commit comments

Comments
 (0)