Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancements for <bitset> #3838

Merged
merged 9 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ function(add_benchmark name)
target_compile_definitions(benchmark-${name} PRIVATE BENCHMARK_STATIC_DEFINE)
endfunction()

add_benchmark(bitset_to_string src/bitset_to_string.cpp)
add_benchmark(locale_classic src/locale_classic.cpp)
add_benchmark(random_integer_generation src/random_integer_generation.cpp)
add_benchmark(std_copy src/std_copy.cpp)
51 changes: 51 additions & 0 deletions benchmarks/src/bitset_to_string.cpp
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <array>
#include <benchmark/benchmark.h>
#include <bit>
#include <bitset>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <random>

using namespace std;

namespace {
const auto random_bits = [] {
mt19937_64 rnd{};
array<uint64_t, 32> arr;
for (auto& d : arr) {
d = rnd();
}
return arr;
}();

template <size_t N, class charT>
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
void BM_bitset_to_string(benchmark::State& state) {
for (auto _ : state) {
for (const auto& bits : random_bits) {
bitset<N> bs{bits};
benchmark::DoNotOptimize(bs.to_string<charT>());
}
}
}

template <class charT>
void BM_bitset_to_string_large_single(benchmark::State& state) {
const auto large_bitset = bit_cast<bitset<CHAR_BIT * sizeof(random_bits)>>(random_bits);
for (auto _ : state) {
benchmark::DoNotOptimize(large_bitset.to_string<charT>());
}
}
} // namespace

BENCHMARK(BM_bitset_to_string<15, char>);
BENCHMARK(BM_bitset_to_string<64, char>);
BENCHMARK(BM_bitset_to_string_large_single<char>);
BENCHMARK(BM_bitset_to_string<7, wchar_t>);
BENCHMARK(BM_bitset_to_string<64, wchar_t>);
BENCHMARK(BM_bitset_to_string_large_single<wchar_t>);

BENCHMARK_MAIN();
36 changes: 18 additions & 18 deletions stl/inc/bitset
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ _STL_DISABLE_CLANG_WARNINGS
_STD_BEGIN
_EXPORT_STD template <size_t _Bits>
class bitset { // store fixed-length sequence of Boolean elements
public:
private:
#pragma warning(push)
#pragma warning(disable : 4296) // expression is always true (/Wall)
using _Ty = conditional_t<_Bits <= sizeof(unsigned long) * CHAR_BIT, unsigned long, unsigned long long>;
#pragma warning(pop)

public:
class reference { // proxy for an element
friend bitset;

Expand Down Expand Up @@ -68,25 +69,26 @@ public:
size_t _Mypos; // position of element in bitset
};

StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
static _CONSTEXPR23 void _Validate(const size_t _Pos) noexcept { // verify that _Pos is within bounds
private:
static constexpr void _Validate(const size_t _Pos) noexcept { // verify that _Pos is within bounds
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
#if _ITERATOR_DEBUG_LEVEL == 0
(void) _Pos;
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv
_STL_VERIFY(_Pos < _Bits, "bitset index outside range");
#endif // _ITERATOR_DEBUG_LEVEL == 0
}

constexpr bool _Subscript(size_t _Pos) const {
constexpr bool _Subscript(size_t _Pos) const noexcept {
return (_Array[_Pos / _Bitsperword] & (_Ty{1} << _Pos % _Bitsperword)) != 0;
}

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

#else // _ITERATOR_DEBUG_LEVEL == 0
return _Bits <= _Pos ? (_Validate(_Pos), false) : _Subscript(_Pos);
#endif // _ITERATOR_DEBUG_LEVEL == 0
public:
_NODISCARD constexpr bool operator[](size_t _Pos) const noexcept /* strengthened */ {
_Validate(_Pos);
return _Subscript(_Pos);
}

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

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

static constexpr bool _Need_mask = _Bits < CHAR_BIT * sizeof(unsigned long long);

static constexpr unsigned long long _Mask = (1ULL << (_Need_mask ? _Bits : 0)) - 1ULL;

constexpr bitset(unsigned long long _Val) noexcept : _Array{static_cast<_Ty>(_Need_mask ? _Val & _Mask : _Val)} {}

private:
template <class _Traits, class _Elem>
_CONSTEXPR23 void _Construct(const _Elem* const _Ptr, size_t _Count, const _Elem _Elem0, const _Elem _Elem1) {
if (_Count > _Bits) {
Expand Down Expand Up @@ -147,6 +146,7 @@ public:
}
}

public:
template <class _Elem, class _Traits, class _Alloc>
_CONSTEXPR23 explicit bitset(const basic_string<_Elem, _Traits, _Alloc>& _Str,
typename basic_string<_Elem, _Traits, _Alloc>::size_type _Pos = 0,
Expand Down Expand Up @@ -347,11 +347,11 @@ public:
_NODISCARD _CONSTEXPR23 basic_string<_Elem, _Tr, _Alloc> to_string(
const _Elem _Elem0 = static_cast<_Elem>('0'), const _Elem _Elem1 = static_cast<_Elem>('1')) const {
// convert bitset to string
basic_string<_Elem, _Tr, _Alloc> _Str;
_Str.reserve(_Bits);

for (auto _Pos = _Bits; 0 < _Pos;) {
_Str.push_back(_Subscript(--_Pos) ? _Elem1 : _Elem0);
basic_string<_Elem, _Tr, _Alloc> _Str(_Bits, _Elem0);
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
for (size_t _Pos = 0; _Pos < _Bits; ++_Pos) {
if (_Subscript(_Bits - 1 - _Pos)) {
_Str[_Pos] = _Elem1;
}
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
}

return _Str;
Expand Down