10#include "gtest/gtest.h"
23TEST(BitVectorTest, BasicConstructionAndAccess) {
24 std::vector<uint8_t>
data{0xAA,
27 EXPECT_EQ(bv.width(), 16u);
29 EXPECT_EQ(bv.getBit(0),
false);
30 EXPECT_EQ(bv.getBit(1),
true);
31 EXPECT_EQ(bv.getBit(2),
false);
32 EXPECT_EQ(bv.getBit(3),
true);
33 EXPECT_EQ(bv.getBit(7),
true);
35 EXPECT_TRUE(bv.getBit(8));
36 EXPECT_TRUE(bv.getBit(9));
37 EXPECT_TRUE(bv.getBit(10));
38 EXPECT_TRUE(bv.getBit(11));
39 EXPECT_FALSE(bv.getBit(12));
42TEST(BitVectorTest, ShiftRightShrinksWidth) {
45 for (
int i = 0; i < 4; ++i)
48 EXPECT_EQ(bv.width(), 14u);
50 EXPECT_TRUE(bv.getBit(0));
51 EXPECT_TRUE(bv.getBit(1));
53 EXPECT_THROW(bv >>= 20, std::out_of_range);
56TEST(BitVectorTest, ShiftLeftIncreaseWidth) {
58 for (
int i = 0; i < 8; ++i)
61 EXPECT_EQ(bv.width(), 20u);
64 for (
int i = 0; i < 4; ++i)
65 EXPECT_FALSE(bv.getBit(i));
68 for (
int i = 4; i < 12; ++i)
69 EXPECT_TRUE(bv.getBit(i));
72 for (
int i = 12; i < 20; ++i)
73 EXPECT_FALSE(bv.getBit(i));
76TEST(BitVectorTest, BitwiseOps) {
79 for (
int i = 0; i < 8; ++i) {
80 a.setBit(i, (i % 2) == 1);
81 b.setBit(i, (i / 2) % 2 ==
87 EXPECT_EQ(c_and.width(), 8u);
89 for (
int i = 0; i < 8; ++i) {
90 bool abit = a.getBit(i);
91 bool bbit = b.getBit(i);
92 EXPECT_EQ(c_and.getBit(i), (abit & bbit));
93 EXPECT_EQ(c_or.getBit(i), (abit | bbit));
94 EXPECT_EQ(c_xor.getBit(i), (abit ^ bbit));
98TEST(BitVectorTest, EqualityAlignedAndMisaligned) {
102 std::vector<uint8_t> raw{0xAA, 0x0F};
105 EXPECT_TRUE(a0 == b0);
114 EXPECT_TRUE(aShift == bShift);
118 b.setBit(3, !b.getBit(3));
119 EXPECT_TRUE(aShift != bShift);
122TEST(BitVectorTest, ZeroWidthAndBitwise) {
126 EXPECT_EQ(a.width(), 0u);
127 EXPECT_EQ((a & b).width(), 0u);
128 EXPECT_EQ((a | b).width(), 0u);
129 EXPECT_EQ((a ^ b).width(), 0u);
132TEST(BitVectorTest, ZeroWidthShiftBehavior) {
135 EXPECT_THROW(z >>= 1, std::out_of_range);
137 EXPECT_NO_THROW(z >>= 0);
139 EXPECT_NO_THROW(z <<= 5);
140 EXPECT_EQ(z.width(), 5u);
143TEST(BitVectorTest, CrossByteAccessAndShift) {
144 std::vector<uint8_t>
data{0xF0, 0x55, 0xCC};
147 EXPECT_EQ(bv.width(), 21u);
150 EXPECT_FALSE(bv.getBit(0));
155TEST(BitVectorTest, MisalignedBitwiseFallback) {
156 std::vector<uint8_t> da{0xAA, 0xCC};
157 std::vector<uint8_t> db{0x0F, 0xF0};
165 for (
size_t i = 0; i < a.width(); ++i) {
166 bool abit = a.getBit(i);
167 bool bbit = b.getBit(i);
168 EXPECT_EQ(rAnd.getBit(i), (abit & bbit));
169 EXPECT_EQ(rOr.getBit(i), (abit | bbit));
170 EXPECT_EQ(rXor.getBit(i), (abit ^ bbit));
174TEST(BitVectorTest, TailByteBitwiseNoMasking) {
177 std::vector<uint8_t> da{0b10101111, 0b00000001};
178 std::vector<uint8_t> db{0b11000011, 0b00000001};
182 for (
size_t i = 0; i < 13; ++i)
183 EXPECT_EQ(r.getBit(i), a.getBit(i) ^ b.getBit(i));
186TEST(BitVectorTest, ConstructorInvalidBitIndex) {
187 std::vector<uint8_t> raw{0xAA, 0xBB};
188 EXPECT_THROW(
BitVector(raw, 16, 8), std::invalid_argument);
191TEST(BitVectorTest, ConstructorWidthExceedsStorage) {
192 std::vector<uint8_t> raw{0xAA};
193 EXPECT_THROW(
BitVector(raw, 16, 0), std::invalid_argument);
196TEST(BitVectorTest, GetBitOutOfRange) {
197 std::vector<uint8_t> raw{0x44};
199 EXPECT_THROW(bv.getBit(8), std::out_of_range);
202TEST(BitVectorTest, SetBitOutOfRange) {
204 EXPECT_THROW(bv.setBit(4,
true), std::out_of_range);
207TEST(BitVectorTest, ZeroWidthGetBitThrows) {
209 EXPECT_THROW(z.getBit(0), std::out_of_range);
212TEST(BitVectorTest, BitwiseWidthMismatchThrows) {
213 std::vector<uint8_t> raw0{0x00};
214 std::vector<uint8_t> raw1{0x00};
217 EXPECT_THROW((
void)(a & b), std::invalid_argument);
218 EXPECT_THROW((
void)(a | b), std::invalid_argument);
219 EXPECT_THROW((
void)(a ^ b), std::invalid_argument);
222TEST(BitVectorTest, NonOwningModificationThrows) {
223 std::vector<uint8_t> raw{0x00, 0x00};
227 EXPECT_THROW(view.getBit(99), std::out_of_range);
231 EXPECT_NO_THROW(owned.setBit(0,
true));
232 EXPECT_TRUE(owned.getBit(0));
236 EXPECT_EQ(trunc.width(), 16u);
238 owned.setBit(5,
true);
239 EXPECT_TRUE(owned.getBit(5));
242TEST(BitVectorTest, PackedSerializationRoundTrip) {
247 uint64_t packed_value = 0;
248 size_t bit_offset = 0;
251 auto pack = [&](uint64_t value,
size_t width) {
252 uint64_t
mask = (width == 64) ? ~0ULL : ((1ULL << width) - 1ULL);
253 packed_value |= ((value &
mask) << bit_offset);
265 ASSERT_EQ(bit_offset, 27u);
268 std::vector<uint8_t> bytes((27 + 7) / 8, 0);
269 for (
size_t i = 0; i < bytes.size(); ++i) {
270 bytes[i] =
static_cast<uint8_t
>((packed_value >> (8 * i)) & 0xFF);
277 for (
size_t i = 0; i < 1; ++i)
278 if (stream.getBit(i))
283 for (
size_t i = 0; i < 7; ++i)
284 if (stream.getBit(1 + i))
286 EXPECT_EQ(ru7, 0x55u);
289 for (
size_t i = 0; i < 1; ++i)
290 if (stream.getBit(8 + i))
295 for (
size_t i = 0; i < 5; ++i)
296 if (stream.getBit(9 + i))
297 rs5raw |= (1ULL << i);
298 EXPECT_EQ(rs5raw, 27u);
301 for (
size_t i = 0; i < 1; ++i)
302 if (stream.getBit(14 + i))
307 for (
size_t i = 0; i < 9; ++i)
308 if (stream.getBit(15 + i))
310 EXPECT_EQ(ru9, 0x1A5u);
313 for (
size_t i = 0; i < 3; ++i)
314 if (stream.getBit(24 + i))
319TEST(IntTest, ConstructionAndSignExtension) {
325 mbv.setBit(2,
false);
333 EXPECT_EQ(
static_cast<int64_t
>(v), -5);
335 bool expected[8] = {
true,
true,
false,
true,
true,
true,
true,
true};
336 for (
int i = 0; i < 8; ++i)
337 EXPECT_EQ(v.getBit(i), expected[i]) <<
"bit " << i;
340TEST(IntTest, SignExtendOnNarrowTo64) {
343 for (
size_t i = 0; i < 12; ++i)
347 EXPECT_EQ(
static_cast<int64_t
>(v), -1);
349 EXPECT_TRUE(v.getBit(11));
352TEST(IntTest, OverflowSigned) {
355 big.setBit(64,
true);
357 EXPECT_THROW((
void)
static_cast<int64_t
>(v), std::overflow_error);
360TEST(IntTest, WidthOneValues) {
366 mbv_neg.setBit(0,
true);
371 EXPECT_EQ(
static_cast<int64_t
>(z), 0);
372 EXPECT_EQ(
static_cast<int64_t
>(neg), -1);
375TEST(IntTest, LargeWidthSignExtendedConversions) {
378 for (
size_t i = 0; i < 130; ++i)
379 mbv_negAll.setBit(i,
true);
383 mbv_posSmall.setBit(0,
true);
384 mbv_posSmall.setBit(2,
true);
386 Int negAll(mbv_negAll);
387 Int posSmall(mbv_posSmall);
389 EXPECT_EQ(
static_cast<int64_t
>(negAll), -1);
390 EXPECT_EQ(
static_cast<int64_t
>(posSmall), 5);
393TEST(IntTest, LargeWidthBadSignExtensionOverflow) {
396 mbv_v.setBit(0,
true);
397 mbv_v.setBit(2,
true);
398 mbv_v.setBit(100,
true);
401 EXPECT_THROW((
void)
static_cast<int64_t
>(v), std::overflow_error);
404TEST(IntTest, LargeWidthBoundaryFitsInI64) {
411 mbv.setBit(63,
true);
413 EXPECT_THROW((
void)
static_cast<int64_t
>(v), std::overflow_error);
418 for (
size_t i = 63; i < 128; ++i)
421 EXPECT_EQ(
static_cast<int64_t
>(n), std::numeric_limits<int64_t>::min());
424TEST(UIntTest, BasicConstruction) {
428 for (
size_t i = 0; i < 16; ++i)
429 if (val & (1ULL << i))
433 EXPECT_EQ(
static_cast<uint64_t
>(u), 123u);
434 EXPECT_EQ(u.width(), 16u);
437TEST(UIntTest, BitwiseFastVsFallbackConsistency) {
439 std::vector<uint8_t> raw1{0xFF, 0x0F, 0xAA};
440 std::vector<uint8_t> raw2{0x0F, 0xF0, 0x55};
443 auto alignedAnd = aAligned & bAligned;
446 for (
size_t i = 0; i < aAligned.width(); ++i)
447 EXPECT_EQ(alignedAnd.getBit(i), (aAligned.getBit(i) && bAligned.getBit(i)));
450TEST(UIntTest, OverflowUnsignedConversion) {
453 EXPECT_NO_THROW((
void)
static_cast<uint64_t
>(
UInt(big)));
456 big.setBit(65,
true);
458 EXPECT_THROW((
void)
static_cast<uint64_t
>(bigUInt), std::overflow_error);
462TEST(BitVectorFormatTest, ToStringAndStreamBases) {
465 const uint64_t val = 0x1F3ULL;
468 std::vector<uint8_t> bytes((width + 7) / 8, 0);
469 for (
size_t i = 0; i < width; ++i)
470 if (val & (1ULL << i))
471 bytes[i / 8] |=
static_cast<uint8_t
>(1u << (i % 8));
477 EXPECT_EQ(bv.
toString(), std::string(
"1f3"));
478 EXPECT_EQ(bv.
toString(16), std::string(
"1f3"));
479 EXPECT_EQ(bv.
toString(10), std::string(
"499"));
480 EXPECT_EQ(bv.
toString(8), std::string(
"763"));
481 EXPECT_EQ(bv.
toString(2), std::string(
"000111110011"));
485 std::ostringstream oss;
487 EXPECT_EQ(oss.str(),
"499");
490 std::ostringstream oss;
491 oss << std::dec << std::showbase << bv;
492 EXPECT_EQ(oss.str(),
"499");
495 std::ostringstream oss;
496 oss << std::hex << bv;
497 EXPECT_EQ(oss.str(),
"1f3");
500 std::ostringstream oss;
501 oss << std::showbase << std::hex << bv;
502 EXPECT_EQ(oss.str(),
"0x1f3");
505 std::ostringstream oss;
506 oss << std::uppercase << std::showbase << std::hex << bv;
507 EXPECT_EQ(oss.str(),
"0X1F3");
510 std::ostringstream oss;
511 oss << std::oct << bv;
512 EXPECT_EQ(oss.str(),
"763");
515 std::ostringstream oss;
516 oss << std::showbase << std::oct << bv;
517 EXPECT_EQ(oss.str(),
"0763");
524 std::ostringstream ossHex, ossDec, ossOct;
525 ossHex << std::hex << z;
526 ossDec << std::dec << z;
527 ossOct << std::oct << z;
528 EXPECT_EQ(ossHex.str(),
"0");
529 EXPECT_EQ(ossDec.str(),
"0");
530 EXPECT_EQ(ossOct.str(),
"0");
531 EXPECT_EQ(z.toString(2),
"0");
A lightweight, non-owning bit vector view backed by a byte array span.
std::string toString(unsigned base=16) const
A mutable bit vector that owns its underlying storage.