Merge remote-tracking branch 'origin/master' into 1.8

This commit is contained in:
Wojtek Figat
2023-12-08 11:23:06 +01:00
155 changed files with 4997 additions and 2971 deletions

View File

@@ -25,6 +25,19 @@ private:
int32 _capacity;
AllocationData _allocation;
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromCount, int32 fromCapacity)
{
if IF_CONSTEXPR (AllocationType::HasSwap)
to.Swap(from);
else
{
to.Allocate(fromCapacity);
Memory::MoveItems(to.Get(), from.Get(), fromCount);
Memory::DestructItems(from.Get(), fromCount);
from.Free();
}
}
public:
/// <summary>
/// Initializes a new instance of the <see cref="Array"/> class.
@@ -134,7 +147,7 @@ public:
_capacity = other._capacity;
other._count = 0;
other._capacity = 0;
_allocation.Swap(other._allocation);
MoveToEmpty(_allocation, other._allocation, _count, _capacity);
}
/// <summary>
@@ -191,7 +204,7 @@ public:
_capacity = other._capacity;
other._count = 0;
other._capacity = 0;
_allocation.Swap(other._allocation);
MoveToEmpty(_allocation, other._allocation, _count, _capacity);
}
return *this;
}
@@ -713,9 +726,18 @@ public:
/// <param name="other">The other collection.</param>
void Swap(Array& other)
{
::Swap(_count, other._count);
::Swap(_capacity, other._capacity);
_allocation.Swap(other._allocation);
if IF_CONSTEXPR (AllocationType::HasSwap)
{
_allocation.Swap(other._allocation);
::Swap(_count, other._count);
::Swap(_capacity, other._capacity);
}
else
{
Array tmp = MoveTemp(other);
other = *this;
*this = MoveTemp(tmp);
}
}
/// <summary>
@@ -726,9 +748,7 @@ public:
T* data = _allocation.Get();
const int32 count = _count / 2;
for (int32 i = 0; i < count; i++)
{
::Swap(data[i], data[_count - i - 1]);
}
}
public:

View File

@@ -55,9 +55,7 @@ public:
for (int32 i = 0; i < obj.Count(); i++)
{
if (predicate(obj[i]))
{
return i;
}
}
return INVALID_INDEX;
}
@@ -74,9 +72,7 @@ public:
for (int32 i = 0; i < obj.Count(); i++)
{
if (predicate(obj[i]))
{
return true;
}
}
return false;
}
@@ -93,13 +89,101 @@ public:
for (int32 i = 0; i < obj.Count(); i++)
{
if (!predicate(obj[i]))
{
return false;
}
}
return true;
}
/// <summary>
/// Filters a sequence of values based on a predicate.
/// </summary>
/// <param name="obj">The target collection.</param>
/// <param name="predicate">The prediction function. Return true for elements that should be included in result list.</param>
/// <param name="result">The result list with items that passed the predicate.</param>
template<typename T, typename AllocationType>
static void Where(const Array<T, AllocationType>& obj, const Function<bool(const T&)>& predicate, Array<T, AllocationType>& result)
{
for (const T& i : obj)
{
if (predicate(i))
result.Add(i);
}
}
/// <summary>
/// Filters a sequence of values based on a predicate.
/// </summary>
/// <param name="obj">The target collection.</param>
/// <param name="predicate">The prediction function. Return true for elements that should be included in result list.</param>
/// <returns>The result list with items that passed the predicate.</returns>
template<typename T, typename AllocationType>
static Array<T, AllocationType> Where(const Array<T, AllocationType>& obj, const Function<bool(const T&)>& predicate)
{
Array<T, AllocationType> result;
Where(obj, predicate, result);
return result;
}
/// <summary>
/// Projects each element of a sequence into a new form.
/// </summary>
/// <param name="obj">The target collection.</param>
/// <param name="selector">A transform function to apply to each source element; the second parameter of the function represents the index of the source element.</param>
/// <param name="result">The result list whose elements are the result of invoking the transform function on each element of source.</param>
template<typename TResult, typename TSource, typename AllocationType>
static void Select(const Array<TSource, AllocationType>& obj, const Function<TResult(const TSource&)>& selector, Array<TResult, AllocationType>& result)
{
for (const TSource& i : obj)
result.Add(MoveTemp(selector(i)));
}
/// <summary>
/// Projects each element of a sequence into a new form.
/// </summary>
/// <param name="obj">The target collection.</param>
/// <param name="selector">A transform function to apply to each source element; the second parameter of the function represents the index of the source element.</param>
/// <returns>The result list whose elements are the result of invoking the transform function on each element of source.</returns>
template<typename TResult, typename TSource, typename AllocationType>
static Array<TResult, AllocationType> Select(const Array<TSource, AllocationType>& obj, const Function<TResult(const TSource&)>& selector)
{
Array<TResult, AllocationType> result;
Select(obj, selector, result);
return result;
}
/// <summary>
/// Removes all the elements that match the conditions defined by the specified predicate.
/// </summary>
/// <param name="obj">The target collection to modify.</param>
/// <param name="predicate">A transform function that defines the conditions of the elements to remove.</param>
template<typename T, typename AllocationType>
static void RemoveAll(Array<T, AllocationType>& obj, const Function<bool(const T&)>& predicate)
{
for (int32 i = obj.Count() - 1; i >= 0; i--)
{
if (predicate(obj[i]))
obj.RemoveAtKeepOrder(i);
}
}
/// <summary>
/// Removes all the elements that match the conditions defined by the specified predicate.
/// </summary>
/// <param name="obj">The target collection to process.</param>
/// <param name="predicate">A transform function that defines the conditions of the elements to remove.</param>
/// <returns>The result list whose elements are the result of invoking the transform function on each element of source.</returns>
template<typename T, typename AllocationType>
static Array<T, AllocationType> RemoveAll(const Array<T, AllocationType>& obj, const Function<bool(const T&)>& predicate)
{
Array<T, AllocationType> result;
for (const T& i : obj)
{
if (!predicate(i))
result.Ass(i);
}
return result;
}
/// <summary>
/// Groups the elements of a sequence according to a specified key selector function.
/// </summary>
@@ -109,7 +193,7 @@ public:
template<typename TSource, typename TKey, typename AllocationType>
static void GroupBy(const Array<TSource, AllocationType>& obj, const Function<TKey(TSource const&)>& keySelector, Array<IGrouping<TKey, TSource>, AllocationType>& result)
{
Dictionary<TKey, IGrouping<TKey, TSource>> data(static_cast<int32>(obj.Count() * 3.0f));
Dictionary<TKey, IGrouping<TKey, TSource>> data;
for (int32 i = 0; i < obj.Count(); i++)
{
const TKey key = keySelector(obj[i]);

View File

@@ -110,6 +110,33 @@ private:
int32 _size = 0;
AllocationData _allocation;
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromSize)
{
if IF_CONSTEXPR (AllocationType::HasSwap)
to.Swap(from);
else
{
to.Allocate(fromSize);
Bucket* toData = to.Get();
Bucket* fromData = from.Get();
for (int32 i = 0; i < fromSize; i++)
{
Bucket& fromBucket = fromData[i];
if (fromBucket.IsOccupied())
{
Bucket& toBucket = toData[i];
Memory::MoveItems(&toBucket.Key, &fromBucket.Key, 1);
Memory::MoveItems(&toBucket.Value, &fromBucket.Value, 1);
toBucket._state = Bucket::Occupied;
Memory::DestructItem(&fromBucket.Key);
Memory::DestructItem(&fromBucket.Value);
fromBucket._state = Bucket::Empty;
}
}
from.Free();
}
}
public:
/// <summary>
/// Initializes a new instance of the <see cref="Dictionary"/> class.
@@ -139,7 +166,7 @@ public:
other._elementsCount = 0;
other._deletedCount = 0;
other._size = 0;
_allocation.Swap(other._allocation);
MoveToEmpty(_allocation, other._allocation, _size);
}
/// <summary>
@@ -180,7 +207,7 @@ public:
other._elementsCount = 0;
other._deletedCount = 0;
other._size = 0;
_allocation.Swap(other._allocation);
MoveToEmpty(_allocation, other._allocation, _size);
}
return *this;
}
@@ -510,7 +537,7 @@ public:
return;
ASSERT(capacity >= 0);
AllocationData oldAllocation;
oldAllocation.Swap(_allocation);
MoveToEmpty(oldAllocation, _allocation, _size);
const int32 oldSize = _size;
const int32 oldElementsCount = _elementsCount;
_deletedCount = _elementsCount = 0;
@@ -580,10 +607,19 @@ public:
/// <param name="other">The other collection.</param>
void Swap(Dictionary& other)
{
::Swap(_elementsCount, other._elementsCount);
::Swap(_deletedCount, other._deletedCount);
::Swap(_size, other._size);
_allocation.Swap(other._allocation);
if IF_CONSTEXPR (AllocationType::HasSwap)
{
::Swap(_elementsCount, other._elementsCount);
::Swap(_deletedCount, other._deletedCount);
::Swap(_size, other._size);
_allocation.Swap(other._allocation);
}
else
{
Dictionary tmp = MoveTemp(other);
other = *this;
*this = MoveTemp(tmp);
}
}
public:
@@ -930,7 +966,7 @@ private:
{
// Rebuild entire table completely
AllocationData oldAllocation;
oldAllocation.Swap(_allocation);
MoveToEmpty(oldAllocation, _allocation, _size);
_allocation.Allocate(_size);
Bucket* data = _allocation.Get();
for (int32 i = 0; i < _size; i++)

View File

@@ -93,6 +93,31 @@ private:
int32 _size = 0;
AllocationData _allocation;
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromSize)
{
if IF_CONSTEXPR (AllocationType::HasSwap)
to.Swap(from);
else
{
to.Allocate(fromSize);
Bucket* toData = to.Get();
Bucket* fromData = from.Get();
for (int32 i = 0; i < fromSize; i++)
{
Bucket& fromBucket = fromData[i];
if (fromBucket.IsOccupied())
{
Bucket& toBucket = toData[i];
Memory::MoveItems(&toBucket.Item, &fromBucket.Item, 1);
toBucket._state = Bucket::Occupied;
Memory::DestructItem(&fromBucket.Item);
fromBucket._state = Bucket::Empty;
}
}
from.Free();
}
}
public:
/// <summary>
/// Initializes a new instance of the <see cref="HashSet"/> class.
@@ -122,7 +147,7 @@ public:
other._elementsCount = 0;
other._deletedCount = 0;
other._size = 0;
_allocation.Swap(other._allocation);
MoveToEmpty(_allocation, other._allocation, _size);
}
/// <summary>
@@ -163,7 +188,7 @@ public:
other._elementsCount = 0;
other._deletedCount = 0;
other._size = 0;
_allocation.Swap(other._allocation);
MoveToEmpty(_allocation, other._allocation, _size);
}
return *this;
}
@@ -389,7 +414,7 @@ public:
return;
ASSERT(capacity >= 0);
AllocationData oldAllocation;
oldAllocation.Swap(_allocation);
MoveToEmpty(oldAllocation, _allocation, _size);
const int32 oldSize = _size;
const int32 oldElementsCount = _elementsCount;
_deletedCount = _elementsCount = 0;
@@ -458,10 +483,19 @@ public:
/// <param name="other">The other collection.</param>
void Swap(HashSet& other)
{
::Swap(_elementsCount, other._elementsCount);
::Swap(_deletedCount, other._deletedCount);
::Swap(_size, other._size);
_allocation.Swap(other._allocation);
if IF_CONSTEXPR (AllocationType::HasSwap)
{
::Swap(_elementsCount, other._elementsCount);
::Swap(_deletedCount, other._deletedCount);
::Swap(_size, other._size);
_allocation.Swap(other._allocation);
}
else
{
HashSet tmp = MoveTemp(other);
other = *this;
*this = MoveTemp(tmp);
}
}
public:
@@ -726,7 +760,7 @@ private:
{
// Rebuild entire table completely
AllocationData oldAllocation;
oldAllocation.Swap(_allocation);
MoveToEmpty(oldAllocation, _allocation, _size);
_allocation.Allocate(_size);
Bucket* data = _allocation.Get();
for (int32 i = 0; i < _size; i++)

View File

@@ -45,6 +45,16 @@ public:
};
public:
/// <summary>
/// Sorts the linear data array using Quick Sort algorithm (non recursive version, uses temporary stack collection).
/// </summary>
/// <param name="data">The data container.</param>
template<typename T, typename AllocationType = HeapAllocation>
FORCE_INLINE static void QuickSort(Array<T, AllocationType>& data)
{
QuickSort(data.Get(), data.Count());
}
/// <summary>
/// Sorts the linear data array using Quick Sort algorithm (non recursive version, uses temporary stack collection).
/// </summary>

View File

@@ -93,3 +93,10 @@
#endif
#define PACK_STRUCT(__Declaration__) PACK_BEGIN() __Declaration__ PACK_END()
// C++ 17
#if __cplusplus >= 201703L
#define IF_CONSTEXPR constexpr
#else
#define IF_CONSTEXPR
#endif

View File

@@ -58,7 +58,7 @@ bool Log::Logger::Init()
int32 remaining = oldLogs.Count() - maxLogFiles + 1;
if (remaining > 0)
{
Sorting::QuickSort(oldLogs.Get(), oldLogs.Count());
Sorting::QuickSort(oldLogs);
// Delete the oldest logs
int32 i = 0;

View File

@@ -15,6 +15,8 @@ const Float2 Float2::Zero(0.0f);
template<>
const Float2 Float2::One(1.0f);
template<>
const Float2 Float2::Half(0.5f);
template<>
const Float2 Float2::UnitX(1.0f, 0.0f);
template<>
const Float2 Float2::UnitY(0.0f, 1.0f);

View File

@@ -44,6 +44,9 @@ public:
// Vector with all components equal 1
static FLAXENGINE_API const Vector2Base<T> One;
// Vector with all components equal 0.5
static FLAXENGINE_API const Vector2Base<T> Half;
// Vector X=1, Y=0
static FLAXENGINE_API const Vector2Base<T> UnitX;

View File

@@ -17,6 +17,8 @@ const Float4 Float4::Zero(0.0f);
template<>
const Float4 Float4::One(1.0f);
template<>
const Float4 Float4::Half(0.5f);
template<>
const Float4 Float4::UnitX(1.0f, 0.0f, 0.0f, 0.0f);
template<>
const Float4 Float4::UnitY(0.0f, 1.0f, 0.0f, 0.0f);

View File

@@ -54,6 +54,9 @@ public:
// Vector with all components equal 1
static FLAXENGINE_API const Vector4Base<T> One;
// Vector with all components equal 0.5
static FLAXENGINE_API const Vector4Base<T> Half;
// Vector X=1, Y=0, Z=0, W=0
static FLAXENGINE_API const Vector4Base<T> UnitX;

View File

@@ -12,6 +12,8 @@ template<int Capacity>
class FixedAllocation
{
public:
enum { HasSwap = false };
template<typename T>
class Data
{
@@ -61,12 +63,9 @@ public:
{
}
FORCE_INLINE void Swap(Data& other)
void Swap(Data& other)
{
byte tmp[Capacity * sizeof(T)];
Platform::MemoryCopy(tmp, _data, Capacity * sizeof(T));
Platform::MemoryCopy(_data, other._data, Capacity * sizeof(T));
Platform::MemoryCopy(other._data, tmp, Capacity * sizeof(T));
// Not supported
}
};
};
@@ -77,6 +76,8 @@ public:
class HeapAllocation
{
public:
enum { HasSwap = true };
template<typename T>
class Data
{
@@ -179,6 +180,8 @@ template<int Capacity, typename OtherAllocator = HeapAllocation>
class InlinedAllocation
{
public:
enum { HasSwap = false };
template<typename T>
class Data
{
@@ -267,14 +270,9 @@ public:
}
}
FORCE_INLINE void Swap(Data& other)
void Swap(Data& other)
{
byte tmp[Capacity * sizeof(T)];
Platform::MemoryCopy(tmp, _data, Capacity * sizeof(T));
Platform::MemoryCopy(_data, other._data, Capacity * sizeof(T));
Platform::MemoryCopy(other._data, tmp, Capacity * sizeof(T));
::Swap(_useOther, other._useOther);
_other.Swap(other._other);
// Not supported
}
};
};