#pragma once #ifndef __FILE_Detail_CP_Arithmetic_Hpp #define __FILE_Detail_CP_Arithmetic_Hpp #include "CHash.hpp" #pragma region TIsArithmetic namespace Internal { /** * Traits class which tests if a type is arithmetic. */ template struct TIsArithmeticTool { constexpr static bool Value = false; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template <> struct TIsArithmeticTool { constexpr static bool Value = true; }; template struct TIsArithmeticTool { constexpr static bool Value = TIsArithmeticTool::Value; }; template struct TIsArithmeticTool< volatile T> { constexpr static bool Value = TIsArithmeticTool::Value; }; template struct TIsArithmeticTool { constexpr static bool Value = TIsArithmeticTool::Value; }; } template constexpr bool TIsArithmetic = Internal::TIsArithmeticTool::Value; #pragma endregion #pragma region TIsSigned namespace Internal { /** * Traits class which tests if a type is a signed integral type. */ template struct TIsSignedTool { constexpr static bool Value = false; }; template <> struct TIsSignedTool { constexpr static bool Value = true; }; template <> struct TIsSignedTool { constexpr static bool Value = true; }; template <> struct TIsSignedTool { constexpr static bool Value = true; }; template <> struct TIsSignedTool { constexpr static bool Value = true; }; template struct TIsSignedTool { constexpr static bool Value = TIsSignedTool::Value; }; template struct TIsSignedTool< volatile T> { constexpr static bool Value = TIsSignedTool::Value; }; template struct TIsSignedTool { constexpr static bool Value = TIsSignedTool::Value; }; } template constexpr bool TIsSigned = Internal::TIsSignedTool::Value; #pragma endregion #pragma region TIsIntegral namespace Internal { /** * Traits class which tests if a type is integral. */ template struct TIsIntegralTool { constexpr static bool Value = false; }; template <> struct TIsIntegralTool< bool> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool< char> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool { constexpr static bool Value = true; }; template <> struct TIsIntegralTool { constexpr static bool Value = true; }; template <> struct TIsIntegralTool< char16_t> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool< char32_t> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool< wchar_t> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool< short> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool { constexpr static bool Value = true; }; template <> struct TIsIntegralTool< int> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool { constexpr static bool Value = true; }; template <> struct TIsIntegralTool< long> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool { constexpr static bool Value = true; }; template <> struct TIsIntegralTool< long long> { constexpr static bool Value = true; }; template <> struct TIsIntegralTool { constexpr static bool Value = true; }; template struct TIsIntegralTool { constexpr static bool Value = TIsIntegralTool::Value; }; template struct TIsIntegralTool< volatile T> { constexpr static bool Value = TIsIntegralTool::Value; }; template struct TIsIntegralTool { constexpr static bool Value = TIsIntegralTool::Value; }; } template constexpr bool TIsIntegral = Internal::TIsIntegralTool::Value; #pragma endregion #pragma region TIsFloatingPoint /////////////////////////////// // TIsFloatingPoint namespace Internal { /** * Traits class which tests if a type is floating point. */ template struct TIsFloatingPointTool { constexpr static bool Value = false; }; template <> struct TIsFloatingPointTool { constexpr static bool Value = true; }; template <> struct TIsFloatingPointTool { constexpr static bool Value = true; }; template <> struct TIsFloatingPointTool { constexpr static bool Value = true; }; template struct TIsFloatingPointTool { constexpr static bool Value = TIsFloatingPointTool::Value; }; template struct TIsFloatingPointTool< volatile T> { constexpr static bool Value = TIsFloatingPointTool::Value; }; template struct TIsFloatingPointTool { constexpr static bool Value = TIsFloatingPointTool::Value; }; } template constexpr bool TIsFloatingPoint = Internal::TIsFloatingPointTool::Value; // TIsFloatingPoint ////////////////////////////////// #pragma endregion #pragma region About Align /////////////////////// // About Align Toolkit #pragma region Align /** * Aligns a value to the nearest higher multiple of 'Alignment', which must be a power of two. * * @param Val The value to align. * @param Alignment The alignment value, must be a power of two. * * @return The value aligned up to the specified alignment. */ template FORCEINLINE constexpr T CAlign(T Val, uint64_t Alignment) { return (T)(((uint64_t)Val + Alignment - 1) & ~(Alignment - 1)); } /** * Aligns a value to the nearest higher multiple of 'Alignment', which must be a power of two. * * @param Val The value to align. * @param Alignment The alignment value, must be a power of two. * * @return The value aligned up to the specified alignment. */ template FORCEINLINE T Align(T Val, uint64_t Alignment) { return (T)(((uint64_t)Val + Alignment - 1) & ~(Alignment - 1)); } #pragma endregion #pragma region AlignDown /** * Aligns a value to the nearest lower multiple of 'Alignment', which must be a power of two. * * @param Val The value to align. * @param Alignment The alignment value, must be a power of two. * * @return The value aligned down to the specified alignment. */ template FORCEINLINE constexpr T CAlignDown(T Val, uint64_t Alignment) { return (T)(((uint64_t)Val) & ~(Alignment - 1)); } /** * Aligns a value to the nearest lower multiple of 'Alignment', which must be a power of two. * * @param Val The value to align. * @param Alignment The alignment value, must be a power of two. * * @return The value aligned down to the specified alignment. */ template FORCEINLINE T AlignDown(T Val, uint64_t Alignment) { return (T)(((uint64_t)Val) & ~(Alignment - 1)); } #pragma endregion #pragma region IsAligned /** * Checks if a pointer is aligned to the specified alignment. * * @param Val The value to align. * @param Alignment The alignment value, must be a power of two. * * @return true if the pointer is aligned to the specified alignment, false otherwise. */ template FORCEINLINE constexpr bool CIsAligned(T Val, uint64_t Alignment) { return !((uint64_t)Val & (Alignment - 1)); } /** * Checks if a pointer is aligned to the specified alignment. * * @param Val The value to align. * @param Alignment The alignment value, must be a power of two. * * @return true if the pointer is aligned to the specified alignment, false otherwise. */ template FORCEINLINE bool IsAligned(T Val, uint64_t Alignment) { return !((uint64_t)Val & (Alignment - 1)); } #pragma endregion #pragma region AlignArbitrary /** * Aligns a value to the nearest higher multiple of 'Alignment'. * * @param Val The value to align. * @param Alignment The alignment value, can be any arbitrary value. * * @return The value aligned up to the specified alignment. */ template FORCEINLINE constexpr T CAlignArbitrary(T Val, uint64_t Alignment) { return (T)((((uint64_t)Val + Alignment - 1) / Alignment) * Alignment); } /** * Aligns a value to the nearest higher multiple of 'Alignment'. * * @param Val The value to align. * @param Alignment The alignment value, can be any arbitrary value. * * @return The value aligned up to the specified alignment. */ template FORCEINLINE T AlignArbitrary(T Val, uint64_t Alignment) { return (T)((((uint64_t)Val + Alignment - 1) / Alignment) * Alignment); } #pragma endregion // Align Toolkit //////////////////////// #pragma endregion #pragma region About Functors #pragma region Less /////////////////// // Less /** * Binary predicate class for sorting elements in order. Assumes < operator is defined for the template type. * Forward declaration exists in ContainersFwd.h * * See: http://en.cppreference.com/w/cpp/utility/functional/less */ struct TLess { template FORCEINLINE bool operator()(const T& A, const U& B) const { return A < B; } }; // Less //////////////////// #pragma endregion #pragma region Greater //////////////////////// // Greater /** * Binary predicate class for sorting elements in reverse order. Assumes < operator is defined for the template type. * * See: http://en.cppreference.com/w/cpp/utility/functional/greater */ struct TGreater { template FORCEINLINE bool operator()(const T& A, const U& B) const { return B < A; } }; // Greater ////////////////////////// #pragma endregion #pragma region EqualTo ///////////////////////////// // EqualTo /** * Binary predicate class for performing equality comparisons. * * Uses operator== when available. * * See: https://en.cppreference.com/w/cpp/utility/functional/equal_to */ struct TEqualTo { template constexpr auto operator()(const T& Lhs, const U& Rhs) const -> decltype(Lhs == Rhs) { return Lhs == Rhs; } }; // EqualTo ///////////////////////////// #pragma endregion #pragma region IdentityFunctor ///////////////////////////// // IdentityFunctor /** * A functor which returns whatever is passed to it. Mainly used for generic composition. */ struct TIdentityFunctor { template FORCEINLINE T&& operator()(T&& Val) const { return (T&&)Val; } }; // IdentityFunctor /////////////////////////////// #pragma endregion #pragma endregion #pragma region IntegralConstant /////////////////////////////// // IntegralConstant /** * Defines a value metafunction of the given Value. */ template struct TIntegralConstant { static constexpr T Value = Val; constexpr operator T() const { return Value; } }; // IntegralConstant /////////////////////////////// #pragma endregion #endif // !__FILE_Detail_CP_Arithmetic_Hpp