Skip to content
Merged
72 changes: 53 additions & 19 deletions tests/std/tests/GH_000625_vector_bool_optimization/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
#include <random>
#include <vector>

#if _HAS_CXX20
#define TEST_CONSTEXPR constexpr
#else
#define TEST_CONSTEXPR
#endif

#pragma warning(disable : 4365) // conversion from 'unsigned __int64' to 'const __int64', signed/unsigned mismatch

using namespace std;
Expand All @@ -20,7 +26,7 @@ constexpr int blockSize = 32;
static_assert(blockSize == _VBITS, "Invalid block size");

// This test data is not random, but irregular enough to ensure confidence in the tests
const vector<bool> source = { //
constexpr bool source_raw[] = { //
true, false, true, false, true, true, true, false, //
true, false, true, false, true, true, true, false, //
true, false, true, false, true, true, true, false, //
Expand All @@ -39,8 +45,7 @@ const vector<bool> source = { //
true, false, true, false, true, true, true, false, //
true, false, true, false, true, true, true, false};


void test_fill_helper(const size_t length) {
TEST_CONSTEXPR void test_fill_helper(const size_t length) {
// No offset
{
vector<bool> result_true(length, true);
Expand Down Expand Up @@ -102,7 +107,7 @@ void test_fill_helper(const size_t length) {
}
}

bool test_fill() {
TEST_CONSTEXPR bool test_fill() {
// Empty
test_fill_helper(0);

Expand All @@ -126,7 +131,7 @@ bool test_fill() {
return true;
}

void test_find_helper(const size_t length) {
TEST_CONSTEXPR void test_find_helper(const size_t length) {
// No offset
{
vector<bool> input_true(length + 3, false);
Expand Down Expand Up @@ -160,7 +165,7 @@ void test_find_helper(const size_t length) {
}
}

bool test_find() {
TEST_CONSTEXPR bool test_find() {
// Empty range
test_find_helper(0);

Expand All @@ -178,10 +183,11 @@ bool test_find() {
return true;
}

void test_count_helper(const ptrdiff_t length) {
TEST_CONSTEXPR void test_count_helper(const ptrdiff_t length) {
const vector<bool> source(begin(source_raw), end(source_raw));
const int counts_true[] = {0, 1, 1, 2, 2, 3, 4, 5};
const int counts_false[] = {0, 0, 1, 1, 2, 2, 2, 2};
const auto expected = div(static_cast<int>(length), 8);
const div_t expected = {static_cast<int>(length) / 8, static_cast<int>(length) % 8};
// No offset
{
const auto result_true = static_cast<int>(count(source.cbegin(), next(source.cbegin(), length), true));
Expand All @@ -203,7 +209,7 @@ void test_count_helper(const ptrdiff_t length) {
}
}

bool test_count() {
TEST_CONSTEXPR bool test_count() {
// Empty range
test_count_helper(0);

Expand Down Expand Up @@ -259,7 +265,7 @@ void test_huge_vector_bool() {
assert(count(v.begin(), v.end(), false) == large_bit_diff - 3);
}

void test_copy_no_offset(const size_t length) {
TEST_CONSTEXPR void test_copy_no_offset(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -304,6 +310,8 @@ void test_copy_no_offset(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(source.begin(), next(source.begin(), length), dest.begin());
Expand Down Expand Up @@ -341,7 +349,7 @@ void test_copy_no_offset(const size_t length) {
}
}

void test_copy_offset_source(const size_t length) {
TEST_CONSTEXPR void test_copy_offset_source(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -389,6 +397,8 @@ void test_copy_offset_source(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(next(source.begin()), next(source.begin(), length + 1), dest.begin());
Expand Down Expand Up @@ -427,7 +437,7 @@ void test_copy_offset_source(const size_t length) {
}
}

void test_copy_offset_dest(const size_t length) {
TEST_CONSTEXPR void test_copy_offset_dest(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -480,6 +490,8 @@ void test_copy_offset_dest(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length + 1, false);
const auto res_copy = copy(source.begin(), next(source.begin(), length), next(dest.begin()));
Expand Down Expand Up @@ -517,7 +529,7 @@ void test_copy_offset_dest(const size_t length) {
}
}

void test_copy_offset_match(const size_t length) {
TEST_CONSTEXPR void test_copy_offset_match(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -570,6 +582,8 @@ void test_copy_offset_match(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(next(source.begin()), next(source.begin(), length), next(dest.begin()));
Expand Down Expand Up @@ -608,7 +622,7 @@ void test_copy_offset_match(const size_t length) {
}
}

void test_copy_offset_mismatch_leftshift(const size_t length) {
TEST_CONSTEXPR void test_copy_offset_mismatch_leftshift(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -661,6 +675,8 @@ void test_copy_offset_mismatch_leftshift(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length + 1, false);
const auto res_copy = copy(next(source.begin()), next(source.begin(), length), next(dest.begin(), 2));
Expand Down Expand Up @@ -699,7 +715,7 @@ void test_copy_offset_mismatch_leftshift(const size_t length) {
}
}

void test_copy_offset_mismatch_rightshift(const size_t length) {
TEST_CONSTEXPR void test_copy_offset_mismatch_rightshift(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -754,6 +770,8 @@ void test_copy_offset_mismatch_rightshift(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(next(source.begin(), 2), next(source.begin(), length + 1), next(dest.begin()));
Expand Down Expand Up @@ -792,7 +810,7 @@ void test_copy_offset_mismatch_rightshift(const size_t length) {
}
}

void test_copy_offset_aligned(const size_t length) {
TEST_CONSTEXPR void test_copy_offset_aligned(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -845,6 +863,8 @@ void test_copy_offset_aligned(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(next(source.begin(), 9), next(source.begin(), length + 8), next(dest.begin()));
Expand Down Expand Up @@ -883,7 +903,9 @@ void test_copy_offset_aligned(const size_t length) {
}
}

void test_copy_sub_char() {
TEST_CONSTEXPR void test_copy_sub_char() {
const vector<bool> source(begin(source_raw), end(source_raw));

{ // sub char copy unaligned
const vector<bool> result = {false, false, true, false, true, false, false, false};

Expand Down Expand Up @@ -1092,7 +1114,7 @@ void test_copy_sub_char() {
}
}

void test_copy_regression() {
TEST_CONSTEXPR void test_copy_regression() {
// This specific case was found by the randomized coverage below.
const vector<bool> src = {0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
Expand All @@ -1115,7 +1137,7 @@ void test_copy_regression() {
assert(dst == correct);
}

bool test_copy() {
TEST_CONSTEXPR bool test_copy() {
test_copy_no_offset(3);
test_copy_no_offset(8);
test_copy_no_offset(22);
Expand Down Expand Up @@ -1354,6 +1376,18 @@ static_assert(test_gh_5345<64>());
static_assert(test_gh_5345<64, 16>());
static_assert(test_gh_5345<120>());
static_assert(test_gh_5345<120, 31>());

static_assert(test_fill());

#if !defined(__EDG__) || !defined(_DEBUG) // TRANSITION: bogus(?) EDG error
static_assert(test_find());
#endif // ^^^ no workaround ^^^

static_assert(test_count());

#if defined(__clang__) && !defined(_DEBUG) || defined(__EDG__) // TRANSITION, VSO-2574489 and clang-cl conxtexpr limit
static_assert(test_copy());
#endif // ^^^ no workaround ^^^
#endif // _HAS_CXX20

int main() {
Expand Down