diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h index 01fe21b38..d5d93495f 100644 --- a/Source/Engine/Core/Collections/Array.h +++ b/Source/Engine/Core/Collections/Array.h @@ -112,15 +112,15 @@ public: /// Initializes a new instance of the class. /// /// The other collection to copy. - template - explicit Array(const Array& other) noexcept + template + explicit Array(const Array& other) noexcept { - _capacity = other._count; - _count = other._count; + _capacity = other.Capacity(); + _count = other.Count(); if (_capacity > 0) { _allocation.Allocate(_capacity); - Memory::ConstructItems(_allocation.Get(), other._data, other._count); + Memory::ConstructItems(_allocation.Get(), other.Get(), _count); } } @@ -164,13 +164,13 @@ public: if (this != &other) { Memory::DestructItems(_allocation.Get(), _count); - if (_capacity < other._count) + if (_capacity < other.Count()) { _allocation.Free(); - _capacity = other._count; + _capacity = other.Count(); _allocation.Allocate(_capacity); } - _count = other._count; + _count = other.Count(); Memory::ConstructItems(_allocation.Get(), other.Get(), _count); } return *this; @@ -489,7 +489,7 @@ public: /// Adds the other collection to the collection. /// /// The other collection to add. - template + template FORCE_INLINE void Add(const Array& other) { Add(other.Get(), other.Count()); @@ -860,9 +860,10 @@ public: } public: - bool operator==(const Array& other) const + template + bool operator==(const Array& other) const { - if (_count == other._count) + if (_count == other.Count()) { const T* data = _allocation.Get(); const T* otherData = other.Get(); @@ -875,7 +876,8 @@ public: return true; } - bool operator!=(const Array& other) const + template + bool operator!=(const Array& other) const { return !operator==(other); } diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index 7d6d50773..660b1e0fe 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -13,7 +13,6 @@ template API_CLASS(InBuild) class BitArray { friend BitArray; - public: typedef uint64 ItemType; typedef typename AllocationType::template Data AllocationData; @@ -49,11 +48,31 @@ public: /// Initializes a new instance of the class. /// /// The other collection to copy. - BitArray(const BitArray& other) + BitArray(const BitArray& other) noexcept { - _count = _capacity = other._count; + _count = _capacity = other.Count(); if (_capacity > 0) - _allocation.Allocate(Math::Max(_capacity / sizeof(ItemType), 1)); + { + const uint64 itemsCapacity = Math::Max(_capacity / sizeof(ItemType), 1); + _allocation.Allocate(itemsCapacity); + Platform::MemoryCopy(Get(), other.Get(), itemsCapacity * sizeof(ItemType)); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The other collection to copy. + template + explicit BitArray(const BitArray& other) noexcept + { + _count = _capacity = other.Count(); + if (_capacity > 0) + { + const uint64 itemsCapacity = Math::Max(_capacity / sizeof(ItemType), 1); + _allocation.Allocate(itemsCapacity); + Platform::MemoryCopy(Get(), other.Get(), itemsCapacity * sizeof(ItemType)); + } } /// @@ -82,7 +101,9 @@ public: { _allocation.Free(); _capacity = other._count; - _allocation.Allocate(Math::Max(_capacity / sizeof(ItemType), 1)); + const uint64 itemsCapacity = Math::Max(_capacity / sizeof(ItemType), 1); + _allocation.Allocate(itemsCapacity); + Platform::MemoryCopy(Get(), other.Get(), itemsCapacity * sizeof(ItemType)); } _count = other._count; } @@ -119,7 +140,6 @@ public: /// /// Gets the pointer to the bits storage data (linear allocation). /// - /// The data pointer. FORCE_INLINE ItemType* Get() { return _allocation.Get(); @@ -128,7 +148,6 @@ public: /// /// Gets the pointer to the bits storage data (linear allocation). /// - /// The data pointer. FORCE_INLINE const ItemType* Get() const { return _allocation.Get(); @@ -137,7 +156,6 @@ public: /// /// Gets the amount of the items in the collection. /// - /// The amount of items. FORCE_INLINE int32 Count() const { return _count; @@ -146,7 +164,6 @@ public: /// /// Gets the amount of the items that can be contained by collection without resizing. /// - /// The collection capacity. FORCE_INLINE int32 Capacity() const { return _capacity; @@ -155,7 +172,6 @@ public: /// /// Returns true if collection isn't empty. /// - /// True if collection isn't empty, otherwise false. FORCE_INLINE bool HasItems() const { return _count != 0; @@ -164,7 +180,6 @@ public: /// /// Returns true if collection is empty. /// - /// True if collection is empty, otherwise false. FORCE_INLINE bool IsEmpty() const { return _count == 0; @@ -316,4 +331,25 @@ public: ::Swap(_capacity, other._capacity); _allocation.Swap(other._allocation); } + +public: + template + bool operator==(const BitArray& other) const + { + if (_count == other.Count()) + { + for (int32 i = 0; i < _count; i++) + { + if (!(Get(i) == other.Get(i))) + return false; + } + } + return true; + } + + template + bool operator!=(const BitArray& other) const + { + return !operator==(other); + } }; diff --git a/Source/Engine/Core/RandomStream.h b/Source/Engine/Core/RandomStream.h index 3b1d43c3b..0d8ad48e2 100644 --- a/Source/Engine/Core/RandomStream.h +++ b/Source/Engine/Core/RandomStream.h @@ -13,7 +13,6 @@ class FLAXENGINE_API RandomStream { private: - /// /// Holds the initial seed. /// @@ -25,7 +24,6 @@ private: mutable int32 _seed; public: - /// /// Init /// @@ -46,22 +44,18 @@ public: } public: - /// /// Gets initial seed value /// - /// Initial seed. int32 GetInitialSeed() const { return _initialSeed; } public: - /// /// Gets the current seed. /// - /// Current seed value. int32 GetCurrentSeed() const { return _seed; @@ -94,11 +88,18 @@ public: } public: - /// - /// Returns a random number between 0 and MAXUINT. + /// Returns a random boolean. + /// + bool GetBool() const + { + MutateSeed(); + return *(uint32*)&_seed < (MAX_uint32 / 2); + } + + /// + /// Returns a random number between 0 and MAX_uint32. /// - /// Random number. uint32 GetUnsignedInt() const { MutateSeed(); @@ -108,7 +109,6 @@ public: /// /// Returns a random number between 0 and 1. /// - /// Random number. float GetFraction() const { MutateSeed(); @@ -121,7 +121,6 @@ public: /// /// Returns a random number between 0 and 1. /// - /// Random number. FORCE_INLINE float Rand() const { return GetFraction(); @@ -130,7 +129,6 @@ public: /// /// Returns a random vector of unit size. /// - /// Random unit length vector Float3 GetUnitVector() const { Float3 result; @@ -144,11 +142,10 @@ public: } while (l > 1.0f || l < ZeroTolerance); return Float3::Normalize(result); } - + /// /// Gets a random with components in a range between [0;1]. /// - /// A random . Vector3 GetVector3() const { return Vector3(GetFraction(), GetFraction(), GetFraction()); @@ -157,11 +154,11 @@ public: /// /// Helper function for rand implementations. /// - /// Top border + /// Top border /// A random number in [0..A) - FORCE_INLINE int32 RandHelper(int32 A) const + FORCE_INLINE int32 RandHelper(int32 a) const { - return A > 0 ? Math::TruncToInt(GetFraction() * ((float)A - ZeroTolerance)) : 0; + return a > 0 ? Math::TruncToInt(GetFraction() * ((float)a - ZeroTolerance)) : 0; } /// @@ -188,7 +185,6 @@ public: } protected: - /// /// Mutates the current seed into the next seed. /// diff --git a/Source/Engine/Tests/TestCollections.cpp b/Source/Engine/Tests/TestCollections.cpp new file mode 100644 index 000000000..a82ae40ce --- /dev/null +++ b/Source/Engine/Tests/TestCollections.cpp @@ -0,0 +1,110 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +#include "Engine/Core/RandomStream.h" +#include "Engine/Core/Collections/Array.h" +#include "Engine/Core/Collections/BitArray.h" +#include + +TEST_CASE("Array") +{ + SECTION("Test Allocators") + { + Array a1; + Array> a2; + Array> a3; + for (int32 i = 0; i < 7; i++) + { + a1.Add(i); + a2.Add(i); + a3.Add(i); + } + CHECK(a1.Count() == 7); + CHECK(a2.Count() == 7); + CHECK(a3.Count() == 7); + for (int32 i = 0; i < 7; i++) + { + CHECK(a1[i] == i); + CHECK(a2[i] == i); + CHECK(a3[i] == i); + } + } + + // Generate some random data for testing + Array testData; + testData.Resize(32); + RandomStream rand(101); + for (int32 i = 0; i < testData.Count(); i++) + testData[i] = rand.GetUnsignedInt(); + + SECTION("Test Copy Constructor") + { + const Array a1(testData); + const Array> a2(testData); + const Array> a3(testData); + const Array> a4(testData); + CHECK(a1 == testData); + CHECK(a2 == testData); + CHECK(a3 == testData); + CHECK(a4 == testData); + } + + SECTION("Test Copy Operator") + { + Array a1; + a1 = testData; + CHECK(a1 == testData); + } +} + +TEST_CASE("BitArray") +{ + SECTION("Test Allocators") + { + BitArray<> a1; + BitArray> a2; + BitArray> a3; + for (int32 i = 0; i < 7; i++) + { + const bool v = i & 2; + a1.Add(v); + a2.Add(v); + a3.Add(v); + } + CHECK(a1.Count() == 7); + CHECK(a2.Count() == 7); + CHECK(a3.Count() == 7); + for (int32 i = 0; i < 7; i++) + { + const bool v = i & 2; + CHECK(a1.Get(i) == v); + CHECK(a2.Get(i) == v); + CHECK(a3.Get(i) == v); + } + } + + // Generate some random data for testing + BitArray<> testData; + testData.Resize(32); + RandomStream rand(101); + for (int32 i = 0; i < testData.Count(); i++) + testData.Set(i, rand.GetBool()); + + SECTION("Test Copy Constructor") + { + const BitArray<> a1(testData); + const BitArray> a2(testData); + const BitArray> a3(testData); + const BitArray> a4(testData); + CHECK(a1 == testData); + CHECK(a2 == testData); + CHECK(a3 == testData); + CHECK(a4 == testData); + } + + SECTION("Test Copy Operator") + { + BitArray<> a1; + a1 = testData; + CHECK(a1 == testData); + } +}