diff --git a/PolyEngine/Core/Src/Collections/BitMask.cpp b/PolyEngine/Core/Src/Collections/BitMask.cpp new file mode 100644 index 00000000..bf94b858 --- /dev/null +++ b/PolyEngine/Core/Src/Collections/BitMask.cpp @@ -0,0 +1,410 @@ +#include "CorePCH.hpp" + +#include + +constexpr u64 ZERO = 0UL; + +using namespace Poly; + +constexpr size_t TYPE_BIT = CHAR_BIT * sizeof(BitMask::DataType); + +BitMask::BitMask(size_t size) + : BitsNumber(size) +{ + size_t arraySize = (size + TYPE_BIT - 1) / TYPE_BIT; + for (size_t i = 0; i < arraySize; i++) + BitList.PushBack(ZERO); +} + +bool BitMask::Reset() +{ + BitList.Clear(); + BitsNumber = 0; + return true; +} + +bool BitMask::Toggle(size_t index) +{ + HEAVY_ASSERTE(index <= BitsNumber, "Out of bounds"); + BitList[index / TYPE_BIT] ^= 1UL << index%TYPE_BIT; + return true; +} + +bool BitMask::operator[](size_t index) const +{ + DataType tempChar = BitList[index / TYPE_BIT]; + tempChar = (tempChar >> index%TYPE_BIT) & 1UL; + return tempChar != 0; +} + +bool BitMask::Set(size_t index, bool state) +{ + HEAVY_ASSERTE(index<=BitsNumber, "Out of bounds"); + + size_t bitListIndex = index / TYPE_BIT; + size_t bitPosition = index % TYPE_BIT; + + if (state) + BitList[bitListIndex] |= (1UL << bitPosition); + else + BitList[bitListIndex] &= ~(1UL << bitPosition); + return true; +} + +BitMask BitMask::operator|(const BitMask& rhs) const +{ + //Equal Dynarray sizes + if (BitList.GetSize() == rhs.BitList.GetSize()) + { + size_t tempBitsNumber = 0; + if (BitsNumber > rhs.BitsNumber) + tempBitsNumber = BitsNumber; + else + tempBitsNumber = rhs.BitsNumber; + + BitMask temp(tempBitsNumber); + for (size_t i = 0; i < BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] | rhs.BitList[i]; + return temp; + } + else if (BitList.GetSize() > rhs.BitList.GetSize()) + { + BitMask temp(BitsNumber); + for (size_t i = 0; i < rhs.BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] | rhs.BitList[i]; + for (size_t i = rhs.BitList.GetSize(); i < BitList.GetSize(); i++) + temp.BitList[i] = BitList[i]; + return temp; + } + else if (BitList.GetSize() < rhs.BitList.GetSize()) + { + BitMask temp(rhs.BitsNumber); + for (size_t i = 0; i < BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] | rhs.BitList[i]; + for (size_t i = BitList.GetSize(); i < rhs.BitList.GetSize(); i++) + temp.BitList[i] = rhs.BitList[i]; + return temp; + } + return BitMask(0); +} + +BitMask BitMask::operator^(const BitMask& rhs) const +{ + if (BitList.GetSize() == rhs.BitList.GetSize()) + { + size_t tempBitsNumber = 0; + if (BitsNumber > rhs.BitsNumber) + tempBitsNumber = BitsNumber; + else + tempBitsNumber = rhs.BitsNumber; + + BitMask temp(tempBitsNumber); + for (size_t i = 0; i < BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] ^ rhs.BitList[i]; + return temp; + } + //Lhs size bigger than rhs size + else if (BitList.GetSize() > rhs.BitList.GetSize()) + { + BitMask temp(BitsNumber); + for (size_t i = 0; i < rhs.BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] ^ rhs.BitList[i]; + for (size_t i = rhs.BitList.GetSize(); i < BitList.GetSize(); i++) + temp.BitList[i] = BitList[i]; + return temp; + } + //rhs size bigger than lhs size + else if (BitList.GetSize() < rhs.BitList.GetSize()) + { + BitMask temp(rhs.BitsNumber); + for (size_t i = 0; i < BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] ^ rhs.BitList[i]; + for (size_t i = BitList.GetSize(); i < rhs.BitList.GetSize(); i++) + temp.BitList[i] = rhs.BitList[i]; + return temp; + } + return BitMask(0); +} + +BitMask BitMask::operator&(const BitMask& rhs) const +{ + if (BitList.GetSize() == rhs.BitList.GetSize()) + { + size_t tempBitsNumber = 0; + if (BitsNumber > rhs.BitsNumber) + tempBitsNumber = BitsNumber; + else + tempBitsNumber = rhs.BitsNumber; + + BitMask temp(tempBitsNumber); + for (size_t i = 0; i < BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] & rhs.BitList[i]; + return temp; + } + else if (BitList.GetSize() > rhs.BitList.GetSize()) + { + BitMask temp(BitsNumber); + for (size_t i = 0; i < rhs.BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] & rhs.BitList[i]; + for (size_t i = rhs.BitList.GetSize(); i < BitList.GetSize(); i++) + temp.BitList[i] = ZERO; + return temp; + } + else if (BitList.GetSize() < rhs.BitList.GetSize()) + { + BitMask temp(rhs.BitsNumber); + for (size_t i = 0; i < BitList.GetSize(); i++) + temp.BitList[i] = BitList[i] & rhs.BitList[i]; + for (size_t i = BitList.GetSize(); i < rhs.BitList.GetSize(); i++) + temp.BitList[i] = ZERO; + return temp; + } + return BitMask(0); +} + +BitMask BitMask::operator~() const +{ + BitMask temp = *this; + + for (auto& x : temp.BitList) + x = ~x; + + return temp; +} + + +bool BitMask::Resize(size_t size) +{ + BitsNumber = size; + BitList.Resize((size + TYPE_BIT - 1) / TYPE_BIT); + return true; + /* + if (offset > 0) + { + if (BitsNumber + offset <= GetDynarraySize()*TYPE_BIT) + { + BitsNumber += offset; + return true; + } + else + { + size_t currentSize = BitList.GetSize(); + size_t targetSize = 0; + if ((BitsNumber + offset) % TYPE_BIT) + targetSize = (BitsNumber + offset) / TYPE_BIT + 1; + else + targetSize = (BitsNumber + offset) / TYPE_BIT; + + size_t pushBackCount = targetSize - currentSize; + + for (size_t i = 0; i < pushBackCount; i++) + BitList.PushBack(ZERO); + + BitsNumber += offset; + return true; + } + } + + if (offset < 0) + { + HEAVY_ASSERTE(BitsNumber + offset(GetDynarraySize() - 1)*TYPE_BIT) + { + BitsNumber += offset; + return true; + } + else + { + size_t currentSize = BitList.GetSize(); + size_t targetSize = 0; + if (-1 * (BitsNumber + offset) % TYPE_BIT) + targetSize = (BitsNumber + offset) / TYPE_BIT + 1; + else + targetSize = (BitsNumber + offset) / TYPE_BIT; + + size_t popBackCount = currentSize - targetSize; + for (size_t i = 0; i < popBackCount; i++) + BitList.PopBack(); + + BitsNumber += offset; + return true; + } + } + + + if (offset == 0) + { + return false; + } + return false; + */ +} + +size_t BitMask::BitListIndex(size_t index) +{ + return index / TYPE_BIT; +} + +BitMask& BitMask::operator|=(const BitMask& rhs) +{ + *this = *this | rhs; + + return *this; + /* + //Equal Dynarray sizes + if (BitList.GetSize() == rhs.BitList.GetSize()) + { + for (size_t i = 0; i < BitList.GetSize(); i++) + BitList[i] |= rhs.BitList[i]; + + if (rhs.BitsNumber > BitsNumber) + BitsNumber = rhs.BitsNumber; + + return *this; + } + + else if (BitList.GetSize() > rhs.BitList.GetSize()) + { + for (size_t i = 0; i < rhs.BitList.GetSize(); i++) + BitList[i] |= rhs.BitList[i]; + + return *this; + } + + else if (BitList.GetSize() < rhs.BitList.GetSize()) + { + for (size_t i = 0; i < BitList.GetSize(); i++) + BitList[i] |= rhs.BitList[i]; + + size_t oldBitListSize = BitList.GetSize(); + + for (size_t i = 0; i < rhs.BitList.GetSize() - oldBitListSize; i++) + BitList.PushBack(ZERO); + + for (size_t i = oldBitListSize; i < BitList.GetSize(); i++) + BitList[i] = rhs.BitList[i]; + + BitsNumber = rhs.BitsNumber; + return *this; + } + return *this; + */ +} + +BitMask& BitMask::operator^=(const BitMask& rhs) +{ + *this = *this ^ rhs; + + return *this; + /* + if (BitList.GetSize() == rhs.BitList.GetSize()) + { + for (size_t i = 0; i < BitList.GetSize(); i++) + BitList[i] ^= rhs.BitList[i]; + + if (rhs.BitsNumber > BitsNumber) + BitsNumber = rhs.BitsNumber; + + return *this; + } + else if (BitList.GetSize() > rhs.BitList.GetSize()) + { + for (size_t i = 0; i < rhs.BitList.GetSize(); i++) + BitList[i] ^= rhs.BitList[i]; + + return *this; + } + else if (BitList.GetSize() < rhs.BitList.GetSize()) + { + for (size_t i = 0; i < BitList.GetSize(); i++) + BitList[i] ^= rhs.BitList[i]; + + size_t oldBitListSize = BitList.GetSize(); + + for (size_t i = 0; i < rhs.BitList.GetSize() - oldBitListSize; i++) + BitList.PushBack(ZERO); + + for (size_t i = oldBitListSize; i < BitList.GetSize(); i++) + BitList[i] = rhs.BitList[i]; + + BitsNumber = rhs.BitsNumber; + return *this; + } + return *this; + */ +} + +BitMask& BitMask::operator&=(const BitMask& rhs) +{ + *this = *this & rhs; + + return *this; + /* + if (BitList.GetSize() == rhs.BitList.GetSize()) + { + for (size_t i = 0; i < BitList.GetSize(); i++) + BitList[i] &= rhs.BitList[i]; + + if (rhs.BitsNumber > BitsNumber) + BitsNumber = rhs.BitsNumber; + + return *this; + } + else if (BitList.GetSize() > rhs.BitList.GetSize()) + { + for (size_t i = 0; i < rhs.BitList.GetSize(); i++) + BitList[i] &= rhs.BitList[i]; + + for (size_t i = rhs.BitList.GetSize(); i < BitList.GetSize(); i++) + BitList[i] = ZERO; + return *this; + } + else if (BitList.GetSize() < rhs.BitList.GetSize()) + { + for (size_t i = 0; i < BitList.GetSize(); i++) + BitList[i] &= rhs.BitList[i]; + + size_t oldBitListSize = BitList.GetSize(); + + for (size_t i = 0; i < rhs.BitList.GetSize() - oldBitListSize; i++) + BitList.PushBack(ZERO); + + for (size_t i = oldBitListSize; i < BitList.GetSize(); i++) + BitList[i] = ZERO; + + BitsNumber = rhs.BitsNumber; + return *this; + } + return *this; + */ +} + +bool BitMask::operator==(const BitMask rhs) const +{ + if (BitsNumber != rhs.BitsNumber) + return false; + + if (BitsNumber == rhs.BitsNumber) + { + for (size_t i = 0; i < BitList.GetSize(); i++) + if (BitList[i] != rhs.BitList[i]) + return false; + return true; + } + return false; +} + +/* +BitMaskProxy BitMaskProxy::operator=(bool index) +{ + BitMaskProxy proxy; + proxy.bitValue = this[index]; + return proxy; +}*/ + +BitMaskProxy BitMaskProxy::operator[](size_t index) +{ + BitMaskProxy temp; + temp.bitValue = BitMask::operator[](index); + return temp; +} \ No newline at end of file diff --git a/PolyEngine/Core/Src/Collections/BitMask.hpp b/PolyEngine/Core/Src/Collections/BitMask.hpp new file mode 100644 index 00000000..79bff942 --- /dev/null +++ b/PolyEngine/Core/Src/Collections/BitMask.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include +#include "Dynarray.hpp" + +namespace Poly { + class CORE_DLLEXPORT BitMask + { + public: + using DataType = unsigned short; + + BitMask(size_t size = sizeof(DataType)); + + //Bitwise operators + BitMask operator|(const BitMask& rhs) const; + BitMask operator^(const BitMask& rhs) const; + BitMask operator&(const BitMask& rhs) const; + BitMask operator~() const; + //Bitwise assignment operators + BitMask& operator|=(const BitMask& rhs); + BitMask& operator^=(const BitMask& rhs); + BitMask& operator&=(const BitMask& rhs); + + + bool operator==(const BitMask rhs) const; + bool operator!=(const BitMask& rhs) const + { + return !(*this == rhs); + } + + + //@todo Convert this method to return bit proxy + bool operator[](size_t index) const; + + //Set,Reset and toggle bits methods + bool Set(size_t index, bool state); + bool Reset(); + bool Toggle(size_t index); + + bool Resize(size_t size = 0); + + + size_t GetSize() { return BitsNumber; } + size_t GetDynarraySize() { return BitList.GetSize(); } + protected: + + private: + inline size_t BitListIndex(size_t index); + + Dynarray BitList; + size_t BitsNumber = 0; //How many bits are in the class + }; + + + class CORE_DLLEXPORT BitMaskProxy : public BitMask { + private: + bool bitValue; + size_t bitIndex; + public: + BitMaskProxy(size_t size = sizeof(DataType)) : BitMask(size) {} + operator bool() { return bitValue; } + BitMaskProxy operator[](size_t index); + BitMaskProxy operator=(bool); + + }; +} \ No newline at end of file diff --git a/PolyEngine/Core/Src/CorePCH.hpp b/PolyEngine/Core/Src/CorePCH.hpp index 4b3c306b..16045e11 100644 --- a/PolyEngine/Core/Src/CorePCH.hpp +++ b/PolyEngine/Core/Src/CorePCH.hpp @@ -31,6 +31,7 @@ #include "Collections/Dynarray.hpp" #include "Collections/Queue.hpp" #include "Collections/PriorityQueue.hpp" +#include "Collections/BitMask.hpp" // Other #include "Math/Color.hpp" diff --git a/PolyEngine/UnitTests/Src/BitMaskTests.cpp b/PolyEngine/UnitTests/Src/BitMaskTests.cpp new file mode 100644 index 00000000..e06ca4ae --- /dev/null +++ b/PolyEngine/UnitTests/Src/BitMaskTests.cpp @@ -0,0 +1,501 @@ +#include +#include + +#include + +using namespace Poly; + +constexpr size_t TYPE_BIT = CHAR_BIT * sizeof(BitMask::DataType); + +//Function calculating expected Dynarray size ,for debugging purposes +size_t DynarraySize(BitMask mask) +{ + if (mask.GetSize() % TYPE_BIT) + return mask.GetSize() / TYPE_BIT + 1; + else + return mask.GetSize() / TYPE_BIT; +} + +TEST_CASE("BitMask constructors", "[BitMask]") +{ + //Default constructor + BitMask a; + REQUIRE(a.GetSize() == 1 * sizeof(BitMask::DataType)); + REQUIRE(a.GetDynarraySize() == DynarraySize(a)); + BitMask b; + REQUIRE(a.GetSize() == b.GetSize()); + REQUIRE(a.GetDynarraySize() == b.GetDynarraySize()); + //"Not even" constructor + BitMask c(20); + REQUIRE(c.GetSize() == 20); + REQUIRE(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < a.GetSize(); i++) + REQUIRE(a[i] == false); + for (size_t i = 0; i < b.GetSize(); i++) + REQUIRE(b[i] == false); + for (size_t i = 0; i < c.GetSize(); i++) + REQUIRE(c[i] == false); + //Even constructor + BitMask d(16); + REQUIRE(d.GetSize() == 16); + REQUIRE(d.GetDynarraySize() == DynarraySize(d)); +} + +TEST_CASE("BitMask Set,Toggle and Reset", "[BitMask]") +{ + BitMask a(8); + //Set method + a.Set(7, true); + a.Set(0, true); + CHECK(a[7] == true); + CHECK(a[0] == true); + a.Set(7, false); + a.Set(0, false); + CHECK(a[7] == false); + CHECK(a[0] == false); + + //Toggle method + a.Toggle(1); + CHECK(a[1] == true); + a.Toggle(1); + CHECK(a[1] == false); + + //Reset method + a.Reset(); + CHECK(a.GetSize() == 0); + CHECK(a.GetDynarraySize() == DynarraySize(a)); +} +TEST_CASE("Bitwise operators", "[BitMask]") +{ + SECTION("Bitwise OR operator") + { + SECTION("Equal Dynarray sizes") + { + BitMask a(17), b(22), c; + a.Toggle(0); a.Toggle(3); a.Toggle(10); a.Toggle(15); + b.Toggle(0); b.Toggle(5); b.Toggle(11); b.Toggle(20); + c = a | b; + CHECK(c.GetSize() == 22); + CHECK(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < c.GetSize(); i++) + { + if (i == 0 || i == 3 || i == 5 || i == 10 || + i == 11 || i == 15 || i == 20) + CHECK(c[i] == true); + else + CHECK(c[i] == false); + } + } + SECTION("Different Dynarray sizes") + { + BitMask a(16), b(5), c; + b.Toggle(1); b.Toggle(2); b.Toggle(4); + a.Toggle(0); a.Toggle(1); a.Toggle(8); a.Toggle(10); a.Toggle(15); + BitMask *left, *right; + left = &a; right = &b; + SECTION("Lhs size bigger than rhs size") + { + c = *left | *right; + CHECK(c.GetSize() == 16); + CHECK(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < c.GetSize(); i++) + { + if (i == 0 || i == 1 || i == 2 || i == 4 || + i == 8 || i == 15 || i == 10) + CHECK(c[i] == true); + else + CHECK(c[i] == false); + } + } + SECTION("Rhs size bigger than lhs size") + { + left = &b; right = &a; + BitMask d = *left | *right; + CHECK(d.GetSize() == 16); + CHECK(d.GetDynarraySize() == DynarraySize(d)); + for (size_t i = 0; i < d.GetSize(); i++) + { + if (i == 0 || i == 1 || i == 2 || i == 4 || + i == 8 || i == 15 || i == 10) + CHECK(d[i] == true); + else + CHECK(d[i] == false); + } + } + } + } + SECTION("Bitwise XOR operator") + { + SECTION("Equal Dynarray sizes") + { + BitMask a(62), b(57), c; + a.Toggle(4); a.Toggle(21); a.Toggle(29); a.Toggle(59); + b.Toggle(4); b.Toggle(18); b.Toggle(21); b.Toggle(29); b.Toggle(55); + c = a ^ b; + CHECK(c.GetSize() == 62); + CHECK(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < c.GetSize(); i++) + if (i == 18 || i == 59 || i == 55) + CHECK(c[i] == true); + else + CHECK(c[i] == false); + } + SECTION("Different Dynarray sizes") + { + BitMask a(4), b(25); + a.Toggle(0); a.Toggle(2); a.Toggle(3); + b.Toggle(0); b.Toggle(2); b.Toggle(10); b.Toggle(20); + BitMask *left = &a, *right = &b; + SECTION("Rhs size bigger than lhs size") + { + BitMask c = *left ^ *right; + CHECK(c.GetSize() == 25); + CHECK(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < c.GetSize(); i++) + if (i == 3 || i == 10 || i == 20) + CHECK(c[i] == true); + else + CHECK(c[i] == false); + } + SECTION("Lhs size bigger than rhs size") + { + left = &b; right = &a; + BitMask c = *left ^ *right; + CHECK(c.GetSize() == 25); + CHECK(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < c.GetSize(); i++) + if (i == 3 || i == 10 || i == 20) + CHECK(c[i] == true); + else + CHECK(c[i] == false); + } + } + } + SECTION("Bitwise AND operator") + { + SECTION("Equal Dynarray sizes") + { + BitMask a(12), b(14); + a.Toggle(0); a.Toggle(7); a.Toggle(8); a.Toggle(11); + b.Toggle(0); b.Toggle(1); b.Toggle(7); b.Toggle(9); b.Toggle(13); + BitMask c = a&b; + CHECK(c.GetSize() == 14); + CHECK(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < c.GetSize(); i++) + { + if (i == 0 || i == 7) + CHECK(c[i] == true); + else + CHECK(c[i] == false); + } + SECTION("Different Dynarray sizes") + { + BitMask a(21), b(8); + a.Toggle(1); a.Toggle(5); a.Toggle(13); a.Toggle(14); a.Toggle(19); + b.Toggle(1); b.Toggle(5); b.Toggle(7); + BitMask *left, *right; + SECTION("Rhs size bigger than lhs size") + { + left = &b; right = &a; + BitMask c = *left & *right; + CHECK(c.GetSize() == 21); + CHECK(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < c.GetSize(); i++) + if (i == 1 || i == 5) + CHECK(c[i] == true); + else + CHECK(c[i] == false); + } + SECTION("Lhs size bigger than rhs size") + { + left = &a; right = &b; + BitMask c = *left & *right; + CHECK(c.GetSize() == 21); + CHECK(c.GetDynarraySize() == DynarraySize(c)); + for (size_t i = 0; i < c.GetSize(); i++) + if (i == 1 || i == 5) + CHECK(c[i] == true); + else + CHECK(c[i] == false); + } + } + } + } +} + +TEST_CASE("Negate operator", "[BitMask]") +{ + BitMask a(10); + for (size_t i = 0; i < a.GetSize(); i++) + if (i % 2) //Toggle for odd numbers + a.Toggle(i); + + a=~a; + for (size_t i = 0; i < a.GetSize(); i++) + if (i % 2) + CHECK(a[i] == false); + else + CHECK(a[i] == true); +} + +TEST_CASE("Bitwise assignment operators", "[BitMask]") +{ + SECTION("Bitwise OR assignment operator") + { + SECTION("Equal Dynarray sizes") + { + BitMask a(13), b(10); + a.Toggle(0); a.Toggle(5); a.Toggle(7); a.Toggle(10); + b.Toggle(0); b.Toggle(4); b.Toggle(5); + a |= b; + CHECK(a.GetSize() == 13); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + for (size_t i = 0; i < a.GetSize(); i++) + { + if (i == 0 || i == 4 || i == 5 || i == 7 || i == 10) + CHECK(a[i] == true); + else + CHECK(a[i] == false); + } + } + SECTION("Different Dynarray sizes") + { + SECTION("Lhs size bigger than rhs size") + { + BitMask a(7), b(26); + a.Toggle(0); a.Toggle(2); a.Toggle(4); a.Toggle(6); + b.Toggle(0); b.Toggle(3); b.Toggle(15); b.Toggle(21); + + b |= a; + CHECK(b.GetSize() == 26); + CHECK(b.GetDynarraySize() == DynarraySize(b)); + for (size_t i = 0; i < b.GetSize(); i++) + if (i == 0 || i == 2 || i == 3 || i == 4 || i == 6 || i == 15 || i == 21) + CHECK(b[i] == true); + else + CHECK(b[i] == false); + } + + SECTION("Rhs size bigger than lhs size") + { + BitMask a(7), b(26); + a.Toggle(0); a.Toggle(2); a.Toggle(4); a.Toggle(6); + b.Toggle(0); b.Toggle(3); b.Toggle(15); b.Toggle(21); + + a |= b; + CHECK(a.GetSize() == 26); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + for (size_t i = 0; i < a.GetSize(); i++) + if (i == 0 || i == 2 || i == 3 || i == 4 || i == 6 || i == 15 || i == 21) + CHECK(a[i] == true); + else + CHECK(a[i] == false); + } + } + } + + SECTION("Bitwise AND assignment operator") + { + SECTION("Equal dynarray sizes") + { + BitMask a(13), b(10); + a.Toggle(0); a.Toggle(3); a.Toggle(6); a.Toggle(12); a.Toggle(9); + b.Toggle(0); b.Toggle(3); b.Toggle(5); b.Toggle(9); + a &= b; + CHECK(a.GetSize() == 13); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + for (size_t i = 0; i < a.GetSize(); i++) + { + if (i == 0 || i == 3 || i == 9) + CHECK(a[i] == true); + else + CHECK(a[i] == false); + } + } + SECTION("Different Dynarray sizes") + { + SECTION("Rhs dynarray size bigger than lhs size") + { + BitMask a(4), b(23); + a.Toggle(1); a.Toggle(2); a.Toggle(3); + b.Toggle(2); b.Toggle(3); b.Toggle(10); b.Toggle(20); b.Toggle(15); + a &= b; + CHECK(a.GetSize() == 23); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + for (size_t i = 0; i < a.GetSize(); i++) + if (i == 2 || i == 3) + CHECK(a[i] == true); + else + CHECK(a[i] == false); + } + SECTION("Lhs dynarray size bigger than rhs size") + { + BitMask a(4), b(23); + a.Toggle(1); a.Toggle(2); a.Toggle(3); + b.Toggle(2); b.Toggle(3); b.Toggle(10); b.Toggle(20); b.Toggle(15); + b &= a; + CHECK(b.GetSize() == 23); + CHECK(b.GetDynarraySize() == DynarraySize(b)); + for (size_t i = 0; i < b.GetSize(); i++) + if (i == 2 || i == 3) + CHECK(b[i] == true); + else + CHECK(b[i] == false); + } + } + } + SECTION("Bitwise XOR assignment operator") + { + SECTION("Same dynarray sizes") + { + BitMask a(29), b(31); + a.Toggle(3); a.Toggle(7); a.Toggle(17); a.Toggle(23); a.Toggle(26); + b.Toggle(7); b.Toggle(15); b.Toggle(23); b.Toggle(26); b.Toggle(29); + a ^= b; + CHECK(a.GetSize() == 31); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + for (size_t i = 0; i < a.GetSize(); i++) + if (i == 3 || i == 15 || i == 17 || i == 3 || i == 29) + CHECK(a[i] == true); + else + CHECK(a[i] == false); + } + SECTION("Different Dynarray sizes") + { + SECTION("Rhs dynnaray size bigger than lhs") + { + BitMask a(8), b(16); + a.Toggle(0); a.Toggle(3); a.Toggle(7); + b.Toggle(1); b.Toggle(3); b.Toggle(7); b.Toggle(12); b.Toggle(15); + a ^= b; + CHECK(a.GetSize() == 16); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + for (size_t i = 0; i < a.GetSize(); i++) + if (i == 0 || i == 1 || i == 12 || i == 15) + CHECK(a[i] == true); + else + CHECK(a[i] == false); + } + SECTION("Lhs dynnaray size bigger than rhs") + { + BitMask a(8), b(16); + a.Toggle(0); a.Toggle(3); a.Toggle(7); + b.Toggle(1); b.Toggle(3); b.Toggle(7); b.Toggle(12); b.Toggle(15); + b ^= a; + CHECK(b.GetSize() == 16); + CHECK(b.GetDynarraySize() == DynarraySize(b)); + + for (size_t i = 0; i < b.GetSize(); i++) + if (i == 0 || i == 1 || i == 12 || i == 15) + CHECK(b[i] == true); + else + CHECK(b[i] == false); + } + } + } +} + +TEST_CASE("Comparision operator", "[BitMask]") +{ + SECTION("Different BitsNumbers") + { + BitMask a(4), b(5); + CHECK_FALSE(a == b); + } + SECTION("Equal BitsNumbers") + { + BitMask a(5), b(5); + a.Toggle(1); a.Toggle(3); + b.Toggle(1); b.Toggle(3); + CHECK(a == b); + BitMask c = b; + CHECK(c == b); + CHECK(c == a); + + a.Toggle(2); + CHECK_FALSE(a == b); + CHECK_FALSE(a == c); + } +} + +TEST_CASE("Negation operator", "[BitMask]") +{ + BitMask a(5), b(6); + CHECK(a != b); + + BitMask c(23), d(23); + c.Toggle(21); + d.Toggle(4); + + CHECK(c != d); +} + +TEST_CASE("Resize function", "[BitMask]") +{ + BitMask a(10); + CHECK(a.GetSize() == 10); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Toggle(1); a.Toggle(4); a.Toggle(6); a.Toggle(0); + a.Resize(5); + CHECK(a.GetSize() == 5); + CHECK(a.GetDynarraySize() == DynarraySize(a)); +} + +TEST_CASE("Proxy functions", "[BitMaskProxy]") +{ + bool value = false; + BitMaskProxy a(5); + a.Toggle(2); + value = a[2]; + CHECK(value == true); + value = a[1]; + CHECK(value == false); +} +/* +TEST_CASE("Resize function", "[BitMask]") +{ + BitMask a(14); + CHECK(a.GetSize() == 14); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(6); + CHECK(a.GetSize() == 20); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(-2); + CHECK(a.GetSize() == 18); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(-4); + CHECK(a.GetSize() == 14); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(-8); + CHECK(a.GetSize() == 6); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(40); + CHECK(a.GetSize() == 46); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(-6); + CHECK(a.GetSize() == 40); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(-1); + CHECK(a.GetSize() == 39); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(-33); + CHECK(a.GetSize() == 6); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(-5); + CHECK(a.GetSize() == 1); + CHECK(a.GetDynarraySize() == DynarraySize(a)); + + a.Resize(-1); + CHECK(a.GetSize() == 0); + CHECK(a.GetDynarraySize() == DynarraySize(a)); +}*/ \ No newline at end of file