Add Array/BitArray tests and fix some detected problems

This commit is contained in:
Wojciech Figat
2022-08-19 11:18:48 +02:00
parent ed7cc96889
commit bf30d7cd29
4 changed files with 185 additions and 41 deletions

View File

@@ -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);
}

View File

@@ -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);
}
};

View File

@@ -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>

View 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);
}
}