25#include <jau/test/catch2_ext.hpp>
34 const size_t bits = 3_uz*64_uz;
41 REQUIRE(0 == b1.
count());
43 REQUIRE(0 == b1.
flip().count());
48 REQUIRE(
true == b1.
set(64, 2_uz*64_uz,
true));
49 REQUIRE(2_uz*64_uz == b1.
count());
52 const size_t bits = 3_uz*64_uz+4_uz;
59 REQUIRE(0 == b1.
count());
61 REQUIRE(0 == b1.
flip().count());
66 REQUIRE(
true == b1.
set(33, 2_uz*64_uz+2_uz,
true));
67 REQUIRE(2_uz*64_uz+2_uz == b1.
count());
70 const size_t bits = 3_uz*32_uz+4_uz;
77 REQUIRE(0 == b1.
count());
80 REQUIRE(0 == b1.
flip().count());
85 REQUIRE(
true == b1.
set(17, 2_uz*32_uz+2_uz,
true));
86 REQUIRE(2_uz*32_uz+2_uz == b1.
count());
89 const size_t bits = 3_uz*8_uz+4_uz;
96 REQUIRE(0 == b1.
count());
99 REQUIRE(0 == b1.
flip().count());
104 REQUIRE(
true == b1.
set(5, 2_uz*8_uz+2_uz,
true));
105 REQUIRE(2_uz*8_uz+2_uz == b1.
count());
109TEST_CASE(
"Bitfield Test 01 BitCount32_One",
"[bitfield]" ) {
111 for(
size_t i=0; i<pyramid32bit_one.size(); i++) {
112 const uint32_t val0 = 1_u32 << i;
115 const std::string_view pattern0 = pyramid32bit_one[i];
122 REQUIRE(val0 == val1);
123 REQUIRE(pattern0 == pattern1);
125 REQUIRE(oneBitCount0 == oneBitCountI1);
126 REQUIRE(oneBitCount0 == oneBitCountI2);
133 fprintf(stderr,
"XXX getBitheap: bitOrder %s, preBits %zu, skipBits %zu, postBits %zu, totalBits %zu\n",
134 jau::to_string(dataBitOrder).c_str(), (
size_t)preBits, (
size_t)skipBits, (
size_t)postBits, (
size_t)totalBits);
144 std::cerr << source <<
"\n";
145 const auto [pre, preOK] = source.
subbits(0, preBits);
146 const auto [post, postOK] = source.
subbits(preBits+skipBits, postBits);
147 REQUIRE(
true == preOK);
148 REQUIRE(
true == postOK);
151 REQUIRE(
true == r.
put(0, pre));
152 REQUIRE(
true == r.
put(preBits, post));
153 std::cerr <<
"ResultExp: <" << pre <<
"> + <" << post <<
"> = <" << r <<
">\n";
154 fprintf(stderr,
"source0: <%s>\n", std::string(in).c_str());
155 fprintf(stderr,
"source1: <%s>\n", source.
toString().c_str());
156 REQUIRE(totalBits == r.
size());
160TEST_CASE(
"Bitfield Test 01 subbits",
"[bitfield][subbits]") {
182 REQUIRE(oneBitCountL == oneBitCount1);
185TEST_CASE(
"Bitfield Test 10 BitCount32_One",
"[bitfield]" ) {
187 const uint32_t MAX_minus = MAX-0x1FF;
188 const uint32_t MAX_half = MAX/2;
189 const uint32_t MAX_half_minus = MAX_half-0x1FF;
190 const uint32_t MAX_half_plus = MAX_half+0x1FF;
192 for(uint32_t l=0; l<=0x1FF; ++l) {
195 for(uint32_t l=MAX_half_minus; l<=MAX_half_plus; ++l) {
198 for(uint32_t l=MAX_minus-1; l++ <MAX; ) {
210 0, 0, 1, 1, 2, 1, 3, 2, 4, 1, 5, 2, 6, 2, 7, 3,
211 8, 1, 9, 2, 10, 2, 11, 3, 12, 2, 13, 3, 14, 3, 15, 4, 16, 1, 17, 2,
212 0x3F, 6, 0x40, 1, 0x41, 2, 0x7f, 7, 0x80, 1, 0x81, 2, 0xfe, 7, 0xff, 8,
213 0x4000, 1, 0x4001, 2, 0x7000, 3, 0x7fff, 15,
229 REQUIRE(expOneBits == oneBitCountI);
230 REQUIRE(oneBitCountI == oneBitCount1);
233TEST_CASE(
"Bitfield Test 11 BitCount32_Data",
"[bitfield]" ) {
251 TestDataBF(
const uint64_t bitSize_,
const uint64_t value_,
const std::string_view pattern_)
265 TestDataBF(64, 0x04030201AFFECAFE,
"0000010000000011000000100000000110101111111111101100101011111110"),
266 TestDataBF(64, 0xAFFECAFE04030201,
"1010111111111110110010101111111000000100000000110000001000000001"),
267 TestDataBF(64, 0xDEADBEEFDEADBEEF,
"1101111010101101101111101110111111011110101011011011111011101111")
273 TestDataBF(32, 0x04030201,
"00000100000000110000001000000001"),
276 TestDataBF(32, 0xAFFECAFE,
"10101111111111101100101011111110"),
278 TestDataBF(32, 0xDEADBEEF,
"11011110101011011011111011101111")
304 std::cout <<
"Test " <<
prefix <<
": " << d <<
"\n";
307 REQUIRE(oneBitCount0 == oneBitCount1);
311 REQUIRE(d.
pattern == pattern0);
314 REQUIRE(d.
val == val1);
315 REQUIRE(d.
bitSize == pattern0.length());
318TEST_CASE(
"Bitfield Test 20 ValidateTestData",
"[bitfield]" ) {
340template<jau::req::
unsigned_
integral StorageType,
size_t BitSize>
342 const std::string_view pattern,
size_t oneBitCount)
344 const size_t len = pattern.length();
345 for(
size_t i=0; i<len; i++) {
346 const bool exp0 = 0 != ( v & ( 1_u64 << i ) );
347 const bool exp1 =
'1' == pattern[len-1-i];
348 const bool has = bf[i+bf_off];
351 REQUIRE(exp0 == has);
352 REQUIRE(exp1 == has);
356template<jau::req::
unsigned_
integral StorageType,
size_t BitSize1,
size_t BitSize2>
360 std::cout <<
"Test " <<
prefix <<
": " << d <<
"\n";
366 REQUIRE(oneBitCount == bf1.
count());
372 REQUIRE(oneBitCount*1 == bf2.
count());
378 REQUIRE(oneBitCount*2 == bf2.
count());
386 REQUIRE(oneBitCount*3 == bf2.
count());
402TEST_CASE(
"Bitfield Test 21 Alignedbits",
"[bitfield]" ) {
424template<jau::req::
unsigned_
integral StorageType,
size_t BitSize>
426 const std::string& msg,
const StorageType expBits) {
427 const size_t highBitnum = lowBitnum + d.
bitSize - 1;
429 for(
size_t i=0; i<lowBitnum; i+=32) {
430 const size_t len = std::min<size_t>(32_uz, lowBitnum-i);
431 const StorageType val = bf.
getUnit(i, len);
434 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), exp == val);
436 for(
size_t i=highBitnum+1; i<bf.
size(); i+=32) {
437 const size_t len = std::min(32_uz, bf.
size() - i);
438 const StorageType val = bf.
getUnit(i, len);
441 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), exp == val);
445template<jau::req::
unsigned_
integral StorageType,
size_t BitSize>
450 const std::string msg =
jau::format_string(
"Value 0x%08" PRIx64
" / %s, l %zu/%zu, c %zu, lbPos %zu -> %zu",
457 for(
size_t i=0; i<d.
bitSize; i++) {
458 const bool exp = d.
val & ( 1_u64 << i );
459 const bool has = bf[lowBitnum+i];
460 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), exp == has);
463 REQUIRE_MSG(msg, oneBitCount == bf.
count());
469 if( lowBitnum < maxBitpos ) {
472 REQUIRE_MSG(msg,
true == bf.
copyUnit(lowBitnum, lowBitnum+1, d.
bitSize));
473 REQUIRE(
true == bf.
clr(lowBitnum));
475 REQUIRE_MSG(msg, oneBitCount == bf.
count());
481 REQUIRE_MSG(msg+
", bitpos 0",
false == bf[lowBitnum]);
482 REQUIRE(
true == bf.
put(lowBitnum,
true));
483 REQUIRE_MSG(msg+
", bitpos 0",
true == bf[lowBitnum]);
484 REQUIRE(
true == bf.
put(lowBitnum,
false));
485 REQUIRE_MSG(msg+
", bitpos 0",
false == bf[lowBitnum]);
490 for(
size_t i=0; i<d.
bitSize; i++) {
491 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i),
false == bf[lowBitnum+i]);
492 const bool v = d.
val & ( 1_u64 << i );
493 REQUIRE(
true == bf.
put(lowBitnum+i, v));
494 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), v == bf[lowBitnum+i]);
497 for(
size_t i=0; i<d.
bitSize; i++) {
498 const bool exp = d.
val & ( 1_u64 << i );
499 const bool has = bf[lowBitnum+i];
500 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), exp == has);
502 REQUIRE_MSG(msg, oneBitCount == bf.
count());
508 if( lowBitnum < maxBitpos ) {
511 for(
size_t i=d.
bitSize; i-- >0; ) {
512 const bool exp = d.
val & (1_u64 << i);
513 REQUIRE(
true == bf.
copy(lowBitnum+i, lowBitnum+1+i));
514 const bool has = bf.
get(lowBitnum+1+i);
515 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), exp == has);
517 REQUIRE(
true == bf.
clr(lowBitnum));
519 for(
size_t i=0; i<d.
bitSize; i++) {
520 const bool exp = d.
val & (1_u64 << i);
521 const bool has = bf[lowBitnum+1+i];
522 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), exp == has);
524 REQUIRE_MSG(msg, oneBitCount == bf.
count());
533 for(
size_t i=0; i<d.
bitSize; i++) {
534 if( d.
val & ( 1_u64 << i ) ) {
535 REQUIRE(
true == bf.
set(lowBitnum+i));
537 REQUIRE(
true == bf.
clr(lowBitnum+i));
541 for(
size_t i=0; i<d.
bitSize; i++) {
542 const bool exp = d.
val & (1_u64 << i);
543 const bool has = bf[lowBitnum+i];
544 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), exp == has);
546 REQUIRE_MSG(msg, oneBitCount == bf.
count());
551 REQUIRE(
true == bf.
set(0, lowBitnum,
false));
554 for(
size_t i=0; i<d.
bitSize; i++) {
555 if( d.
val & ( 1_u64 << i ) ) {
556 REQUIRE(
true == bf.
set(lowBitnum+i));
558 REQUIRE(
true == bf.
clr(lowBitnum+i));
562 for(
size_t i=0; i<d.
bitSize; i++) {
563 const bool exp = d.
val & (1_u64 << i);
564 const bool has = bf[lowBitnum+i];
565 REQUIRE_MSG(msg+
", bitpos "+std::to_string(i), exp == has);
567 if( oneBitCount != bf.
count() ) {
568 REQUIRE_MSG(msg, oneBitCount == bf.
count());
585template<jau::req::
unsigned_
integral StorageType,
size_t BitSize>
588 for(
size_t i=0; i<=maxBitpos; i++) {
594template<
size_t BitSize1,
size_t BitSize2>
602TEST_CASE(
"Bitfield Test 22 Unalignedbits",
"[bitfield]" ) {
618template<jau::req::
unsigned_
integral StorageType,
size_t BitSize>
620 const bool verbose =
true;
622 std::cout <<
prefix <<
": " << d <<
"\n";
629 std::string s_be2_rev = s_be2;
630 std::ranges::reverse(s_be2_rev);
633 std::cout <<
" data: " << d.
pattern <<
"\n";
634 std::cout <<
" s_be2: " << s_be2 <<
"\n";
635 std::cout <<
" s_be2_rev: " << s_be2_rev <<
"\n";
636 std::cout <<
" s_be3_rev: " << s_be3_rev <<
"\n";
639 REQUIRE( s_be2_rev == s_be3_rev );
642template<
size_t BitSize>
654TEST_CASE(
"Bitfield Test 30 Aligned Reverse",
"[bitfield][bitreverse]") {
683template<jau::req::
unsigned_
integral StorageType,
size_t BitSize>
685 const bool verbose =
true;
687 std::cout <<
prefix <<
", offset " << offset <<
": " << d <<
"\n";
694 std::string s_be2_rev = s_be2;
695 std::ranges::reverse(s_be2_rev);
698 std::cout <<
" data: " << d.
pattern <<
"\n";
699 std::cout <<
" s_be2: " << s_be2 <<
"\n";
700 std::cout <<
" s_be2_rev: " << s_be2_rev <<
"\n";
701 std::cout <<
" s_be3_rev: " << s_be3_rev <<
"\n";
704 REQUIRE( s_be2_rev == s_be3_rev );
707template<
size_t BitSize>
734TEST_CASE(
"Bitfield Test 31 Unaligned Reverse",
"[bitfield][bitreverse]") {
static constexpr std::string_view testStringMSB64_le
static uint64_t toInteger(const std::string_view bitPattern)
static constexpr uint64_t testIntLSB64_le
static std::string toBinaryString(const uint64_t v, const size_t bitCount)
static size_t getOneBitCount(std::string_view pattern)
static uint32_t getBitMask(size_t n)
Returns the 32 bit mask of n-bits, i.e.
static constexpr uint64_t testIntMSB64_le
static const std::vector< std::string_view > pyramid32bit_one
static constexpr uint64_t testIntLSB64_be
static constexpr uint32_t UNSIGNED_INT_MAX_VALUE
static constexpr std::string_view testStringLSB64_be
static constexpr std::string_view testStringLSB64_le
static constexpr uint64_t testIntMSB64_be
static constexpr std::string_view testStringMSB64_be
Simple statically sized bitfield template for efficient bit storage access in O(1).
constexpr bitfield_t & reset() noexcept
static constexpr size_type unit_shift
One unit shift amount.
bool putUnit(size_type bitpos, size_type length, unit_type data) noexcept
Writes length bits of given data into this storage, starting with the lowest bit from the storage pos...
bitfield_t & setAll(bool bit) noexcept
Set all bits of this bitfield to the given value bit.
constexpr bool put(size_type bitpos, bool v) noexcept
Writes the bit value v to position bitpos into this storage.
static constexpr size_type unit_bit_size
One unit size in bits.
static constexpr size_type unit_size
Storage size in units.
constexpr void clear() noexcept
constexpr bool clr(size_type bitpos) noexcept
Clear the bit at position bitpos of this storage.
constexpr bool set(size_type bitpos) noexcept
Sets the bit at position bitpos of this storage.
constexpr bitfield_t & reverse() noexcept
bool copyUnit(size_type srcBitpos, size_type dstBitpos, size_type length) noexcept
Copies length bits at position srcBitpos to position dstBitpos, returning the copied bits.
static constexpr size_type unit_byte_size
One unit size in bytes.
std::string toString(size_type bitpos, size_type length, PrefixOpt prefix=PrefixOpt::none) const noexcept
size_type count() const noexcept
bool copy(size_type srcBitpos, size_type dstBitpos) noexcept
Copies the bit at position srcBitpos to position dstBitpos, returning the copied bit-value.
unit_type getUnit(size_type bitpos, size_type length) const noexcept
constexpr bool get(size_type bitpos) const noexcept
static constexpr size_type bit_size
Storage size in bits.
constexpr size_type size() const noexcept
Returns storage size in bits.
constexpr bool flip(size_type bitpos) noexcept
Flips the bit value at position bitpos in this storage.
Simple dynamically heap-sized bitheap for efficient bit storage access in O(1).
std::string toString(size_type bitpos, size_type length, PrefixOpt prefix=PrefixOpt::none) const noexcept
std::pair< bitheap, bool > subbits(size_type bitpos, size_type length) const noexcept
constexpr size_type size() const noexcept
Returns storage size in bits.
constexpr bool put(size_type bitpos, bool v) noexcept
Writes the bit value v to position bitpos into this storage.
constexpr bitheap & reverse() noexcept
bitfield_t< unsigned long, BitSize > bitfield
Simple bitfield template for efficient bit storage access in O(1).
constexpr uint32_t ct_bit_count(uint32_t n) noexcept
Returns the number of set bits within given 32bit integer (w/o branching) in O(1) and constant time (...
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
constexpr size_t bit_count(T n) noexcept
Returns the number of set bits within given unsigned integral.
constexpr std::string format_string(const std::string_view format, const Args &...args)
Safely returns a (non-truncated) string according to snprintf() formatting rules and variable number ...
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.
bit_order_t
Bit order type, i.e.
@ lsb
Identifier for least-significant-bit (lsb) first.
@ msb
Identifier for most-significant-bit (msb) first.
std::string to_string(const bit_order_t v) noexcept
Return std::string representation of the given bit_order_t.
const std::string_view pattern
TestDataBF(const uint64_t bitSize_, const uint64_t value_, const std::string_view pattern_)
std::string toString() const
static std::vector< TestDataBF > testDataBF32Bit
static std::vector< TestDataBF > testDataBF16Bit
static std::ostream & operator<<(std::ostream &out, const TestDataBF &v)
static void test_ValidateTestData(std::string_view prefix, const TestDataBF &d)
static std::vector< TestDataBF > testDataBF64Bit
static void checkOtherBits(const TestDataBF &d, const jau::bitfield_t< StorageType, BitSize > &bf, const size_t lowBitnum, const std::string &msg, const StorageType expBits)
static void testUnalignedBitReverse(std::string_view prefix, const size_t offset, const TestDataBF &d, jau::bitfield_t< StorageType, BitSize > &bf)
static std::vector< uint32_t > testDataOneBit
static jau::bitheap getBitheap(const jau::bit_order_t dataBitOrder, const jau::nsize_t preBits, const jau::nsize_t skipBits, const jau::nsize_t postBits)
static void test_BitCount32_Data(const uint32_t i, const uint32_t expOneBits)
static std::vector< TestDataBF > testDataBF3Bit
static void test_BitCount32_Samples(const uint32_t l)
static void testAlignedBitReverse(std::string_view prefix, const TestDataBF &d, jau::bitfield_t< StorageType, BitSize > &bf)
static void test_AlignedBits(std::string_view prefix, const TestDataBF &d, jau::bitfield_t< StorageType, BitSize1 > &bf1, jau::bitfield_t< StorageType, BitSize2 > &bf2)
static void test_Unaligned(const TestDataBF &d, jau::bitfield_t< StorageType, BitSize > &bf, const size_t lowBitnum)
static void assertEquals(const jau::bitfield_t< StorageType, BitSize > &bf, const size_t bf_off, const uint64_t v, const std::string_view pattern, size_t oneBitCount)
TEST_CASE("Bitfield Test 00", "[bitfield]")