Add Array/BitArray tests and fix some detected problems
This commit is contained in:
@@ -112,15 +112,15 @@ public:
|
||||
/// Initializes a new instance of the <see cref="Array"/> class.
|
||||
/// </summary>
|
||||
/// <param name="other">The other collection to copy.</param>
|
||||
template<typename U>
|
||||
explicit Array(const Array<U>& other) noexcept
|
||||
template<typename OtherT = T, typename OtherAllocationType = AllocationType>
|
||||
explicit Array(const Array<OtherT, OtherAllocationType>& 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.
|
||||
/// </summary>
|
||||
/// <param name="other">The other collection to add.</param>
|
||||
template<typename OtherT, typename OtherAllocationType = HeapAllocation>
|
||||
template<typename OtherT, typename OtherAllocationType = AllocationType>
|
||||
FORCE_INLINE void Add(const Array<OtherT, OtherAllocationType>& other)
|
||||
{
|
||||
Add(other.Get(), other.Count());
|
||||
@@ -860,9 +860,10 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
bool operator==(const Array& other) const
|
||||
template<typename OtherT = T, typename OtherAllocationType = AllocationType>
|
||||
bool operator==(const Array<OtherT, OtherAllocationType>& 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<typename OtherT = T, typename OtherAllocationType = AllocationType>
|
||||
bool operator!=(const Array<OtherT, OtherAllocationType>& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ template<typename AllocationType = HeapAllocation>
|
||||
API_CLASS(InBuild) class BitArray
|
||||
{
|
||||
friend BitArray;
|
||||
|
||||
public:
|
||||
typedef uint64 ItemType;
|
||||
typedef typename AllocationType::template Data<ItemType> AllocationData;
|
||||
@@ -49,11 +48,31 @@ public:
|
||||
/// Initializes a new instance of the <see cref="BitArray"/> class.
|
||||
/// </summary>
|
||||
/// <param name="other">The other collection to copy.</param>
|
||||
BitArray(const BitArray& other)
|
||||
BitArray(const BitArray& other) noexcept
|
||||
{
|
||||
_count = _capacity = other._count;
|
||||
_count = _capacity = other.Count();
|
||||
if (_capacity > 0)
|
||||
_allocation.Allocate(Math::Max<ItemType>(_capacity / sizeof(ItemType), 1));
|
||||
{
|
||||
const uint64 itemsCapacity = Math::Max<ItemType>(_capacity / sizeof(ItemType), 1);
|
||||
_allocation.Allocate(itemsCapacity);
|
||||
Platform::MemoryCopy(Get(), other.Get(), itemsCapacity * sizeof(ItemType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitArray"/> class.
|
||||
/// </summary>
|
||||
/// <param name="other">The other collection to copy.</param>
|
||||
template<typename OtherAllocationType = AllocationType>
|
||||
explicit BitArray(const BitArray<OtherAllocationType>& other) noexcept
|
||||
{
|
||||
_count = _capacity = other.Count();
|
||||
if (_capacity > 0)
|
||||
{
|
||||
const uint64 itemsCapacity = Math::Max<ItemType>(_capacity / sizeof(ItemType), 1);
|
||||
_allocation.Allocate(itemsCapacity);
|
||||
Platform::MemoryCopy(Get(), other.Get(), itemsCapacity * sizeof(ItemType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -82,7 +101,9 @@ public:
|
||||
{
|
||||
_allocation.Free();
|
||||
_capacity = other._count;
|
||||
_allocation.Allocate(Math::Max<ItemType>(_capacity / sizeof(ItemType), 1));
|
||||
const uint64 itemsCapacity = Math::Max<ItemType>(_capacity / sizeof(ItemType), 1);
|
||||
_allocation.Allocate(itemsCapacity);
|
||||
Platform::MemoryCopy(Get(), other.Get(), itemsCapacity * sizeof(ItemType));
|
||||
}
|
||||
_count = other._count;
|
||||
}
|
||||
@@ -119,7 +140,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the pointer to the bits storage data (linear allocation).
|
||||
/// </summary>
|
||||
/// <returns>The data pointer.</returns>
|
||||
FORCE_INLINE ItemType* Get()
|
||||
{
|
||||
return _allocation.Get();
|
||||
@@ -128,7 +148,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the pointer to the bits storage data (linear allocation).
|
||||
/// </summary>
|
||||
/// <returns>The data pointer.</returns>
|
||||
FORCE_INLINE const ItemType* Get() const
|
||||
{
|
||||
return _allocation.Get();
|
||||
@@ -137,7 +156,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the amount of the items in the collection.
|
||||
/// </summary>
|
||||
/// <returns>The amount of items.</returns>
|
||||
FORCE_INLINE int32 Count() const
|
||||
{
|
||||
return _count;
|
||||
@@ -146,7 +164,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the amount of the items that can be contained by collection without resizing.
|
||||
/// </summary>
|
||||
/// <returns>The collection capacity.</returns>
|
||||
FORCE_INLINE int32 Capacity() const
|
||||
{
|
||||
return _capacity;
|
||||
@@ -155,7 +172,6 @@ public:
|
||||
/// <summary>
|
||||
/// Returns true if collection isn't empty.
|
||||
/// </summary>
|
||||
/// <returns>True if collection isn't empty, otherwise false.</returns>
|
||||
FORCE_INLINE bool HasItems() const
|
||||
{
|
||||
return _count != 0;
|
||||
@@ -164,7 +180,6 @@ public:
|
||||
/// <summary>
|
||||
/// Returns true if collection is empty.
|
||||
/// </summary>
|
||||
/// <returns>True if collection is empty, otherwise false.</returns>
|
||||
FORCE_INLINE bool IsEmpty() const
|
||||
{
|
||||
return _count == 0;
|
||||
@@ -316,4 +331,25 @@ public:
|
||||
::Swap(_capacity, other._capacity);
|
||||
_allocation.Swap(other._allocation);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename OtherAllocationType = AllocationType>
|
||||
bool operator==(const BitArray<OtherAllocationType>& other) const
|
||||
{
|
||||
if (_count == other.Count())
|
||||
{
|
||||
for (int32 i = 0; i < _count; i++)
|
||||
{
|
||||
if (!(Get(i) == other.Get(i)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename OtherAllocationType = AllocationType>
|
||||
bool operator!=(const BitArray<OtherAllocationType>& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
class FLAXENGINE_API RandomStream
|
||||
{
|
||||
private:
|
||||
|
||||
/// <summary>
|
||||
/// Holds the initial seed.
|
||||
/// </summary>
|
||||
@@ -25,7 +24,6 @@ private:
|
||||
mutable int32 _seed;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Init
|
||||
/// </summary>
|
||||
@@ -46,22 +44,18 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets initial seed value
|
||||
/// </summary>
|
||||
/// <returns>Initial seed.</returns>
|
||||
int32 GetInitialSeed() const
|
||||
{
|
||||
return _initialSeed;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current seed.
|
||||
/// </summary>
|
||||
/// <returns>Current seed value.</returns>
|
||||
int32 GetCurrentSeed() const
|
||||
{
|
||||
return _seed;
|
||||
@@ -94,11 +88,18 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random number between 0 and MAXUINT.
|
||||
/// Returns a random boolean.
|
||||
/// </summary>
|
||||
bool GetBool() const
|
||||
{
|
||||
MutateSeed();
|
||||
return *(uint32*)&_seed < (MAX_uint32 / 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random number between 0 and MAX_uint32.
|
||||
/// </summary>
|
||||
/// <returns>Random number.</returns>
|
||||
uint32 GetUnsignedInt() const
|
||||
{
|
||||
MutateSeed();
|
||||
@@ -108,7 +109,6 @@ public:
|
||||
/// <summary>
|
||||
/// Returns a random number between 0 and 1.
|
||||
/// </summary>
|
||||
/// <returns>Random number.</returns>
|
||||
float GetFraction() const
|
||||
{
|
||||
MutateSeed();
|
||||
@@ -121,7 +121,6 @@ public:
|
||||
/// <summary>
|
||||
/// Returns a random number between 0 and 1.
|
||||
/// </summary>
|
||||
/// <returns>Random number.</returns>
|
||||
FORCE_INLINE float Rand() const
|
||||
{
|
||||
return GetFraction();
|
||||
@@ -130,7 +129,6 @@ public:
|
||||
/// <summary>
|
||||
/// Returns a random vector of unit size.
|
||||
/// </summary>
|
||||
/// <returns>Random unit length vector</returns>
|
||||
Float3 GetUnitVector() const
|
||||
{
|
||||
Float3 result;
|
||||
@@ -144,11 +142,10 @@ public:
|
||||
} while (l > 1.0f || l < ZeroTolerance);
|
||||
return Float3::Normalize(result);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random <see cref="Vector3"/> with components in a range between [0;1].
|
||||
/// </summary>
|
||||
/// <returns>A random <see cref="Vector3"/>.</returns>
|
||||
Vector3 GetVector3() const
|
||||
{
|
||||
return Vector3(GetFraction(), GetFraction(), GetFraction());
|
||||
@@ -157,11 +154,11 @@ public:
|
||||
/// <summary>
|
||||
/// Helper function for rand implementations.
|
||||
/// </summary>
|
||||
/// <param name="A">Top border</param>
|
||||
/// <param name="a">Top border</param>
|
||||
/// <returns>A random number in [0..A)</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -188,7 +185,6 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/// <summary>
|
||||
/// Mutates the current seed into the next seed.
|
||||
/// </summary>
|
||||
|
||||
110
Source/Engine/Tests/TestCollections.cpp
Normal file
110
Source/Engine/Tests/TestCollections.cpp
Normal file
@@ -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 <ThirdParty/catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("Array")
|
||||
{
|
||||
SECTION("Test Allocators")
|
||||
{
|
||||
Array<int32> a1;
|
||||
Array<int32, InlinedAllocation<8>> a2;
|
||||
Array<int32, FixedAllocation<8>> 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<uint32> 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<uint32> a1(testData);
|
||||
const Array<uint32, InlinedAllocation<8>> a2(testData);
|
||||
const Array<uint32, InlinedAllocation<64>> a3(testData);
|
||||
const Array<uint32, FixedAllocation<64>> a4(testData);
|
||||
CHECK(a1 == testData);
|
||||
CHECK(a2 == testData);
|
||||
CHECK(a3 == testData);
|
||||
CHECK(a4 == testData);
|
||||
}
|
||||
|
||||
SECTION("Test Copy Operator")
|
||||
{
|
||||
Array<uint32> a1;
|
||||
a1 = testData;
|
||||
CHECK(a1 == testData);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("BitArray")
|
||||
{
|
||||
SECTION("Test Allocators")
|
||||
{
|
||||
BitArray<> a1;
|
||||
BitArray<InlinedAllocation<8>> a2;
|
||||
BitArray<FixedAllocation<8>> 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<InlinedAllocation<8>> a2(testData);
|
||||
const BitArray<InlinedAllocation<64>> a3(testData);
|
||||
const BitArray<FixedAllocation<64>> 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user