Skip to content

Commit f17d31f

Browse files
committed
Inline selection of __zero and __one inside __to_string
1 parent 78a21d3 commit f17d31f

File tree

2 files changed

+31
-38
lines changed

2 files changed

+31
-38
lines changed

libcxx/docs/ReleaseNotes/21.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ Improvements and New Features
7070
- The segmented iterator optimization for ``std::for_each`` has been backported to C++11. Previously it was only available
7171
in C++23 and later.
7272

73+
- The ``bitset::to_string`` function has been optimized, resulting in a performance improvement of up to 8.3x for bitsets
74+
with uniformly distributed zeros and ones, and up to 13.5x and 16.1x for sparse and dense bitsets, respectively.
75+
7376
Deprecations and Removals
7477
-------------------------
7578

libcxx/include/bitset

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,25 @@ protected:
226226
return to_ullong(integral_constant < bool, _Size< sizeof(unsigned long long) * CHAR_BIT>());
227227
}
228228

229-
template <bool _Spare, class _CharT, class _Traits, class _Allocator>
230-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
231-
__to_string(_CharT __zero, _CharT __one) const;
232-
233229
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT;
234230
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT;
235231
_LIBCPP_HIDE_FROM_ABI size_t __hash_code() const _NOEXCEPT;
236232

233+
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
234+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
235+
__to_string(_CharT __zero, _CharT __one) const {
236+
basic_string<_CharT, _Traits, _Allocator> __r(_Size, _Sparse ? __zero : __one);
237+
for (size_t __i = 0, __bits = 0; __i < _N_words; ++__i, __bits += __bits_per_word) {
238+
__storage_type __word = std::__invert_if<!_Sparse>(__first_[__i]);
239+
if (__i == _N_words - 1 && _Size - __bits < __bits_per_word)
240+
__word &= (__storage_type(1) << (_Size - __bits)) - 1;
241+
for (; __word; __word &= (__word - 1))
242+
__r[_Size - 1 - (__bits + std::__countr_zero(__word))] = _Sparse ? __one : __zero;
243+
}
244+
245+
return __r;
246+
}
247+
237248
private:
238249
# ifdef _LIBCPP_CXX03_LANG
239250
void __init(unsigned long long __v, false_type) _NOEXCEPT;
@@ -394,22 +405,6 @@ __bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
394405
return __r;
395406
}
396407

397-
template <size_t _N_words, size_t _Size>
398-
template <bool _Spare, class _CharT, class _Traits, class _Allocator>
399-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
400-
__bitset<_N_words, _Size>::__to_string(_CharT __zero, _CharT __one) const {
401-
basic_string<_CharT, _Traits, _Allocator> __r(_Size, __zero);
402-
for (size_t __i = 0, __bits = 0; __i < _N_words; ++__i, __bits += __bits_per_word) {
403-
__storage_type __word = std::__invert_if<!_Spare>(__first_[__i]);
404-
if (__i == _N_words - 1 && _Size - __bits < __bits_per_word)
405-
__word &= (__storage_type(1) << (_Size - __bits)) - 1;
406-
for (; __word; __word &= (__word - 1))
407-
__r[_Size - 1 - (__bits + std::__countr_zero(__word))] = __one;
408-
}
409-
410-
return __r;
411-
}
412-
413408
template <size_t _N_words, size_t _Size>
414409
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool __bitset<_N_words, _Size>::all() const _NOEXCEPT {
415410
// do middle whole words
@@ -507,7 +502,17 @@ protected:
507502

508503
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
509504
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
510-
__to_string(_CharT __zero, _CharT __one) const;
505+
__to_string(_CharT __zero, _CharT __one) const {
506+
basic_string<_CharT, _Traits, _Allocator> __r(_Size, _Sparse ? __zero : __one);
507+
__storage_type __word = std::__invert_if<!_Sparse>(__first_);
508+
if (_Size < __bits_per_word)
509+
__word &= (__storage_type(1) << _Size) - 1;
510+
for (; __word; __word &= (__word - 1)) {
511+
size_t __pos = std::__countr_zero(__word);
512+
__r[_Size - 1 - __pos] = _Sparse ? __one : __zero;
513+
}
514+
return __r;
515+
}
511516

512517
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT;
513518
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT;
@@ -556,21 +561,6 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __
556561
return __first_;
557562
}
558563

559-
template <size_t _Size>
560-
template <bool _Spare, class _CharT, class _Traits, class _Allocator>
561-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
562-
__bitset<1, _Size>::__to_string(_CharT __zero, _CharT __one) const {
563-
basic_string<_CharT, _Traits, _Allocator> __r(_Size, __zero);
564-
__storage_type __word = std::__invert_if<!_Spare>(__first_);
565-
if (_Size < __bits_per_word)
566-
__word &= (__storage_type(1) << _Size) - 1;
567-
for (; __word; __word &= (__word - 1)) {
568-
size_t __pos = std::__countr_zero(__word);
569-
__r[_Size - 1 - __pos] = __one;
570-
}
571-
return __r;
572-
}
573-
574564
template <size_t _Size>
575565
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool __bitset<1, _Size>::all() const _NOEXCEPT {
576566
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - _Size);
@@ -635,7 +625,7 @@ protected:
635625
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return 0; }
636626
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { return 0; }
637627

638-
template <bool _Spare, class _CharT, class _Traits, class _Allocator>
628+
template <bool _Sparse, class _CharT, class _Traits, class _Allocator>
639629
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 basic_string<_CharT, _Traits, _Allocator>
640630
__to_string(_CharT, _CharT) const {
641631
return basic_string<_CharT, _Traits, _Allocator>();
@@ -898,7 +888,7 @@ bitset<_Size>::to_string(_CharT __zero, _CharT __one) const {
898888
if (__sparse)
899889
return __base::template __to_string<true, _CharT, _Traits, _Allocator>(__zero, __one);
900890
else
901-
return __base::template __to_string<false, _CharT, _Traits, _Allocator>(__one, __zero);
891+
return __base::template __to_string<false, _CharT, _Traits, _Allocator>(__zero, __one);
902892
}
903893

904894
template <size_t _Size>

0 commit comments

Comments
 (0)