feat(numeric): add basic random number generator function
This commit is contained in:
parent
2d06667c40
commit
9d901df68a
51
Redcraft.Utility/Source/Private/Numeric/Random.cpp
Normal file
51
Redcraft.Utility/Source/Private/Numeric/Random.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "Numeric/Random.h"
|
||||
|
||||
#include "Templates/Atomic.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
NAMESPACE_BEGIN(Math)
|
||||
|
||||
NAMESPACE_UNNAMED_BEGIN
|
||||
|
||||
TAtomic<uint32> RandState = 586103306;
|
||||
|
||||
NAMESPACE_UNNAMED_END
|
||||
|
||||
uint32 Seed(uint32 InSeed)
|
||||
{
|
||||
uint32 OldSeed = RandState.Load(EMemoryOrder::Relaxed);
|
||||
|
||||
if (InSeed != 0) RandState.Store(InSeed, EMemoryOrder::Relaxed);
|
||||
|
||||
return OldSeed;
|
||||
}
|
||||
|
||||
uint32 Rand()
|
||||
{
|
||||
uint32 Result;
|
||||
|
||||
RandState.FetchFn(
|
||||
[&Result](uint32 Value)
|
||||
{
|
||||
Result = Value;
|
||||
|
||||
Result ^= Result << 13;
|
||||
Result ^= Result >> 17;
|
||||
Result ^= Result << 5;
|
||||
|
||||
return Result;
|
||||
},
|
||||
EMemoryOrder::Relaxed
|
||||
);
|
||||
|
||||
return Result % 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
NAMESPACE_END(Math)
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -6,3 +6,4 @@
|
||||
#include "Numeric/Numbers.h"
|
||||
#include "Numeric/Bit.h"
|
||||
#include "Numeric/Math.h"
|
||||
#include "Numeric/Random.h"
|
||||
|
88
Redcraft.Utility/Source/Public/Numeric/Random.h
Normal file
88
Redcraft.Utility/Source/Public/Numeric/Random.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Numeric/Bit.h"
|
||||
#include "Numeric/Math.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
NAMESPACE_BEGIN(Math)
|
||||
|
||||
/** Seeds the random number generator. Return the previous seed. */
|
||||
NODISCARD REDCRAFTUTILITY_API uint32 Seed(uint32 InSeed = 0);
|
||||
|
||||
/** @return The generated random number within the range of [0, 0x7FFFFFFF). */
|
||||
NODISCARD REDCRAFTUTILITY_API uint32 Rand();
|
||||
|
||||
/** @return The generated random number within the range of [0, A). */
|
||||
template <CIntegral T>
|
||||
NODISCARD FORCEINLINE T Rand(T A)
|
||||
{
|
||||
constexpr uint32 RandStateNum = 0x7FFFFFFF;
|
||||
|
||||
if (A <= 0) return 0;
|
||||
|
||||
if (A <= RandStateNum) return Rand() % A;
|
||||
|
||||
constexpr uint32 BlockSize = Math::BitFloor(RandStateNum);
|
||||
constexpr uint BlockWidth = Math::CountRightZero(BlockSize);
|
||||
|
||||
const T BlockNum = Math::DivAndCeil(A, BlockSize);
|
||||
|
||||
T Result = 0;
|
||||
|
||||
for (T I = 0; I < BlockNum; ++I)
|
||||
{
|
||||
Result ^= Rand();
|
||||
|
||||
Result <<= BlockWidth;
|
||||
}
|
||||
|
||||
return Math::Abs(Result) % A;
|
||||
}
|
||||
|
||||
/** @return The generated random number within the range of [0, A). */
|
||||
template <CFloatingPoint T>
|
||||
NODISCARD FORCEINLINE T Rand(T A)
|
||||
{
|
||||
constexpr uint32 RandStateNum = 0x7FFFFFFF;
|
||||
|
||||
if (Math::IsNegative(A)) return TNumericLimits<T>::QuietNaN();
|
||||
|
||||
constexpr size_t BlockNum = Math::DivAndCeil(sizeof(T), 4);
|
||||
|
||||
T Multiplier = A;
|
||||
|
||||
Multiplier /= BlockNum;
|
||||
Multiplier /= RandStateNum;
|
||||
|
||||
T Result = 0;
|
||||
|
||||
for (size_t I = 0; I < BlockNum; ++I)
|
||||
{
|
||||
Result += Rand() * Multiplier;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/** @return The generated random number within the range of [A, B). */
|
||||
template <CArithmetic T, CArithmetic U> requires (CCommonType<T, U>)
|
||||
NODISCARD FORCEINLINE auto RandWithin(T A, U B)
|
||||
{
|
||||
using FCommonT = TCommonType<T, U>;
|
||||
|
||||
if (A == B) return static_cast<FCommonT>(A);
|
||||
|
||||
if (A > B) return Math::RandWithin(B, A);
|
||||
|
||||
return static_cast<FCommonT>(A + Math::Rand(B - A));
|
||||
}
|
||||
|
||||
NAMESPACE_END(Math)
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
Loading…
Reference in New Issue
Block a user