Files
fahnen_esp32/.pio/libdeps/esp01_1m/FastLED/tests/test_bitset.cpp

450 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// g++ --std=c++11 test.cpp
#include "test.h"
#include "fl/bitset.h"
#include "fl/bitset_dynamic.h"
using namespace fl;
TEST_CASE("test bitset") {
// defaultconstructed bitset is empty
bitset_fixed<10> bs;
REQUIRE_EQ(bs.none(), true);
REQUIRE_EQ(bs.count(), 0);
REQUIRE_EQ(bs.size(), 10);
// set a bit
bs.set(3);
REQUIRE_EQ(bs.test(3), true);
REQUIRE_EQ(bs[3], true);
REQUIRE_EQ(bs.any(), true);
REQUIRE_EQ(bs.count(), 1);
// reset that bit
bs.reset(3);
REQUIRE_EQ(bs.test(3), false);
REQUIRE_EQ(bs.none(), true);
// toggle a bit
bs.flip(2);
REQUIRE_EQ(bs.test(2), true);
bs.flip(2);
REQUIRE_EQ(bs.test(2), false);
// flip all bits
bitset_fixed<5> bs2;
for (size_t i = 0; i < 5; ++i)
bs2.set(i, (i % 2) == 0);
auto bs2_flipped = ~bs2;
for (size_t i = 0; i < 5; ++i)
REQUIRE_EQ(bs2_flipped.test(i), !bs2.test(i));
// all() and count()
bitset_fixed<4> bs3;
for (size_t i = 0; i < 4; ++i)
bs3.set(i);
REQUIRE_EQ(bs3.all(), true);
REQUIRE_EQ(bs3.count(), 4);
// check that the count can auto expand
bs3.set(100);
REQUIRE_EQ(bs3.count(), 4);
// bitwise AND, OR, XOR
bitset_fixed<4> a, b;
a.set(0); a.set(2);
b.set(1); b.set(2);
auto or_ab = a | b;
REQUIRE_EQ(or_ab.test(0), true);
REQUIRE_EQ(or_ab.test(1), true);
REQUIRE_EQ(or_ab.test(2), true);
REQUIRE_EQ(or_ab.test(3), false);
auto and_ab = a & b;
REQUIRE_EQ(and_ab.test(2), true);
REQUIRE_EQ(and_ab.test(0), false);
auto xor_ab = a ^ b;
REQUIRE_EQ(xor_ab.test(0), true);
REQUIRE_EQ(xor_ab.test(1), true);
REQUIRE_EQ(xor_ab.test(2), false);
// reset and none()
a.reset(); b.reset();
REQUIRE_EQ(a.none(), true);
// Test expected size of bitset_fixed
REQUIRE_EQ(bitset_fixed<8>().size(), 8);
REQUIRE_EQ(bitset_fixed<16>().size(), 16);
REQUIRE_EQ(bitset_fixed<32>().size(), 32);
REQUIRE_EQ(bitset_fixed<64>().size(), 64);
REQUIRE_EQ(bitset_fixed<100>().size(), 100);
REQUIRE_EQ(bitset_fixed<1000>().size(), 1000);
// Test memory size of bitset_fixed class (sizeof)
// For bitset_fixed<8>, we expect 1 uint16_t block (2 bytes)
REQUIRE_EQ(sizeof(bitset_fixed<8>), 2);
// For bitset_fixed<16>, we expect 1 uint16_t block (2 bytes)
REQUIRE_EQ(sizeof(bitset_fixed<16>), 2);
// For bitset_fixed<17>, we expect 2 uint16_t blocks (4 bytes)
REQUIRE_EQ(sizeof(bitset_fixed<17>), 4);
// For bitset_fixed<32>, we expect 2 uint16_t blocks (4 bytes)
REQUIRE_EQ(sizeof(bitset_fixed<32>), 4);
// For bitset_fixed<33>, we expect 3 uint16_t blocks (6 bytes)
REQUIRE_EQ(sizeof(bitset_fixed<33>), 6);
}
TEST_CASE("compare fixed and dynamic bitsets") {
// Test that fixed and dynamic bitsets behave the same
bitset_fixed<10> fixed_bs;
fl::bitset_dynamic dynamic_bs(10);
// Set the same bits in both
fixed_bs.set(1);
fixed_bs.set(5);
fixed_bs.set(9);
dynamic_bs.set(1);
dynamic_bs.set(5);
dynamic_bs.set(9);
// Verify they have the same state
REQUIRE_EQ(fixed_bs.size(), dynamic_bs.size());
REQUIRE_EQ(fixed_bs.count(), dynamic_bs.count());
for (size_t i = 0; i < 10; ++i) {
REQUIRE_EQ(fixed_bs.test(i), dynamic_bs.test(i));
}
}
TEST_CASE("test bitset_dynamic") {
// default-constructed bitset is empty
bitset_dynamic bs;
REQUIRE_EQ(bs.size(), 0);
REQUIRE_EQ(bs.none(), true);
REQUIRE_EQ(bs.count(), 0);
// resize and test
bs.resize(10);
REQUIRE_EQ(bs.size(), 10);
REQUIRE_EQ(bs.none(), true);
// set a bit
bs.set(3);
REQUIRE_EQ(bs.test(3), true);
REQUIRE_EQ(bs[3], true);
REQUIRE_EQ(bs.any(), true);
REQUIRE_EQ(bs.count(), 1);
// reset that bit
bs.reset(3);
REQUIRE_EQ(bs.test(3), false);
REQUIRE_EQ(bs.none(), true);
// toggle a bit
bs.flip(2);
REQUIRE_EQ(bs.test(2), true);
bs.flip(2);
REQUIRE_EQ(bs.test(2), false);
// resize larger
bs.set(5);
bs.resize(20);
REQUIRE_EQ(bs.size(), 20);
REQUIRE_EQ(bs.test(5), true);
REQUIRE_EQ(bs.count(), 1);
// resize smaller (truncate)
bs.resize(4);
REQUIRE_EQ(bs.size(), 4);
REQUIRE_EQ(bs.test(5), false); // out of range now
REQUIRE_EQ(bs.count(), 0);
// test with larger sizes that span multiple blocks
bitset_dynamic large_bs(100);
large_bs.set(0);
large_bs.set(63);
large_bs.set(64);
large_bs.set(99);
REQUIRE_EQ(large_bs.count(), 4);
REQUIRE_EQ(large_bs.test(0), true);
REQUIRE_EQ(large_bs.test(63), true);
REQUIRE_EQ(large_bs.test(64), true);
REQUIRE_EQ(large_bs.test(99), true);
// flip all bits
bitset_dynamic bs2(5);
for (size_t i = 0; i < 5; ++i)
bs2.set(i, (i % 2) == 0);
bs2.flip();
for (size_t i = 0; i < 5; ++i)
REQUIRE_EQ(bs2.test(i), !((i % 2) == 0));
// all() and count()
bitset_dynamic bs3(4);
for (size_t i = 0; i < 4; ++i)
bs3.set(i);
REQUIRE_EQ(bs3.all(), true);
REQUIRE_EQ(bs3.count(), 4);
// out-of-range ops are no-ops
bs3.set(100);
REQUIRE_EQ(bs3.count(), 4);
// bitwise AND, OR, XOR
bitset_dynamic a(4), b(4);
a.set(0); a.set(2);
b.set(1); b.set(2);
auto or_ab = a | b;
REQUIRE_EQ(or_ab.test(0), true);
REQUIRE_EQ(or_ab.test(1), true);
REQUIRE_EQ(or_ab.test(2), true);
REQUIRE_EQ(or_ab.test(3), false);
auto and_ab = a & b;
REQUIRE_EQ(and_ab.test(2), true);
REQUIRE_EQ(and_ab.test(0), false);
auto xor_ab = a ^ b;
REQUIRE_EQ(xor_ab.test(0), true);
REQUIRE_EQ(xor_ab.test(1), true);
REQUIRE_EQ(xor_ab.test(2), false);
// reset and none()
a.reset(); b.reset();
REQUIRE_EQ(a.none(), true);
REQUIRE_EQ(b.none(), true);
// copy constructor
bitset_dynamic original(10);
original.set(3);
original.set(7);
bitset_dynamic copy(original);
REQUIRE_EQ(copy.size(), 10);
REQUIRE_EQ(copy.test(3), true);
REQUIRE_EQ(copy.test(7), true);
REQUIRE_EQ(copy.count(), 2);
// move constructor
bitset_dynamic moved(fl::move(copy));
REQUIRE_EQ(moved.size(), 10);
REQUIRE_EQ(moved.test(3), true);
REQUIRE_EQ(moved.test(7), true);
REQUIRE_EQ(moved.count(), 2);
REQUIRE_EQ(copy.size(), 0); // moved from should be empty
// assignment operator
bitset_dynamic assigned = original;
REQUIRE_EQ(assigned.size(), 10);
REQUIRE_EQ(assigned.test(3), true);
REQUIRE_EQ(assigned.test(7), true);
// clear
assigned.clear();
REQUIRE_EQ(assigned.size(), 0);
REQUIRE_EQ(assigned.none(), true);
// Test memory size changes with resize
bitset_dynamic small_bs(8);
bitset_dynamic medium_bs(65);
bitset_dynamic large_bs2(129);
// These sizes should match the fixed bitset tests
REQUIRE_EQ(small_bs.size(), 8);
REQUIRE_EQ(medium_bs.size(), 65);
REQUIRE_EQ(large_bs2.size(), 129);
}
TEST_CASE("test bitset_fixed find_first") {
// Test find_first for true bits
bitset_fixed<64> bs;
// Initially no bits are set, so find_first(true) should return -1
REQUIRE_EQ(bs.find_first(true), -1);
// find_first(false) should return 0 (first unset bit)
REQUIRE_EQ(bs.find_first(false), 0);
// Set bit at position 5
bs.set(5);
REQUIRE_EQ(bs.find_first(true), 5);
REQUIRE_EQ(bs.find_first(false), 0);
// Set bit at position 0
bs.set(0);
REQUIRE_EQ(bs.find_first(true), 0);
REQUIRE_EQ(bs.find_first(false), 1);
// Set bit at position 63 (last bit)
bs.set(63);
REQUIRE_EQ(bs.find_first(true), 0);
REQUIRE_EQ(bs.find_first(false), 1);
// Clear bit 0, now first set bit should be 5
bs.reset(0);
REQUIRE_EQ(bs.find_first(true), 5);
REQUIRE_EQ(bs.find_first(false), 0);
// Test with larger bitset
bitset_fixed<128> bs2;
bs2.set(100);
REQUIRE_EQ(bs2.find_first(true), 100);
REQUIRE_EQ(bs2.find_first(false), 0);
// Test edge case: all bits set
bitset_fixed<8> bs3;
for (fl::u32 i = 0; i < 8; ++i) {
bs3.set(i);
}
REQUIRE_EQ(bs3.find_first(true), 0);
REQUIRE_EQ(bs3.find_first(false), -1);
// Test edge case: no bits set
bitset_fixed<8> bs4;
REQUIRE_EQ(bs4.find_first(true), -1);
REQUIRE_EQ(bs4.find_first(false), 0);
}
TEST_CASE("test bitset_dynamic find_first") {
// Test find_first for dynamic bitset
bitset_dynamic bs(64);
// Initially no bits are set, so find_first(true) should return -1
REQUIRE_EQ(bs.find_first(true), -1);
// find_first(false) should return 0 (first unset bit)
REQUIRE_EQ(bs.find_first(false), 0);
// Set bit at position 5
bs.set(5);
REQUIRE_EQ(bs.find_first(true), 5);
REQUIRE_EQ(bs.find_first(false), 0);
// Set bit at position 0
bs.set(0);
REQUIRE_EQ(bs.find_first(true), 0);
REQUIRE_EQ(bs.find_first(false), 1);
// Set bit at position 63 (last bit)
bs.set(63);
REQUIRE_EQ(bs.find_first(true), 0);
REQUIRE_EQ(bs.find_first(false), 1);
// Clear bit 0, now first set bit should be 5
bs.reset(0);
REQUIRE_EQ(bs.find_first(true), 5);
REQUIRE_EQ(bs.find_first(false), 0);
// Test with all bits set
bitset_dynamic bs2(16);
for (fl::u32 i = 0; i < 16; ++i) {
bs2.set(i);
}
REQUIRE_EQ(bs2.find_first(true), 0);
REQUIRE_EQ(bs2.find_first(false), -1);
// Test with no bits set
bitset_dynamic bs3(16);
REQUIRE_EQ(bs3.find_first(true), -1);
REQUIRE_EQ(bs3.find_first(false), 0);
}
TEST_CASE("test bitset_inlined find_first") {
// Test find_first for inlined bitset (uses fixed bitset internally for small sizes)
bitset<64> bs;
// Initially no bits are set, so find_first(true) should return -1
REQUIRE_EQ(bs.find_first(true), -1);
// find_first(false) should return 0 (first unset bit)
REQUIRE_EQ(bs.find_first(false), 0);
// Set bit at position 5
bs.set(5);
REQUIRE_EQ(bs.find_first(true), 5);
REQUIRE_EQ(bs.find_first(false), 0);
// Set bit at position 0
bs.set(0);
REQUIRE_EQ(bs.find_first(true), 0);
REQUIRE_EQ(bs.find_first(false), 1);
// Set bit at position 63 (last bit)
bs.set(63);
REQUIRE_EQ(bs.find_first(true), 0);
REQUIRE_EQ(bs.find_first(false), 1);
// Clear bit 0, now first set bit should be 5
bs.reset(0);
REQUIRE_EQ(bs.find_first(true), 5);
REQUIRE_EQ(bs.find_first(false), 0);
// Test with all bits set
bitset<16> bs2;
for (fl::u32 i = 0; i < 16; ++i) {
bs2.set(i);
}
REQUIRE_EQ(bs2.find_first(true), 0);
REQUIRE_EQ(bs2.find_first(false), -1);
// Test with no bits set
bitset<16> bs3;
REQUIRE_EQ(bs3.find_first(true), -1);
REQUIRE_EQ(bs3.find_first(false), 0);
// Test with larger size that uses dynamic bitset internally
bitset<300> bs4;
bs4.set(150);
REQUIRE_EQ(bs4.find_first(true), 150);
REQUIRE_EQ(bs4.find_first(false), 0);
}
TEST_CASE("test bitset_fixed find_run") {
// Test interesting patterns
bitset_fixed<32> bs;
// Set pattern: 0001 1001 0111 1100 0000 1111 0000 0011
bs.set(3);
bs.set(4);
bs.set(7);
bs.set(9);
bs.set(10);
bs.set(11);
bs.set(12);
bs.set(13);
bs.set(20);
bs.set(21);
bs.set(22);
bs.set(23);
bs.set(30);
bs.set(31);
FL_WARN("bs: " << bs);
// Find first run of length 3
int idx = bs.find_run(true, 3);
REQUIRE_EQ(idx, 9); // First run at 3
idx = bs.find_run(false, 2, 9);
REQUIRE_EQ(idx, 14); // First run at 3
// off the edge
idx = bs.find_run(true, 3, 31);
REQUIRE_EQ(idx, -1);
}