diff --git a/Redcraft.Utility/Source/Private/Testing/Algorithms.cpp b/Redcraft.Utility/Source/Private/Testing/Algorithms.cpp new file mode 100644 index 0000000..c1f731a --- /dev/null +++ b/Redcraft.Utility/Source/Private/Testing/Algorithms.cpp @@ -0,0 +1,45 @@ +#include "Testing/Testing.h" + +#include "Algorithms/Algorithms.h" +#include "Containers/Array.h" +#include "Containers/List.h" +#include "Miscellaneous/AssertionMacros.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +NAMESPACE_BEGIN(Testing) + +NAMESPACE_PRIVATE_BEGIN + +void TestBasic() +{ + TArray Arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + auto Iter = Arr.Begin(); + + Algorithm::Advance(Iter, 5); + + always_check(*Iter == 5); + + always_check(Algorithm::Distance(Arr.Begin(), Iter) == 5); + + always_check(Algorithm::Distance(Arr) == 10); + + always_check(*Algorithm::Next(Iter, 2) == 7); + always_check(*Algorithm::Prev(Iter, 2) == 3); +} + +NAMESPACE_PRIVATE_END + +void TestAlgorithms() +{ + NAMESPACE_PRIVATE::TestBasic(); +} + +NAMESPACE_END(Testing) + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Algorithms/Algorithms.h b/Redcraft.Utility/Source/Public/Algorithms/Algorithms.h new file mode 100644 index 0000000..578db61 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Algorithms/Algorithms.h @@ -0,0 +1,4 @@ +#pragma once + +#include "CoreTypes.h" +#include "Algorithms/Basic.h" diff --git a/Redcraft.Utility/Source/Public/Algorithms/Basic.h b/Redcraft.Utility/Source/Public/Algorithms/Basic.h new file mode 100644 index 0000000..1316dde --- /dev/null +++ b/Redcraft.Utility/Source/Public/Algorithms/Basic.h @@ -0,0 +1,85 @@ +#pragma once + +#include "CoreTypes.h" +#include "TypeTraits/TypeTraits.h" +#include "Iterators/Utility.h" +#include "Iterators/BasicIterator.h" +#include "Ranges/Utility.h" +#include "Miscellaneous/AssertionMacros.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +NAMESPACE_BEGIN(Algorithm) + +/** Increments given iterator 'Iter' by 'N' elements. */ +template +FORCEINLINE constexpr void Advance(I& Iter, ptrdiff N) +{ + if constexpr (CRandomAccessIterator) + { + Iter += N; + } + + else if constexpr (CBidirectionalIterator) + { + for (; N > 0; --N) ++Iter; + for (; N < 0; ++N) --Iter; + } + + else + { + checkf(N >= 0, TEXT("The iterator must satisfy the CBidirectionalIterator in order to be decremented.")); + for (; N > 0; --N) ++Iter; + } +} + +/** @return The number of hops from 'First' to 'Last'. */ +template S> +NODISCARD FORCEINLINE constexpr ptrdiff Distance(I First, S Last) +{ + if constexpr (CSizedSentinelFor) + { + return Last - First; + } + else + { + ptrdiff Result = 0; + for (; First != Last; ++First) ++Result; + return Result; + } +} + +/** @return The size of the range. */ +template +NODISCARD FORCEINLINE constexpr ptrdiff Distance(R&& Range) +{ + if constexpr (CSizedRange) + { + return static_cast(Range::Num(Range)); + } + else return Algorithm::Distance(Range::Begin(Range), Range::End(Range)); +} + +/** @return The 'N'-th successor of iterator 'Iter'. */ +template +NODISCARD FORCEINLINE constexpr I Next(I Iter, ptrdiff N = 1) +{ + Algorithm::Advance(Iter, N); + return Iter; +} + +/** @return The 'N'-th predecessor of iterator 'Iter'. */ +template +NODISCARD FORCEINLINE constexpr I Prev(I Iter, ptrdiff N = 1) +{ + Algorithm::Advance(Iter, -N); + return Iter; +} + +NAMESPACE_END(Algorithm) + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Testing/Testing.h b/Redcraft.Utility/Source/Public/Testing/Testing.h index 823b6cf..96358a1 100644 --- a/Redcraft.Utility/Source/Public/Testing/Testing.h +++ b/Redcraft.Utility/Source/Public/Testing/Testing.h @@ -13,6 +13,7 @@ REDCRAFTUTILITY_API void TestTemplates(); REDCRAFTUTILITY_API void TestNumeric(); REDCRAFTUTILITY_API void TestIterator(); REDCRAFTUTILITY_API void TestRange(); +REDCRAFTUTILITY_API void TestAlgorithms(); REDCRAFTUTILITY_API void TestMemory(); REDCRAFTUTILITY_API void TestContainers(); REDCRAFTUTILITY_API void TestString();