jaulib v1.4.0-2-g788cf73
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
test_bitfield00.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2022-2025 Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11
12#include <cassert>
13#include <cstdlib>
14#include <cstring>
15
16#include <jau/basic_types.hpp>
17#include <jau/bitfield.hpp>
18#include <jau/bitheap.hpp>
19#include <jau/debug.hpp>
20#include <jau/int_math.hpp>
21#include <jau/int_math_ct.hpp>
22#include <jau/io/file_util.hpp>
23#include <jau/io/io_util.hpp>
24#include <jau/string_util.hpp>
25#include <jau/test/catch2_ext.hpp>
26
27// #include "test_httpd.hpp"
28#include "data_bitstream.hpp"
29
30using namespace jau::int_literals;
31
32TEST_CASE( "Bitfield Test 00", "[bitfield]" ) {
33 {
34 const size_t bits = 3_uz*64_uz;
36 REQUIRE(bits == b1.bit_size);
37 REQUIRE(64 == b1.unit_bit_size);
38 REQUIRE(8 == b1.unit_byte_size);
39 REQUIRE(6 == b1.unit_shift);
40 REQUIRE(3 == b1.unit_size);
41 REQUIRE(0 == b1.count());
42 REQUIRE(b1.bit_size == b1.flip().count());
43 REQUIRE(0 == b1.flip().count());
44 REQUIRE(b1.bit_size == b1.flip().count());
45 REQUIRE(0 == b1.reset().count());
46 REQUIRE(b1.bit_size == b1.setAll(true).count());
47 REQUIRE(0 == b1.setAll(false).count());
48 REQUIRE( true == b1.set(64, 2_uz*64_uz, true));
49 REQUIRE(2_uz*64_uz == b1.count());
50 }
51 {
52 const size_t bits = 3_uz*64_uz+4_uz;
54 REQUIRE(bits == b1.bit_size);
55 REQUIRE(64 == b1.unit_bit_size);
56 REQUIRE(8 == b1.unit_byte_size);
57 REQUIRE(6 == b1.unit_shift);
58 REQUIRE(4 == b1.unit_size);
59 REQUIRE(0 == b1.count());
60 REQUIRE(b1.bit_size == b1.flip().count());
61 REQUIRE(0 == b1.flip().count());
62 REQUIRE(b1.bit_size == b1.flip().count());
63 REQUIRE(0 == b1.reset().count());
64 REQUIRE(b1.bit_size == b1.setAll(true).count());
65 REQUIRE(0 == b1.setAll(false).count());
66 REQUIRE( true == b1.set(33, 2_uz*64_uz+2_uz, true));
67 REQUIRE(2_uz*64_uz+2_uz == b1.count());
68 }
69 {
70 const size_t bits = 3_uz*32_uz+4_uz;
72 REQUIRE(bits == b1.bit_size);
73 REQUIRE(32 == b1.unit_bit_size);
74 REQUIRE(4 == b1.unit_byte_size);
75 REQUIRE(5 == b1.unit_shift);
76 REQUIRE(4 == b1.unit_size);
77 REQUIRE(0 == b1.count());
78
79 REQUIRE(b1.bit_size == b1.flip().count());
80 REQUIRE(0 == b1.flip().count());
81 REQUIRE(b1.bit_size == b1.flip().count());
82 REQUIRE(0 == b1.reset().count());
83 REQUIRE(b1.bit_size == b1.setAll(true).count());
84 REQUIRE(0 == b1.setAll(false).count());
85 REQUIRE(true == b1.set(17, 2_uz*32_uz+2_uz, true));
86 REQUIRE(2_uz*32_uz+2_uz == b1.count());
87 }
88 {
89 const size_t bits = 3_uz*8_uz+4_uz;
91 REQUIRE(bits == b1.bit_size);
92 REQUIRE(8 == b1.unit_bit_size);
93 REQUIRE(1 == b1.unit_byte_size);
94 REQUIRE(3 == b1.unit_shift);
95 REQUIRE(4 == b1.unit_size);
96 REQUIRE(0 == b1.count());
97
98 REQUIRE(b1.bit_size == b1.flip().count());
99 REQUIRE(0 == b1.flip().count());
100 REQUIRE(b1.bit_size == b1.flip().count());
101 REQUIRE(0 == b1.reset().count());
102 REQUIRE(b1.bit_size == b1.setAll(true).count());
103 REQUIRE(0 == b1.setAll(false).count());
104 REQUIRE(true == b1.set(5, 2_uz*8_uz+2_uz, true));
105 REQUIRE(2_uz*8_uz+2_uz == b1.count());
106 }
107}
108
109TEST_CASE( "Bitfield Test 01 BitCount32_One", "[bitfield]" ) {
110 const std::vector<std::string_view> &pyramid32bit_one = BitDemoData::pyramid32bit_one;
111 for(size_t i=0; i<pyramid32bit_one.size(); i++) {
112 const uint32_t val0 = 1_u32 << i;
113 const size_t oneBitCountI1 = jau::ct_bit_count(val0);
114 const size_t oneBitCountI2 = jau::bit_count(val0);
115 const std::string_view pattern0 = pyramid32bit_one[i];
116 const uint32_t val1 = BitDemoData::toInteger(pattern0);
117 const std::string pattern1 = BitDemoData::toBinaryString(val0, 32);
118 const size_t oneBitCount0 = BitDemoData::getOneBitCount(pattern0);
119 // fprintf(stderr, "Round %02zu: 0x%08x %s, c %zu / %zu / %zu\n : 0x%08x %s\n",
120 // i, val0, std::string(pattern0).c_str(), oneBitCount0, oneBitCountI1, oneBitCountI2,
121 // val1, pattern1.c_str());
122 REQUIRE(val0 == val1);
123 REQUIRE(pattern0 == pattern1);
124
125 REQUIRE(oneBitCount0 == oneBitCountI1);
126 REQUIRE(oneBitCount0 == oneBitCountI2);
127 }
128}
129
130static jau::bitheap getBitheap(const jau::bit_order_t dataBitOrder,
131 const jau::nsize_t preBits, const jau::nsize_t skipBits, const jau::nsize_t postBits) {
132 const jau::nsize_t totalBits = preBits+postBits;
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);
135
136 // msb 11111010 11011110 10101111 11111110 11011110 10101111 11001010 11111110
137 // lsb 01111111 01010011 11110101 01111011 01111111 11110101 01111011 01011111
138 std::string_view in = BitDemoData::testStringMSB64_be;
139 jau::bitheap source(in);
140 if( jau::bit_order_t::msb != dataBitOrder ) {
141 source.reverse();
142 REQUIRE(BitDemoData::testStringLSB64_le == source.toString());
143 }
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);
149
150 jau::bitheap r(preBits+postBits);
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());
157 return r;
158}
159
160TEST_CASE("Bitfield Test 01 subbits", "[bitfield][subbits]") {
161 // msb 11111010 11011110 10101111 11111110 11011110 10101111 11001010 11111110
162 REQUIRE(jau::bitheap("11111110") == getBitheap(jau::bit_order_t::msb, 0, 0, 8));
163 REQUIRE(jau::bitheap("010") == getBitheap(jau::bit_order_t::msb, 0, 8, 3));
164 REQUIRE(jau::bitheap("01011111110") == getBitheap(jau::bit_order_t::msb, 8, 0, 3));
165 // msb 11111010 11011110 10101111 11111110 11011110 10101111 11001010 11111110
166 // lsb 01111111 01010011 11110101 01111011 01111111 11110101 01111011 01011111
167 REQUIRE(jau::bitheap("01011111") == getBitheap(jau::bit_order_t::lsb, 0, 0, 8));
168 REQUIRE(jau::bitheap("011") == getBitheap(jau::bit_order_t::lsb, 0, 8, 3));
169 REQUIRE(jau::bitheap("01101011111") == getBitheap(jau::bit_order_t::lsb, 8, 0, 3));
170}
171
172/**
173 * ***********************************************************************************
174 * ***********************************************************************************
175 * ***********************************************************************************
176 */
177
178static void test_BitCount32_Samples(const uint32_t l) {
179 const size_t oneBitCountL = jau::bit_count(l);
180 const size_t oneBitCount1 = jau::ct_bit_count(l);
181 // fprintf(stderr, "Round 0x%08x, c %zu / %zu\n", l, oneBitCountL, oneBitCount1);
182 REQUIRE(oneBitCountL == oneBitCount1);
183}
184
185TEST_CASE( "Bitfield Test 10 BitCount32_One", "[bitfield]" ) {
186 const uint32_t MAX = BitDemoData::UNSIGNED_INT_MAX_VALUE;
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;
191
192 for(uint32_t l=0; l<=0x1FF; ++l) {
194 }
195 for(uint32_t l=MAX_half_minus; l<=MAX_half_plus; ++l) {
197 }
198 for(uint32_t l=MAX_minus-1; l++ <MAX; ) {
200 }
201}
202
203/**
204 * ***********************************************************************************
205 * ***********************************************************************************
206 * ***********************************************************************************
207 */
208
209static std::vector<uint32_t> testDataOneBit = {
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,
214 0x0FFFFFF0, 24,
215 0x55555555, 16,
216 0x7F53F57B, 23,
217 0xFEA7EAF6, 23, /* << 1 */
218 0x80000000, 1,
219 0xAAAAAAAA, 16,
220 0xC0C0C0C0, 8,
221 0xFF000000, 8,
222 0xFFFFFFFF, 32
223};
224
225static void test_BitCount32_Data(const uint32_t i, const uint32_t expOneBits) {
226 const size_t oneBitCountI = jau::bit_count(i);
227 const size_t oneBitCount1 = jau::ct_bit_count(i);
228 // fprintf(stderr, "Round 0x%08x, c %zu / %zu\n", i, oneBitCountI, oneBitCount1);
229 REQUIRE(expOneBits == oneBitCountI);
230 REQUIRE(oneBitCountI == oneBitCount1);
231}
232
233TEST_CASE( "Bitfield Test 11 BitCount32_Data", "[bitfield]" ) {
234 for(size_t i = 0; i<testDataOneBit.size(); i+=2) {
236 }
237}
238
239
240/**
241 * ***********************************************************************************
242 * ***********************************************************************************
243 * ***********************************************************************************
244 */
245
247 const size_t bitSize;
248 const uint64_t val;
249 const std::string_view pattern;
250
251 TestDataBF(const uint64_t bitSize_, const uint64_t value_, const std::string_view pattern_)
252 : bitSize(bitSize_), val(value_), pattern(pattern_) { }
253 std::string toString() const { return "BF[bitSize " + std::to_string(bitSize)+", val "+jau::toHexString(val)+", pattern '"+std::string(pattern)+"']"; }
254};
255static std::ostream &operator<<(std::ostream &out, const TestDataBF &v) {
256 return out << v.toString();
257}
258
259static std::vector<TestDataBF> testDataBF64Bit = {
264
265 TestDataBF(64, 0x04030201AFFECAFE, "0000010000000011000000100000000110101111111111101100101011111110"),
266 TestDataBF(64, 0xAFFECAFE04030201, "1010111111111110110010101111111000000100000000110000001000000001"),
267 TestDataBF(64, 0xDEADBEEFDEADBEEF, "1101111010101101101111101110111111011110101011011011111011101111")
268};
269
270
271static std::vector<TestDataBF> testDataBF32Bit = {
272 // H->L : 0x04030201: 00000100 00000011 00000010 00000001
273 TestDataBF(32, 0x04030201, "00000100000000110000001000000001"),
274
275 // H->L : 0xAFFECAFE: 10101111 11111110 11001010 11111110
276 TestDataBF(32, 0xAFFECAFE, "10101111111111101100101011111110"),
277 // H->L : 0xDEADBEEF: 11011110 10101101 10111110 11101111
278 TestDataBF(32, 0xDEADBEEF, "11011110101011011011111011101111")
279};
280
281static std::vector<TestDataBF> testDataBF16Bit = {
282 // H->L : 0x0201: 00000100 00000011 00000010 00000001
283 TestDataBF(16, 0x0201, "0000001000000001"),
284 // H->L : 0x0403: 00000100 00000011
285 TestDataBF(16, 0x0403, "0000010000000011"),
286
287 // H->L : 0xAFFE: 10101111 11111110
288 TestDataBF(16, 0xAFFE, "1010111111111110"),
289 // H->L : 0xCAFE: 11001010 11111110
290 TestDataBF(16, 0xCAFE, "1100101011111110"),
291
292 // H->L : 0xDEADBEEF: 11011110 10101101 10111110 11101111
293 TestDataBF(16, 0xDEAD, "1101111010101101"),
294 TestDataBF(16, 0xBEEF, "1011111011101111")
295};
296
297static std::vector<TestDataBF> testDataBF3Bit = {
298 TestDataBF(3, 0x01, "001"),
299 TestDataBF(3, 0x02, "010"),
300 TestDataBF(3, 0x05, "101")
301};
302
303static void test_ValidateTestData(std::string_view prefix, const TestDataBF& d) {
304 std::cout << "Test " << prefix << ": " << d << "\n";
305 const size_t oneBitCount0 = jau::bit_count(d.val);
306 const size_t oneBitCount1 = BitDemoData::getOneBitCount(d.pattern);
307 REQUIRE(oneBitCount0 == oneBitCount1);
308 // Test: BF[bitSize 64, val 0xdeafcafe, pattern '1111101011011110101011111111111011011110101011111100101011111110'
309
310 const std::string& pattern0 = BitDemoData::toBinaryString(d.val, d.bitSize);
311 REQUIRE(d.pattern == pattern0);
312
313 const uint64_t val1 = BitDemoData::toInteger(d.pattern);
314 REQUIRE(d.val == val1);
315 REQUIRE(d.bitSize == pattern0.length());
316}
317
318TEST_CASE( "Bitfield Test 20 ValidateTestData", "[bitfield]" ) {
319 for(size_t i=0; i<testDataBF64Bit.size(); ++i) {
320 test_ValidateTestData( "BF64Bit."+std::to_string(i), testDataBF64Bit[i] );
321 }
322 for(size_t i=0; i<testDataBF32Bit.size(); ++i) {
323 test_ValidateTestData( "BF32Bit."+std::to_string(i), testDataBF32Bit[i] );
324 }
325 for(size_t i=0; i<testDataBF16Bit.size(); ++i) {
326 test_ValidateTestData( "BF16Bit."+std::to_string(i), testDataBF16Bit[i] );
327 }
328 for(size_t i=0; i<testDataBF3Bit.size(); ++i) {
329 test_ValidateTestData( "BF03Bit."+std::to_string(i), testDataBF3Bit[i] );
330 }
331}
332
333
334/**
335 * ***********************************************************************************
336 * ***********************************************************************************
337 * ***********************************************************************************
338 */
339
340template<jau::req::unsigned_integral StorageType, size_t BitSize>
341static void assertEquals(const jau::bitfield_t<StorageType, BitSize>& bf, const size_t bf_off, const uint64_t v,
342 const std::string_view pattern, size_t oneBitCount)
343{
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];
349 (void)oneBitCount;
350 // fprintf(stderr, "Pos %04zu: Value 0x%08" PRIu64 "x / %s, c %zu\n", i, v, std::string(pattern).c_str(), oneBitCount);
351 REQUIRE(exp0 == has);
352 REQUIRE(exp1 == has);
353 }
354}
355
356template<jau::req::unsigned_integral StorageType, size_t BitSize1, size_t BitSize2>
357static void test_AlignedBits(std::string_view prefix, const TestDataBF& d,
359{
360 std::cout << "Test " << prefix << ": " << d << "\n";
361
362 const size_t oneBitCount = jau::bit_count(d.val);
363
364 REQUIRE(true == bf1.putUnit( 0, d.bitSize, d.val) );
365 REQUIRE(d.val == bf1.getUnit(0, d.bitSize));
366 REQUIRE(oneBitCount == bf1.count());
367 // std::cout << "Test " << prefix << ".1 - bf1: " << bf1 << "\n";
368 assertEquals(bf1, 0, d.val, d.pattern, oneBitCount);
369
370 REQUIRE(true == bf2.putUnit( 0, d.bitSize, d.val));
371 REQUIRE(d.val == bf2.getUnit( 0, d.bitSize));
372 REQUIRE(oneBitCount*1 == bf2.count());
373 // std::cout << "Test " << prefix << ".2 - bf2: " << bf2 << "\n";
374 assertEquals(bf2, 0, d.val, d.pattern, oneBitCount);
375
376 REQUIRE(true == bf2.putUnit(128, d.bitSize, d.val));
377 REQUIRE(d.val == bf2.getUnit(128, d.bitSize));
378 REQUIRE(oneBitCount*2 == bf2.count());
379 // std::cout << "Test " << prefix << ".3 - bf2: " << bf2 << "\n";
380 assertEquals(bf2, 128, d.val, d.pattern, oneBitCount);
381
382 REQUIRE(true == bf2.copyUnit(0, 233, d.bitSize));
383 REQUIRE(d.val == bf2.getUnit(233, d.bitSize));
384
385 // std::cout << "Test " << prefix << ".4 - bf2: " << bf2 << "\n";
386 REQUIRE(oneBitCount*3 == bf2.count());
387 assertEquals(bf2, 233, d.val, d.pattern, oneBitCount);
388}
389static void test_AlignedBits(std::string_view prefix, const TestDataBF& d) {
390 {
393 test_AlignedBits(std::string(prefix)+".a", d, bf1, bf2);
394 }
395 if( d.bitSize <= 32 ) {
398 test_AlignedBits(std::string(prefix)+".b", d, bf1, bf2);
399 }
400}
401
402TEST_CASE( "Bitfield Test 21 Alignedbits", "[bitfield]" ) {
403 for(size_t i=0; i<testDataBF64Bit.size(); ++i) {
404 test_AlignedBits( "BF64Bit."+std::to_string(i), testDataBF64Bit[i] );
405 }
406 for(size_t i=0; i<testDataBF32Bit.size(); ++i) {
407 test_AlignedBits( "BF32Bit."+std::to_string(i), testDataBF32Bit[i] );
408 }
409 for(size_t i=0; i<testDataBF16Bit.size(); ++i) {
410 test_AlignedBits( "BF16Bit."+std::to_string(i), testDataBF16Bit[i] );
411 }
412 for(size_t i=0; i<testDataBF3Bit.size(); ++i) {
413 test_AlignedBits( "BF03Bit."+std::to_string(i), testDataBF3Bit[i] );
414 }
415}
416
417
418/**
419 * ***********************************************************************************
420 * ***********************************************************************************
421 * ***********************************************************************************
422 */
423
424template<jau::req::unsigned_integral StorageType, size_t BitSize>
425static void checkOtherBits(const TestDataBF& d, const jau::bitfield_t<StorageType, BitSize>& bf, const size_t lowBitnum,
426 const std::string& msg, const StorageType expBits) {
427 const size_t highBitnum = lowBitnum + d.bitSize - 1;
428 // fprintf(stderr,msg+": [0"+".."+"("+lowBitnum+".."+highBitnum+").."+(bf.size()-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);
432 const StorageType exp = expBits & BitDemoData::getBitMask(len);
433 // fprintf(stderr," <"+i+".."+(i+len-1)+">, exp "+BitDemoData.toHexString(exp));
434 REQUIRE_MSG(msg+", bitpos "+std::to_string(i), exp == val);
435 }
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);
439 const StorageType exp = expBits & BitDemoData::getBitMask(len);
440 // fprintf(stderr," <"+i+".."+(i+len-1)+">, exp "+BitDemoData.toHexString(exp));
441 REQUIRE_MSG(msg+", bitpos "+std::to_string(i), exp == val);
442 }
443}
444
445template<jau::req::unsigned_integral StorageType, size_t BitSize>
446static void test_Unaligned(const TestDataBF &d, jau::bitfield_t<StorageType, BitSize>& bf, const size_t lowBitnum) {
447 const size_t maxBitpos = bf.size()-d.bitSize;
448 const size_t oneBitCount = jau::bit_count(d.val);
449
450 const std::string msg = jau::format_string("Value 0x%08" PRIx64 " / %s, l %zu/%zu, c %zu, lbPos %zu -> %zu",
451 d.val, std::string(d.pattern).c_str(), d.bitSize, bf.size(), oneBitCount, lowBitnum, maxBitpos);
452
453 //
454 // via putUnit
455 //
456 REQUIRE( true == bf.putUnit( lowBitnum, d.bitSize, d.val) );
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);
461 }
462 REQUIRE_MSG(msg, d.val == bf.getUnit( lowBitnum, d.bitSize));
463 REQUIRE_MSG(msg, oneBitCount == bf.count());
464 assertEquals(bf, lowBitnum, d.val, d.pattern, oneBitCount);
465
466 //
467 // via copyUnit
468 //
469 if( lowBitnum < maxBitpos ) {
470 // copy bits 1 forward
471 // clear trailing orig bit
472 REQUIRE_MSG(msg, true == bf.copyUnit(lowBitnum, lowBitnum+1, d.bitSize));
473 REQUIRE(true == bf.clr(lowBitnum));
474 REQUIRE_MSG(msg, d.val == bf.getUnit(lowBitnum+1, d.bitSize));
475 REQUIRE_MSG(msg, oneBitCount == bf.count());
476 assertEquals(bf, lowBitnum+1, d.val, d.pattern, oneBitCount);
477 }
478
479 // test put/get
480 bf.reset();
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]);
486
487 //
488 // via put/get
489 //
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]);
495 }
496 REQUIRE_MSG(msg, d.val == bf.getUnit(lowBitnum, d.bitSize));
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);
501 }
502 REQUIRE_MSG(msg, oneBitCount == bf.count());
503 assertEquals(bf, lowBitnum, d.val, d.pattern, oneBitCount);
504
505 //
506 // via copy
507 //
508 if( lowBitnum < maxBitpos ) {
509 // copy bits 1 forward
510 // clear trailing orig bit
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);
516 }
517 REQUIRE(true == bf.clr(lowBitnum));
518 REQUIRE_MSG(msg, d.val == bf.getUnit( lowBitnum+1, d.bitSize));
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);
523 }
524 REQUIRE_MSG(msg, oneBitCount == bf.count());
525 assertEquals(bf, lowBitnum+1, d.val, d.pattern, oneBitCount);
526 }
527
528 //
529 // via set/clear
530 //
531 {
532 REQUIRE(0 == bf.setAll(false).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));
536 } else {
537 REQUIRE(true == bf.clr(lowBitnum+i));
538 }
539 }
540 REQUIRE_MSG(msg, d.val == bf.getUnit(lowBitnum, d.bitSize));
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);
545 }
546 REQUIRE_MSG(msg, oneBitCount == bf.count());
547 assertEquals(bf, lowBitnum, d.val, d.pattern, oneBitCount);
548 }
549 {
550 REQUIRE(bf.bit_size == bf.setAll(true).count());
551 REQUIRE(true == bf.set(0, lowBitnum, false));
552 REQUIRE(true == bf.set(lowBitnum+d.bitSize, bf.bit_size-(lowBitnum+d.bitSize), false));
553 REQUIRE_MSG(msg, d.bitSize == bf.count());
554 for(size_t i=0; i<d.bitSize; i++) {
555 if( d.val & ( 1_u64 << i ) ) {
556 REQUIRE(true == bf.set(lowBitnum+i));
557 } else {
558 REQUIRE(true == bf.clr(lowBitnum+i));
559 }
560 }
561 REQUIRE_MSG(msg, d.val == bf.getUnit(lowBitnum, d.bitSize));
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);
566 }
567 if( oneBitCount != bf.count() ) {
568 REQUIRE_MSG(msg, oneBitCount == bf.count());
569 }
570 assertEquals(bf, lowBitnum, d.val, d.pattern, oneBitCount);
571 }
572
573 //
574 // Validate 'other bits' put32/get32
575 //
576 bf.setAll(false);
577 REQUIRE(true == bf.putUnit( lowBitnum, d.bitSize, d.val));
578 checkOtherBits(d, bf, lowBitnum, msg, StorageType(0));
579
580 bf.setAll(true);
581 REQUIRE(true == bf.putUnit( lowBitnum, d.bitSize, d.val));
582 checkOtherBits(d, bf, lowBitnum, msg, StorageType(BitDemoData::UNSIGNED_INT_MAX_VALUE));
583}
584
585template<jau::req::unsigned_integral StorageType, size_t BitSize>
587 const size_t maxBitpos = bf.size()-d.bitSize;
588 for(size_t i=0; i<=maxBitpos; i++) {
589 bf.setAll(false);
590 test_Unaligned(d, bf, i);
591 }
592}
593
594template<size_t BitSize1, size_t BitSize2>
601
602TEST_CASE( "Bitfield Test 22 Unalignedbits", "[bitfield]" ) {
603 for(const auto & i : testDataBF64Bit) {
605 }
606 for(const auto & i : testDataBF32Bit) {
608 }
609 for(const auto & i : testDataBF16Bit) {
611 }
612 for(const auto & i : testDataBF3Bit) {
614 }
615}
616
617
618template<jau::req::unsigned_integral StorageType, size_t BitSize>
620 const bool verbose = true;
621 if( verbose ) {
622 std::cout << prefix << ": " << d << "\n";
623 std::cout << " bf bit-size[unit " << bf.unit_bit_size << ", total " << bf.bit_size << "], units " << bf.unit_size << "\n";
624 }
625 bf.clear();
626 REQUIRE( true == bf.put(0, d.pattern) );
627
628 std::string s_be2 = bf.toString();
629 std::string s_be2_rev = s_be2;
630 std::ranges::reverse(s_be2_rev);
631 std::string s_be3_rev = bf.reverse().toString();
632 if( verbose ) {
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";
637 }
638 REQUIRE( d.pattern == s_be2 );
639 REQUIRE( s_be2_rev == s_be3_rev );
640}
641
642template<size_t BitSize>
653
654TEST_CASE("Bitfield Test 30 Aligned Reverse", "[bitfield][bitreverse]") {
655 {
658 has.reverse();
659 REQUIRE(exp == has);
661 }
662 {
664 source.reverse();
666 REQUIRE(BitDemoData::testStringLSB64_le == source.toString());
667 }
668
669 for(size_t i=0; i<testDataBF64Bit.size(); ++i) {
670 testAlignedBitReverse<64>( "BF64Bit."+std::to_string(i), testDataBF64Bit[i] );
671 }
672 for(size_t i=0; i<testDataBF32Bit.size(); ++i) {
673 testAlignedBitReverse<32>( "BF32Bit."+std::to_string(i), testDataBF32Bit[i] );
674 }
675 for(size_t i=0; i<testDataBF16Bit.size(); ++i) {
676 testAlignedBitReverse<16>( "BF16Bit."+std::to_string(i), testDataBF16Bit[i] );
677 }
678 for(size_t i=0; i<testDataBF3Bit.size(); ++i) {
679 testAlignedBitReverse<3>( "BF03Bit."+std::to_string(i), testDataBF3Bit[i] );
680 }
681}
682
683template<jau::req::unsigned_integral StorageType, size_t BitSize>
684static void testUnalignedBitReverse(std::string_view prefix, const size_t offset, const TestDataBF& d, jau::bitfield_t<StorageType, BitSize>& bf) {
685 const bool verbose = true;
686 if( verbose ) {
687 std::cout << prefix << ", offset " << offset << ": " << d << "\n";
688 std::cout << " bf bit-size[unit " << bf.unit_bit_size << ", total " << bf.bit_size << "], units " << bf.unit_size << "\n";
689 }
690 bf.clear();
691 REQUIRE( true == bf.put(offset, d.pattern) );
692
693 std::string s_be2 = bf.toString(offset, d.bitSize);
694 std::string s_be2_rev = s_be2;
695 std::ranges::reverse(s_be2_rev);
696 std::string s_be3_rev = bf.reverse().toString(bf.size()-d.bitSize-offset, d.bitSize);
697 if( verbose ) {
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";
702 }
703 REQUIRE( d.pattern == s_be2 );
704 REQUIRE( s_be2_rev == s_be3_rev );
705}
706
707template<size_t BitSize>
708static void testUnalignedBitReverse(std::string_view prefix, const TestDataBF& d) {
713 testUnalignedBitReverse( prefix, 0, d, bf1 );
714 testUnalignedBitReverse( prefix, 1, d, bf1 );
715 testUnalignedBitReverse( prefix, 32, d, bf1 );
716 testUnalignedBitReverse( prefix, 33, d, bf1 );
717
718 testUnalignedBitReverse( prefix, 0, d, bf2 );
719 testUnalignedBitReverse( prefix, 1, d, bf2 );
720 testUnalignedBitReverse( prefix, 32, d, bf2 );
721 testUnalignedBitReverse( prefix, 33, d, bf2 );
722
723 testUnalignedBitReverse( prefix, 0, d, bf3 );
724 testUnalignedBitReverse( prefix, 1, d, bf3 );
725 testUnalignedBitReverse( prefix, 32, d, bf3 );
726 testUnalignedBitReverse( prefix, 33, d, bf3 );
727
728 testUnalignedBitReverse( prefix, 0, d, bf4 );
729 testUnalignedBitReverse( prefix, 1, d, bf4 );
730 testUnalignedBitReverse( prefix, 32, d, bf4 );
731 testUnalignedBitReverse( prefix, 33, d, bf4 );
732}
733
734TEST_CASE("Bitfield Test 31 Unaligned Reverse", "[bitfield][bitreverse]") {
735 for(size_t i=0; i<testDataBF64Bit.size(); ++i) {
736 testUnalignedBitReverse<64*2+33>( "BF64Bit."+std::to_string(i), testDataBF64Bit[i] );
737 }
738 for(size_t i=0; i<testDataBF32Bit.size(); ++i) {
739 testUnalignedBitReverse<32*2+33>( "BF32Bit."+std::to_string(i), testDataBF32Bit[i] );
740 }
741 for(size_t i=0; i<testDataBF16Bit.size(); ++i) {
742 testUnalignedBitReverse<16*2+33>( "BF16Bit."+std::to_string(i), testDataBF16Bit[i] );
743 }
744 for(size_t i=0; i<testDataBF3Bit.size(); ++i) {
745 testUnalignedBitReverse<3*2+33>( "BF03Bit."+std::to_string(i), testDataBF3Bit[i] );
746 }
747}
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).
Definition bitfield.hpp:53
constexpr bitfield_t & reset() noexcept
Definition bitfield.hpp:101
static constexpr size_type unit_shift
One unit shift amount.
Definition bitfield.hpp:59
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...
Definition bitfield.hpp:242
bitfield_t & setAll(bool bit) noexcept
Set all bits of this bitfield to the given value bit.
Definition bitfield.hpp:342
constexpr bool put(size_type bitpos, bool v) noexcept
Writes the bit value v to position bitpos into this storage.
Definition bitfield.hpp:122
static constexpr size_type unit_bit_size
One unit size in bits.
Definition bitfield.hpp:58
static constexpr size_type unit_size
Storage size in units.
Definition bitfield.hpp:66
constexpr void clear() noexcept
Definition bitfield.hpp:97
constexpr bool clr(size_type bitpos) noexcept
Clear the bit at position bitpos of this storage.
Definition bitfield.hpp:196
constexpr bool set(size_type bitpos) noexcept
Sets the bit at position bitpos of this storage.
Definition bitfield.hpp:191
constexpr bitfield_t & reverse() noexcept
Definition bitfield.hpp:165
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.
Definition bitfield.hpp:351
static constexpr size_type unit_byte_size
One unit size in bytes.
Definition bitfield.hpp:57
std::string toString(size_type bitpos, size_type length, PrefixOpt prefix=PrefixOpt::none) const noexcept
Definition bitfield.hpp:442
size_type count() const noexcept
Definition bitfield.hpp:356
bool copy(size_type srcBitpos, size_type dstBitpos) noexcept
Copies the bit at position srcBitpos to position dstBitpos, returning the copied bit-value.
Definition bitfield.hpp:207
unit_type getUnit(size_type bitpos, size_type length) const noexcept
Definition bitfield.hpp:212
constexpr bool get(size_type bitpos) const noexcept
Definition bitfield.hpp:110
static constexpr size_type bit_size
Storage size in bits.
Definition bitfield.hpp:60
constexpr size_type size() const noexcept
Returns storage size in bits.
Definition bitfield.hpp:63
constexpr bool flip(size_type bitpos) noexcept
Flips the bit value at position bitpos in this storage.
Definition bitfield.hpp:140
Simple dynamically heap-sized bitheap for efficient bit storage access in O(1).
Definition bitheap.hpp:49
std::string toString(size_type bitpos, size_type length, PrefixOpt prefix=PrefixOpt::none) const noexcept
Definition bitheap.hpp:450
std::pair< bitheap, bool > subbits(size_type bitpos, size_type length) const noexcept
Definition bitheap.hpp:419
constexpr size_type size() const noexcept
Returns storage size in bits.
Definition bitheap.hpp:58
constexpr bool put(size_type bitpos, bool v) noexcept
Writes the bit value v to position bitpos into this storage.
Definition bitheap.hpp:133
constexpr bitheap & reverse() noexcept
Definition bitheap.hpp:176
bitfield_t< unsigned long, BitSize > bitfield
Simple bitfield template for efficient bit storage access in O(1).
Definition bitfield.hpp:499
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.
Definition int_types.hpp:55
constexpr size_t bit_count(T n) noexcept
Returns the number of set bits within given unsigned integral.
Definition int_math.hpp:220
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 uint64_t val
const std::string_view pattern
const size_t bitSize
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]")