Skip to content

Commit 750ec42

Browse files
achabensefrederick-vs-jaStephanTLavavej
authored
Enhancements for <bitset> (#3838)
Co-authored-by: A. Jiang <[email protected]> Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 5c91cbb commit 750ec42

File tree

3 files changed

+70
-18
lines changed

3 files changed

+70
-18
lines changed

benchmarks/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ function(add_benchmark name)
105105
target_compile_definitions(benchmark-${name} PRIVATE BENCHMARK_STATIC_DEFINE)
106106
endfunction()
107107

108+
add_benchmark(bitset_to_string src/bitset_to_string.cpp)
108109
add_benchmark(locale_classic src/locale_classic.cpp)
109110
add_benchmark(path_lexically_normal src/path_lexically_normal.cpp)
110111
add_benchmark(random_integer_generation src/random_integer_generation.cpp)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <array>
5+
#include <benchmark/benchmark.h>
6+
#include <bit>
7+
#include <bitset>
8+
#include <climits>
9+
#include <cstddef>
10+
#include <cstdint>
11+
#include <random>
12+
13+
using namespace std;
14+
15+
namespace {
16+
const auto random_bits = [] {
17+
mt19937_64 rnd{};
18+
array<uint64_t, 32> arr;
19+
for (auto& d : arr) {
20+
d = rnd();
21+
}
22+
return arr;
23+
}();
24+
25+
template <size_t N, class charT>
26+
void BM_bitset_to_string(benchmark::State& state) {
27+
for (auto _ : state) {
28+
for (const auto& bits : random_bits) {
29+
bitset<N> bs{bits};
30+
benchmark::DoNotOptimize(bs.to_string<charT>());
31+
}
32+
}
33+
}
34+
35+
template <class charT>
36+
void BM_bitset_to_string_large_single(benchmark::State& state) {
37+
const auto large_bitset = bit_cast<bitset<CHAR_BIT * sizeof(random_bits)>>(random_bits);
38+
for (auto _ : state) {
39+
benchmark::DoNotOptimize(large_bitset.to_string<charT>());
40+
}
41+
}
42+
} // namespace
43+
44+
BENCHMARK(BM_bitset_to_string<15, char>);
45+
BENCHMARK(BM_bitset_to_string<64, char>);
46+
BENCHMARK(BM_bitset_to_string_large_single<char>);
47+
BENCHMARK(BM_bitset_to_string<7, wchar_t>);
48+
BENCHMARK(BM_bitset_to_string<64, wchar_t>);
49+
BENCHMARK(BM_bitset_to_string_large_single<wchar_t>);
50+
51+
BENCHMARK_MAIN();

stl/inc/bitset

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ _STL_DISABLE_CLANG_WARNINGS
2222
_STD_BEGIN
2323
_EXPORT_STD template <size_t _Bits>
2424
class bitset { // store fixed-length sequence of Boolean elements
25-
public:
25+
private:
2626
#pragma warning(push)
2727
#pragma warning(disable : 4296) // expression is always true (/Wall)
2828
using _Ty = conditional_t<_Bits <= sizeof(unsigned long) * CHAR_BIT, unsigned long, unsigned long long>;
2929
#pragma warning(pop)
3030

31+
public:
3132
class reference { // proxy for an element
3233
friend bitset;
3334

@@ -68,25 +69,26 @@ public:
6869
size_t _Mypos; // position of element in bitset
6970
};
7071

71-
static _CONSTEXPR23 void _Validate(const size_t _Pos) noexcept { // verify that _Pos is within bounds
72+
private:
73+
static constexpr void _Validate(const size_t _Pos) noexcept { // verify that _Pos is within bounds
7274
#if _ITERATOR_DEBUG_LEVEL == 0
7375
(void) _Pos;
7476
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv
7577
_STL_VERIFY(_Pos < _Bits, "bitset index outside range");
7678
#endif // _ITERATOR_DEBUG_LEVEL == 0
7779
}
7880

79-
constexpr bool _Subscript(size_t _Pos) const {
81+
constexpr bool _Subscript(size_t _Pos) const noexcept {
8082
return (_Array[_Pos / _Bitsperword] & (_Ty{1} << _Pos % _Bitsperword)) != 0;
8183
}
8284

83-
_NODISCARD constexpr bool operator[](size_t _Pos) const {
84-
#if _ITERATOR_DEBUG_LEVEL == 0
85-
return _Subscript(_Pos);
85+
static constexpr bool _Need_mask = _Bits < CHAR_BIT * sizeof(unsigned long long);
86+
static constexpr unsigned long long _Mask = (1ULL << (_Need_mask ? _Bits : 0)) - 1ULL;
8687

87-
#else // _ITERATOR_DEBUG_LEVEL == 0
88-
return _Bits <= _Pos ? (_Validate(_Pos), false) : _Subscript(_Pos);
89-
#endif // _ITERATOR_DEBUG_LEVEL == 0
88+
public:
89+
_NODISCARD constexpr bool operator[](size_t _Pos) const noexcept /* strengthened */ {
90+
_Validate(_Pos);
91+
return _Subscript(_Pos);
9092
}
9193

9294
_NODISCARD _CONSTEXPR23 reference operator[](const size_t _Pos) noexcept /* strengthened */ {
@@ -96,12 +98,9 @@ public:
9698

9799
constexpr bitset() noexcept : _Array() {} // construct with all false values
98100

99-
static constexpr bool _Need_mask = _Bits < CHAR_BIT * sizeof(unsigned long long);
100-
101-
static constexpr unsigned long long _Mask = (1ULL << (_Need_mask ? _Bits : 0)) - 1ULL;
102-
103101
constexpr bitset(unsigned long long _Val) noexcept : _Array{static_cast<_Ty>(_Need_mask ? _Val & _Mask : _Val)} {}
104102

103+
private:
105104
template <class _Traits, class _Elem>
106105
_CONSTEXPR23 void _Construct(const _Elem* const _Ptr, size_t _Count, const _Elem _Elem0, const _Elem _Elem1) {
107106
if (_Count > _Bits) {
@@ -147,6 +146,7 @@ public:
147146
}
148147
}
149148

149+
public:
150150
template <class _Elem, class _Traits, class _Alloc>
151151
_CONSTEXPR23 explicit bitset(const basic_string<_Elem, _Traits, _Alloc>& _Str,
152152
typename basic_string<_Elem, _Traits, _Alloc>::size_type _Pos = 0,
@@ -347,11 +347,11 @@ public:
347347
_NODISCARD _CONSTEXPR23 basic_string<_Elem, _Tr, _Alloc> to_string(
348348
const _Elem _Elem0 = static_cast<_Elem>('0'), const _Elem _Elem1 = static_cast<_Elem>('1')) const {
349349
// convert bitset to string
350-
basic_string<_Elem, _Tr, _Alloc> _Str;
351-
_Str.reserve(_Bits);
352-
353-
for (auto _Pos = _Bits; 0 < _Pos;) {
354-
_Str.push_back(_Subscript(--_Pos) ? _Elem1 : _Elem0);
350+
basic_string<_Elem, _Tr, _Alloc> _Str(_Bits, _Elem0);
351+
for (size_t _Pos = 0; _Pos < _Bits; ++_Pos) {
352+
if (_Subscript(_Bits - 1 - _Pos)) {
353+
_Str[_Pos] = _Elem1;
354+
}
355355
}
356356

357357
return _Str;

0 commit comments

Comments
 (0)