Simplify DqnRndPCG

This commit is contained in:
Doyle T 2018-06-11 19:16:54 +10:00
parent 0bf1b6d3ff
commit 5dee3d9f89
2 changed files with 21 additions and 42 deletions

View File

@ -709,7 +709,7 @@ void DqnRnd_Test()
{ {
LOG_HEADER(); LOG_HEADER();
DqnRndPCG pcg; pcg.Init(); auto pcg = DqnRndPCG();
for (i32 i = 0; i < 1000000; i++) for (i32 i = 0; i < 1000000; i++)
{ {
i32 min = -100; i32 min = -100;
@ -1932,7 +1932,7 @@ FILE_SCOPE void DqnJobQueue_Test()
void DqnQuickSort_Test() void DqnQuickSort_Test()
{ {
LOG_HEADER(); LOG_HEADER();
DqnRndPCG state; state.Init(); auto state = DqnRndPCG();
if (1) if (1)
{ {
DqnMemStack stack = {}; DqnMemStack stack = {};
@ -2247,7 +2247,7 @@ void Dqn_BSearch_Test()
void DqnMemSet_Test() void DqnMemSet_Test()
{ {
LOG_HEADER(); LOG_HEADER();
DqnRndPCG rnd = DqnRndPCG_(); auto rnd = DqnRndPCG();
const int NUM_TIMINGS = 5; const int NUM_TIMINGS = 5;
f64 timings[2][NUM_TIMINGS] = {}; f64 timings[2][NUM_TIMINGS] = {};

57
dqn.h
View File

@ -766,23 +766,18 @@ DQN_FILE_SCOPE i32 Dqn_I32ToWStr (i32 value, wchar_t *buf, i32
// #DqnRnd API // #DqnRnd API
// ================================================================================================= // =================================================================================================
// NOTE: Uses PCG (Permuted Congruential Generator) struct DqnRndPCG // PCG (Permuted Congruential Generator)
struct DqnRndPCG
{ {
u64 state[2]; u64 state[2];
void Init (); // Uses rdstc to create a seed DqnRndPCG();
void InitWithSeed(u32 seed); DqnRndPCG(u32 seed);
u32 Next (); // return: A random number N between [0, 0xFFFFFFFF] u32 Next (); // return: A random number N between [0, 0xFFFFFFFF]
f32 Nextf(); // return: A random float N between [0.0, 1.0f] f32 Nextf(); // return: A random float N between [0.0, 1.0f]
i32 Range(i32 min, i32 max); // return: A random integer N between [min, max] i32 Range(i32 min, i32 max); // return: A random integer N between [min, max]
}; };
DQN_FILE_SCOPE DqnRndPCG DqnRndPCG_(); // Uses rdtsc to create a seed
DQN_FILE_SCOPE DqnRndPCG DqnRndPCG_(u32 seed);
// #Dqn_* API // #Dqn_* API
// ================================================================================================= // =================================================================================================
// return: The number of splits in the array. If array is null this returns the required size of the array. // return: The number of splits in the array. If array is null this returns the required size of the array.
@ -835,8 +830,7 @@ DQN_FILE_SCOPE void Dqn_QuickSort(T *array, i64 size,
} }
#endif #endif
DqnRndPCG state; state.Init(); auto state = DqnRndPCG();
auto lastIndex = size - 1; auto lastIndex = size - 1;
auto pivotIndex = (i64)state.Range(0, (i32)lastIndex); auto pivotIndex = (i64)state.Range(0, (i32)lastIndex);
auto partitionIndex = 0; auto partitionIndex = 0;
@ -907,8 +901,7 @@ DQN_FILE_SCOPE void Dqn_QuickSort(T *array, i64 size)
} }
#endif #endif
DqnRndPCG state; state.Init(); auto state = DqnRndPCG();
auto lastIndex = size - 1; auto lastIndex = size - 1;
auto pivotIndex = (i64)state.Range(0, (i32)lastIndex); // TODO(doyle): RNG 64bit auto pivotIndex = (i64)state.Range(0, (i32)lastIndex); // TODO(doyle): RNG 64bit
auto partitionIndex = 0; auto partitionIndex = 0;
@ -5925,23 +5918,23 @@ DQN_FILE_SCOPE i32 Dqn_I32ToWstr(i32 value, wchar_t *buf, i32 bufSize)
// < 1.0f. Contributed by Jonatan Hedborg // < 1.0f. Contributed by Jonatan Hedborg
// NOTE: This is to abide to strict aliasing rules. // NOTE: This is to abide to strict aliasing rules.
union DqnRndInternal_U32F32 union DqnRnd__U32F32
{ {
u32 unsigned32; u32 unsigned32;
f32 float32; f32 float32;
}; };
FILE_SCOPE f32 DqnRndInternal_F32NormalizedFromU32(u32 value) FILE_SCOPE f32 DqnRnd__F32NormalizedFromU32(u32 value)
{ {
u32 exponent = 127; u32 exponent = 127;
u32 mantissa = value >> 9; u32 mantissa = value >> 9;
union DqnRndInternal_U32F32 uf; union DqnRnd__U32F32 uf;
uf.unsigned32 = (exponent << 23 | mantissa); uf.unsigned32 = (exponent << 23 | mantissa);
return uf.float32 - 1.0f; return uf.float32 - 1.0f;
} }
FILE_SCOPE u64 DqnRndInternal_Murmur3Avalanche64(u64 h) FILE_SCOPE u64 DqnRnd__Murmur3Avalanche64(u64 h)
{ {
h ^= h >> 33; h ^= h >> 33;
h *= 0xff51afd7ed558ccd; h *= 0xff51afd7ed558ccd;
@ -5955,7 +5948,7 @@ FILE_SCOPE u64 DqnRndInternal_Murmur3Avalanche64(u64 h)
#include <x86intrin.h> // __rdtsc #include <x86intrin.h> // __rdtsc
#endif #endif
FILE_SCOPE u32 DqnRndInternal_MakeSeed() FILE_SCOPE u32 DqnRnd__MakeSeed()
{ {
#if defined(DQN_WIN32_PLATFORM) || defined(DQN_UNIX_PLATFORM) #if defined(DQN_WIN32_PLATFORM) || defined(DQN_UNIX_PLATFORM)
i64 numClockCycles = __rdtsc(); i64 numClockCycles = __rdtsc();
@ -5969,37 +5962,23 @@ FILE_SCOPE u32 DqnRndInternal_MakeSeed()
#endif #endif
} }
DQN_FILE_SCOPE DqnRndPCG DqnRndPCG_() DqnRndPCG::DqnRndPCG()
{ {
DqnRndPCG result; u32 seed = DqnRnd__MakeSeed();
result.Init(); *this = DqnRndPCG(seed);
return result;
} }
DQN_FILE_SCOPE DqnRndPCG DqnRndPCG_(u32 seed) DqnRndPCG::DqnRndPCG(u32 seed)
{ {
DqnRndPCG result; u64 value = (((u64)seed) << 1ULL) | 1ULL;
result.InitWithSeed(seed); value = DqnRnd__Murmur3Avalanche64(value);
return result;
}
void DqnRndPCG::InitWithSeed(u32 seed)
{
u64 value = (((u64)seed) << 1ULL) | 1ULL;
value = DqnRndInternal_Murmur3Avalanche64(value);
this->state[0] = 0U; this->state[0] = 0U;
this->state[1] = (value << 1ULL) | 1ULL; this->state[1] = (value << 1ULL) | 1ULL;
this->Next(); this->Next();
this->state[0] += DqnRndInternal_Murmur3Avalanche64(value); this->state[0] += DqnRnd__Murmur3Avalanche64(value);
this->Next(); this->Next();
} }
void DqnRndPCG::Init()
{
u32 seed = DqnRndInternal_MakeSeed();
this->InitWithSeed(seed);
}
u32 DqnRndPCG::Next() u32 DqnRndPCG::Next()
{ {
u64 oldstate = this->state[0]; u64 oldstate = this->state[0];
@ -6011,7 +5990,7 @@ u32 DqnRndPCG::Next()
f32 DqnRndPCG::Nextf() f32 DqnRndPCG::Nextf()
{ {
f32 result = DqnRndInternal_F32NormalizedFromU32(this->Next()); f32 result = DqnRnd__F32NormalizedFromU32(this->Next());
return result; return result;
} }