Compare commits

...

4 Commits

6 changed files with 1995 additions and 18 deletions

View File

@ -4,6 +4,7 @@
#include "Containers/Array.h"
#include "Containers/List.h"
#include "Ranges/Factory.h"
#include "Numerics/Math.h"
#include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN
@ -121,11 +122,243 @@ void TestBasic()
}
}
void TestSearch()
{
{
TArray<int> Arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
TList<int> Brr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto Crr = Ranges::Iota(0, 10);
always_check( Algorithms::AllOf(Arr, [](int A) { return A < 10; }));
always_check( Algorithms::AllOf(Brr, [](int A) { return A < 10; }));
always_check( Algorithms::AllOf(Crr, [](int A) { return A < 10; }));
always_check(!Algorithms::AllOf(Arr, [](int A) { return A > 5; }));
always_check(!Algorithms::AllOf(Brr, [](int A) { return A > 5; }));
always_check(!Algorithms::AllOf(Crr, [](int A) { return A > 5; }));
always_check( Algorithms::AllOf(Arr.Begin(), Arr.End(), [](int A) { return A < 10; }));
always_check( Algorithms::AllOf(Brr.Begin(), Brr.End(), [](int A) { return A < 10; }));
always_check( Algorithms::AllOf(Crr.Begin(), Crr.End(), [](int A) { return A < 10; }));
always_check(!Algorithms::AllOf(Arr.Begin(), Arr.End(), [](int A) { return A > 5; }));
always_check(!Algorithms::AllOf(Brr.Begin(), Brr.End(), [](int A) { return A > 5; }));
always_check(!Algorithms::AllOf(Crr.Begin(), Crr.End(), [](int A) { return A > 5; }));
always_check(Algorithms::AnyOf(Arr, [](int A) { return A < 10; }));
always_check(Algorithms::AnyOf(Brr, [](int A) { return A < 10; }));
always_check(Algorithms::AnyOf(Crr, [](int A) { return A < 10; }));
always_check(Algorithms::AnyOf(Arr, [](int A) { return A > 5; }));
always_check(Algorithms::AnyOf(Brr, [](int A) { return A > 5; }));
always_check(Algorithms::AnyOf(Crr, [](int A) { return A > 5; }));
always_check(Algorithms::AnyOf(Arr.Begin(), Arr.End(), [](int A) { return A < 10; }));
always_check(Algorithms::AnyOf(Brr.Begin(), Brr.End(), [](int A) { return A < 10; }));
always_check(Algorithms::AnyOf(Crr.Begin(), Crr.End(), [](int A) { return A < 10; }));
always_check(Algorithms::AnyOf(Arr.Begin(), Arr.End(), [](int A) { return A > 5; }));
always_check(Algorithms::AnyOf(Brr.Begin(), Brr.End(), [](int A) { return A > 5; }));
always_check(Algorithms::AnyOf(Crr.Begin(), Crr.End(), [](int A) { return A > 5; }));
always_check(!Algorithms::NoneOf(Arr, [](int A) { return A < 10; }));
always_check(!Algorithms::NoneOf(Brr, [](int A) { return A < 10; }));
always_check(!Algorithms::NoneOf(Crr, [](int A) { return A < 10; }));
always_check(!Algorithms::NoneOf(Arr, [](int A) { return A > 5; }));
always_check(!Algorithms::NoneOf(Brr, [](int A) { return A > 5; }));
always_check(!Algorithms::NoneOf(Crr, [](int A) { return A > 5; }));
always_check(!Algorithms::NoneOf(Arr.Begin(), Arr.End(), [](int A) { return A < 10; }));
always_check(!Algorithms::NoneOf(Brr.Begin(), Brr.End(), [](int A) { return A < 10; }));
always_check(!Algorithms::NoneOf(Crr.Begin(), Crr.End(), [](int A) { return A < 10; }));
always_check(!Algorithms::NoneOf(Arr.Begin(), Arr.End(), [](int A) { return A > 5; }));
always_check(!Algorithms::NoneOf(Brr.Begin(), Brr.End(), [](int A) { return A > 5; }));
always_check(!Algorithms::NoneOf(Crr.Begin(), Crr.End(), [](int A) { return A > 5; }));
always_check( Algorithms::Contains(Arr, 5));
always_check( Algorithms::Contains(Brr, 5));
always_check( Algorithms::Contains(Crr, 5));
always_check(!Algorithms::Contains(Arr, 10));
always_check(!Algorithms::Contains(Brr, 10));
always_check(!Algorithms::Contains(Crr, 10));
always_check( Algorithms::Contains(Arr.Begin(), Arr.End(), 5));
always_check( Algorithms::Contains(Brr.Begin(), Brr.End(), 5));
always_check( Algorithms::Contains(Crr.Begin(), Crr.End(), 5));
always_check(!Algorithms::Contains(Arr.Begin(), Arr.End(), 10));
always_check(!Algorithms::Contains(Brr.Begin(), Brr.End(), 10));
always_check(!Algorithms::Contains(Crr.Begin(), Crr.End(), 10));
auto Projection = [](int A) { return A % 4; }; // Project to { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1 }
always_check(Algorithms::Find(Arr, 2, { }, Projection) == Algorithms::Next(Arr.Begin(), 2));
always_check(Algorithms::Find(Brr, 2, { }, Projection) == Algorithms::Next(Brr.Begin(), 2));
always_check(Algorithms::Find(Crr, 2, { }, Projection) == Algorithms::Next(Crr.Begin(), 2));
always_check(Algorithms::Find(Arr.Begin(), Arr.End(), 2, { }, Projection) == Algorithms::Next(Arr.Begin(), 2));
always_check(Algorithms::Find(Brr.Begin(), Brr.End(), 2, { }, Projection) == Algorithms::Next(Brr.Begin(), 2));
always_check(Algorithms::Find(Crr.Begin(), Crr.End(), 2, { }, Projection) == Algorithms::Next(Crr.Begin(), 2));
always_check(Algorithms::Find(Arr, 10) == Arr.End());
always_check(Algorithms::Find(Brr, 10) == Brr.End());
always_check(Algorithms::Find(Crr, 10) == Crr.End());
always_check(Algorithms::Find(Arr, Ranges::Iota(1, 4), { }, Projection).Begin() == Algorithms::Next(Arr.Begin()));
always_check(Algorithms::Find(Brr, Ranges::Iota(1, 4), { }, Projection).Begin() == Algorithms::Next(Brr.Begin()));
always_check(Algorithms::Find(Crr, Ranges::Iota(1, 4), { }, Projection).Begin() == Algorithms::Next(Crr.Begin()));
always_check(Algorithms::Find(Arr, Ranges::Iota(4, 16)).IsEmpty());
always_check(Algorithms::Find(Brr, Ranges::Iota(4, 16)).IsEmpty());
always_check(Algorithms::Find(Crr, Ranges::Iota(4, 16)).IsEmpty());
always_check(Algorithms::FindIf(Arr, [](int A) { return A == 2; }, Projection) == Algorithms::Next(Arr.Begin(), 2));
always_check(Algorithms::FindIf(Brr, [](int A) { return A == 2; }, Projection) == Algorithms::Next(Brr.Begin(), 2));
always_check(Algorithms::FindIf(Crr, [](int A) { return A == 2; }, Projection) == Algorithms::Next(Crr.Begin(), 2));
always_check(Algorithms::FindIf(Arr.Begin(), Arr.End(), [](int A) { return A == 2; }, Projection) == Algorithms::Next(Arr.Begin(), 2));
always_check(Algorithms::FindIf(Brr.Begin(), Brr.End(), [](int A) { return A == 2; }, Projection) == Algorithms::Next(Brr.Begin(), 2));
always_check(Algorithms::FindIf(Crr.Begin(), Crr.End(), [](int A) { return A == 2; }, Projection) == Algorithms::Next(Crr.Begin(), 2));
always_check(Algorithms::FindIf(Arr, [](int A) { return A == 10; }) == Arr.End());
always_check(Algorithms::FindIf(Brr, [](int A) { return A == 10; }) == Brr.End());
always_check(Algorithms::FindIf(Crr, [](int A) { return A == 10; }) == Crr.End());
always_check(Algorithms::FindIfNot(Arr, [](int A) { return A > 0; }, Projection) == Arr.Begin());
always_check(Algorithms::FindIfNot(Brr, [](int A) { return A > 0; }, Projection) == Brr.Begin());
always_check(Algorithms::FindIfNot(Crr, [](int A) { return A > 0; }, Projection) == Crr.Begin());
always_check(Algorithms::FindIfNot(Arr.Begin(), Arr.End(), [](int A) { return A > 0; }, Projection) == Arr.Begin());
always_check(Algorithms::FindIfNot(Brr.Begin(), Brr.End(), [](int A) { return A > 0; }, Projection) == Brr.Begin());
always_check(Algorithms::FindIfNot(Crr.Begin(), Crr.End(), [](int A) { return A > 0; }, Projection) == Crr.Begin());
always_check(Algorithms::FindIfNot(Arr, [](int A) { return A < 8; }) == Algorithms::Next(Arr.Begin(), 8));
always_check(Algorithms::FindIfNot(Brr, [](int A) { return A < 8; }) == Algorithms::Next(Brr.Begin(), 8));
always_check(Algorithms::FindIfNot(Crr, [](int A) { return A < 8; }) == Algorithms::Next(Crr.Begin(), 8));
always_check(Algorithms::FindLast(Arr, 2, { }, Projection) == Algorithms::Next(Arr.Begin(), 6));
always_check(Algorithms::FindLast(Brr, 2, { }, Projection) == Algorithms::Next(Brr.Begin(), 6));
always_check(Algorithms::FindLast(Crr, 2, { }, Projection) == Algorithms::Next(Crr.Begin(), 6));
always_check(Algorithms::FindLast(Arr.Begin(), Arr.End(), 2, { }, Projection) == Algorithms::Next(Arr.Begin(), 6));
always_check(Algorithms::FindLast(Brr.Begin(), Brr.End(), 2, { }, Projection) == Algorithms::Next(Brr.Begin(), 6));
always_check(Algorithms::FindLast(Crr.Begin(), Crr.End(), 2, { }, Projection) == Algorithms::Next(Crr.Begin(), 6));
always_check(Algorithms::FindLast(Arr, 10) == Arr.End());
always_check(Algorithms::FindLast(Brr, 10) == Brr.End());
always_check(Algorithms::FindLast(Crr, 10) == Crr.End());
always_check(Algorithms::FindLast(Arr, Ranges::Iota(1, 4), { }, Projection).Begin() == Algorithms::Next(Arr.Begin(), 5));
always_check(Algorithms::FindLast(Brr, Ranges::Iota(1, 4), { }, Projection).Begin() == Algorithms::Next(Brr.Begin(), 5));
always_check(Algorithms::FindLast(Crr, Ranges::Iota(1, 4), { }, Projection).Begin() == Algorithms::Next(Crr.Begin(), 5));
always_check(Algorithms::FindLast(Arr, Ranges::Iota(4, 16)).IsEmpty());
always_check(Algorithms::FindLast(Brr, Ranges::Iota(4, 16)).IsEmpty());
always_check(Algorithms::FindLast(Crr, Ranges::Iota(4, 16)).IsEmpty());
always_check(Algorithms::FindLastIf(Arr, [](int A) { return A == 2; }, Projection) == Algorithms::Next(Arr.Begin(), 6));
always_check(Algorithms::FindLastIf(Brr, [](int A) { return A == 2; }, Projection) == Algorithms::Next(Brr.Begin(), 6));
always_check(Algorithms::FindLastIf(Crr, [](int A) { return A == 2; }, Projection) == Algorithms::Next(Crr.Begin(), 6));
always_check(Algorithms::FindLastIf(Arr.Begin(), Arr.End(), [](int A) { return A == 2; }, Projection) == Algorithms::Next(Arr.Begin(), 6));
always_check(Algorithms::FindLastIf(Brr.Begin(), Brr.End(), [](int A) { return A == 2; }, Projection) == Algorithms::Next(Brr.Begin(), 6));
always_check(Algorithms::FindLastIf(Crr.Begin(), Crr.End(), [](int A) { return A == 2; }, Projection) == Algorithms::Next(Crr.Begin(), 6));
always_check(Algorithms::FindLastIf(Arr, [](int A) { return A == 10; }) == Arr.End());
always_check(Algorithms::FindLastIf(Brr, [](int A) { return A == 10; }) == Brr.End());
always_check(Algorithms::FindLastIf(Crr, [](int A) { return A == 10; }) == Crr.End());
always_check(Algorithms::FindLastIfNot(Arr, [](int A) { return A > 0; }, Projection) == Algorithms::Next(Arr.Begin(), 8));
always_check(Algorithms::FindLastIfNot(Brr, [](int A) { return A > 0; }, Projection) == Algorithms::Next(Brr.Begin(), 8));
always_check(Algorithms::FindLastIfNot(Crr, [](int A) { return A > 0; }, Projection) == Algorithms::Next(Crr.Begin(), 8));
always_check(Algorithms::FindLastIfNot(Arr.Begin(), Arr.End(), [](int A) { return A > 0; }, Projection) == Algorithms::Next(Arr.Begin(), 8));
always_check(Algorithms::FindLastIfNot(Brr.Begin(), Brr.End(), [](int A) { return A > 0; }, Projection) == Algorithms::Next(Brr.Begin(), 8));
always_check(Algorithms::FindLastIfNot(Crr.Begin(), Crr.End(), [](int A) { return A > 0; }, Projection) == Algorithms::Next(Crr.Begin(), 8));
always_check(Algorithms::FindLastIfNot(Arr, [](int A) { return A < 8; }) == Algorithms::Next(Arr.Begin(), 9));
always_check(Algorithms::FindLastIfNot(Brr, [](int A) { return A < 8; }) == Algorithms::Next(Brr.Begin(), 9));
always_check(Algorithms::FindLastIfNot(Crr, [](int A) { return A < 8; }) == Algorithms::Next(Crr.Begin(), 9));
always_check(Algorithms::FindAdjacent(Arr, { }, [](int A) { return Math::DivAndCeil(A, 2); }) == Algorithms::Next(Arr.Begin()));
always_check(Algorithms::FindAdjacent(Brr, { }, [](int A) { return Math::DivAndCeil(A, 2); }) == Algorithms::Next(Brr.Begin()));
always_check(Algorithms::FindAdjacent(Crr, { }, [](int A) { return Math::DivAndCeil(A, 2); }) == Algorithms::Next(Crr.Begin()));
always_check(Algorithms::FindAdjacent(Arr.Begin(), Arr.End(), { }, [](int A) { return Math::DivAndCeil(A, 2); }) == Algorithms::Next(Arr.Begin()));
always_check(Algorithms::FindAdjacent(Brr.Begin(), Brr.End(), { }, [](int A) { return Math::DivAndCeil(A, 2); }) == Algorithms::Next(Brr.Begin()));
always_check(Algorithms::FindAdjacent(Crr.Begin(), Crr.End(), { }, [](int A) { return Math::DivAndCeil(A, 2); }) == Algorithms::Next(Crr.Begin()));
always_check(Algorithms::FindAdjacent(Arr) == Arr.End());
always_check(Algorithms::FindAdjacent(Brr) == Brr.End());
always_check(Algorithms::FindAdjacent(Crr) == Crr.End());
always_check(Algorithms::Count(Arr, 2, { }, Projection) == 2);
always_check(Algorithms::Count(Brr, 2, { }, Projection) == 2);
always_check(Algorithms::Count(Crr, 2, { }, Projection) == 2);
always_check(Algorithms::Count(Arr.Begin(), Arr.End(), 2, { }, Projection) == 2);
always_check(Algorithms::Count(Brr.Begin(), Brr.End(), 2, { }, Projection) == 2);
always_check(Algorithms::Count(Crr.Begin(), Crr.End(), 2, { }, Projection) == 2);
always_check(Algorithms::Count(Arr, 10) == 0);
always_check(Algorithms::Count(Brr, 10) == 0);
always_check(Algorithms::Count(Crr, 10) == 0);
always_check(Algorithms::CountIf(Arr, [](int A) { return A == 2; }, Projection) == 2);
always_check(Algorithms::CountIf(Brr, [](int A) { return A == 2; }, Projection) == 2);
always_check(Algorithms::CountIf(Crr, [](int A) { return A == 2; }, Projection) == 2);
always_check(Algorithms::CountIf(Arr.Begin(), Arr.End(), [](int A) { return A == 2; }, Projection) == 2);
always_check(Algorithms::CountIf(Brr.Begin(), Brr.End(), [](int A) { return A == 2; }, Projection) == 2);
always_check(Algorithms::CountIf(Crr.Begin(), Crr.End(), [](int A) { return A == 2; }, Projection) == 2);
always_check(Algorithms::CountIf(Arr, [](int A) { return A == 10; }) == 0);
always_check(Algorithms::CountIf(Brr, [](int A) { return A == 10; }) == 0);
always_check(Algorithms::CountIf(Crr, [](int A) { return A == 10; }) == 0);
always_check(Algorithms::Mismatch(Arr, Arr, { }, Projection) == MakeTuple(Algorithms::Next(Arr.Begin(), 4), Algorithms::Next(Arr.Begin(), 4)));
always_check(Algorithms::Mismatch(Brr, Brr, { }, Projection) == MakeTuple(Algorithms::Next(Brr.Begin(), 4), Algorithms::Next(Brr.Begin(), 4)));
always_check(Algorithms::Mismatch(Crr, Crr, { }, Projection) == MakeTuple(Algorithms::Next(Crr.Begin(), 4), Algorithms::Next(Crr.Begin(), 4)));
always_check(Algorithms::Mismatch(Arr.Begin(), Arr.End(), Brr.Begin(), Brr.End(), { }, Projection) == MakeTuple(Algorithms::Next(Arr.Begin(), 4), Algorithms::Next(Brr.Begin(), 4)));
always_check(Algorithms::Mismatch(Brr.Begin(), Brr.End(), Crr.Begin(), Crr.End(), { }, Projection) == MakeTuple(Algorithms::Next(Brr.Begin(), 4), Algorithms::Next(Crr.Begin(), 4)));
always_check(Algorithms::Mismatch(Crr.Begin(), Crr.End(), Arr.Begin(), Arr.End(), { }, Projection) == MakeTuple(Algorithms::Next(Crr.Begin(), 4), Algorithms::Next(Arr.Begin(), 4)));
always_check(Algorithms::Mismatch(Arr, Brr, { }, Projection) == MakeTuple(Algorithms::Next(Arr.Begin(), 4), Algorithms::Next(Brr.Begin(), 4)));
always_check(Algorithms::Mismatch(Brr, Crr, { }, Projection) == MakeTuple(Algorithms::Next(Brr.Begin(), 4), Algorithms::Next(Crr.Begin(), 4)));
always_check(Algorithms::Mismatch(Crr, Arr, { }, Projection) == MakeTuple(Algorithms::Next(Crr.Begin(), 4), Algorithms::Next(Arr.Begin(), 4)));
always_check(Algorithms::Equal(Arr, Arr));
always_check(Algorithms::Equal(Brr, Brr));
always_check(Algorithms::Equal(Crr, Crr));
always_check(Algorithms::Equal(Arr.Begin(), Arr.End(), Brr.Begin(), Brr.End()));
always_check(Algorithms::Equal(Brr.Begin(), Brr.End(), Crr.Begin(), Crr.End()));
always_check(Algorithms::Equal(Crr.Begin(), Crr.End(), Arr.Begin(), Arr.End()));
always_check(Algorithms::Equal(Arr, Brr));
always_check(Algorithms::Equal(Brr, Crr));
always_check(Algorithms::Equal(Crr, Arr));
always_check(Algorithms::StartsWith(Arr, Ranges::Iota(0, 8)));
always_check(Algorithms::StartsWith(Brr, Ranges::Iota(0, 8)));
always_check(Algorithms::StartsWith(Crr, Ranges::Iota(0, 8)));
always_check(!Algorithms::StartsWith(Arr, Ranges::Iota(0, 8), { }, Projection));
always_check(!Algorithms::StartsWith(Brr, Ranges::Iota(0, 8), { }, Projection));
always_check(!Algorithms::StartsWith(Crr, Ranges::Iota(0, 8), { }, Projection));
always_check(Algorithms::EndsWith(Arr, Ranges::Iota(8, 10)));
always_check(Algorithms::EndsWith(Brr, Ranges::Iota(8, 10)));
always_check(Algorithms::EndsWith(Crr, Ranges::Iota(8, 10)));
always_check(Algorithms::EndsWith(Arr, Ranges::Iota(0, 2), { }, Projection));
always_check(Algorithms::EndsWith(Brr, Ranges::Iota(0, 2), { }, Projection));
always_check(Algorithms::EndsWith(Crr, Ranges::Iota(0, 2), { }, Projection));
}
}
NAMESPACE_PRIVATE_END
void TestAlgorithms()
{
NAMESPACE_PRIVATE::TestBasic();
NAMESPACE_PRIVATE::TestSearch();
}
NAMESPACE_END(Testing)

View File

@ -2,3 +2,4 @@
#include "CoreTypes.h"
#include "Algorithms/Basic.h"
#include "Algorithms/Search.h"

View File

@ -115,11 +115,11 @@ NODISCARD FORCEINLINE constexpr ptrdiff Distance(I First, S Last)
}
}
/** @return The size of the range. */
/** @return The size of the range. The range will not be modified if it is a sized range. */
template <CRange R>
NODISCARD FORCEINLINE constexpr ptrdiff Distance(R&& Range)
{
if constexpr (CSizedRange<R>)
if constexpr (CSizedRange<R&>)
{
return static_cast<ptrdiff>(Ranges::Num(Range));
}

File diff suppressed because it is too large Load Diff

View File

@ -222,7 +222,8 @@ NAMESPACE_END(Ranges)
* A concept specifies a type is a range.
* A range is an iterator-sentinel pair that represents a sequence of elements.
* This concept does not require that iterator-sentinel pair can be fetched multiple times
* from the range object. again this means that const R may not be a range if R is a range,
* if the range does not satisfy the forward range, otherwise it is equality-preserving.
* Again, this means that const R may not be a range if R is a range,
* e.g. fetching the iterator-sentinel pair from the input range may require moving the iterator
* directly from the range object and thus the range object may be modified.
*/
@ -262,9 +263,8 @@ concept CBorrowedRange = CRange<R> && (CLValueReference<R> || bEnableBorrowedRan
/**
* A concept specifies a type is a sized range.
* Indicates the expression 'Ranges::Num(Range)' can get the size of the range at constant time
* without modifying the range object. Modifying the range usually occurs when the iterator of
* the range is an input iterator. Indirect calculation of the range by obtaining the iterator
* may cause the range to become invalid, that is, the iterator cannot be obtained again.
* without modifying the range object. A sized range may support fetched size before fetched iterator-sentinel pair
* if the range does not satisfy the forward range, otherwise it is equality-preserving.
*/
template <typename R>
concept CSizedRange = CRange<R>

View File

@ -94,18 +94,6 @@ FORCEINLINE constexpr TReferenceWrapper<T> Ref(TReferenceWrapper<T> InValue)
return Ref(InValue.Get());
}
template <typename T>
FORCEINLINE constexpr TReferenceWrapper<const T> Ref(const T& InValue)
{
return TReferenceWrapper<const T>(InValue);
}
template <typename T>
FORCEINLINE constexpr TReferenceWrapper<const T> Ref(TReferenceWrapper<T> InValue)
{
return Ref(InValue.Get());
}
NAMESPACE_PRIVATE_BEGIN
template <typename T> struct TIsTReferenceWrapperImpl : FFalse { };