diff --git a/dqn.h b/dqn.h index 4016428..bb3df59 100644 --- a/dqn.h +++ b/dqn.h @@ -539,7 +539,8 @@ bool DqnArray::Free() template bool DqnArray::Resize(i64 newMax) { - if (!this->data) return false; + if (!this->data) return false; + if (!this->memAPI.callback) return false; i64 oldSize = this->max * sizeof(T); i64 newSize = newMax * sizeof(T); @@ -1468,22 +1469,18 @@ DQN_FILE_SCOPE i32 Dqn_I32ToWStr(i32 value, wchar_t *buf, i32 bufSize); // #DqnRnd Public API - Random Number Generator //////////////////////////////////////////////////////////////////////////////// // PCG (Permuted Congruential Generator) Random Number Generator -typedef struct DqnRandPCGState +class DqnRndPCG { +public: u64 state[2]; -} DqnRandPCGState; -// pcg: Pass in a pointer to a zero-cleared DqnRandPCGState -DQN_FILE_SCOPE void DqnRnd_PCGInitWithSeed(DqnRandPCGState *pcg, u32 seed); -// Uses __rdtsc() to create a seed. TODO(doyle): This requires the platform layer. -DQN_FILE_SCOPE void DqnRnd_PCGInit(DqnRandPCGState *pcg); + void Init (); // Uses rdstc to create a seed + void InitWithSeed(u32 seed); -// return: A random number N between [0, 0xFFFFFFFF] -DQN_FILE_SCOPE u32 DqnRnd_PCGNext (DqnRandPCGState *pcg); -// return: A random float N between [0.0, 1.0f] -DQN_FILE_SCOPE f32 DqnRnd_PCGNextf(DqnRandPCGState *pcg); -// return: A random integer N between [min, max] -DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max); + u32 Next (); // return: A random number N between [0, 0xFFFFFFFF] + 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] +}; //////////////////////////////////////////////////////////////////////////////// // #Dqn_* Public API @@ -1525,11 +1522,10 @@ DQN_FILE_SCOPE void Dqn_QuickSort(T *const array, const i32 size, } #endif - DqnRandPCGState state = {}; - DqnRnd_PCGInit(&state); + DqnRndPCG state; state.Init(); i32 lastIndex = size - 1; - i32 pivotIndex = DqnRnd_PCGRange(&state, 0, lastIndex); + i32 pivotIndex = state.Range(0, lastIndex); i32 partitionIndex = 0; i32 startIndex = 0; @@ -5169,7 +5165,7 @@ union DqnRndInternal_U32F32 f32 float32; }; -FILE_SCOPE f32 DqnRnd_F32NormalizedFromU32Internal(u32 value) +FILE_SCOPE f32 DqnRndInternal_F32NormalizedFromU32(u32 value) { u32 exponent = 127; u32 mantissa = value >> 9; @@ -5179,7 +5175,7 @@ FILE_SCOPE f32 DqnRnd_F32NormalizedFromU32Internal(u32 value) return uf.float32 - 1.0f; } -FILE_SCOPE u64 DqnRnd_Murmur3Avalanche64Internal(u64 h) +FILE_SCOPE u64 DqnRndInternal_Murmur3Avalanche64(u64 h) { h ^= h >> 33; h *= 0xff51afd7ed558ccd; @@ -5193,7 +5189,7 @@ FILE_SCOPE u64 DqnRnd_Murmur3Avalanche64Internal(u64 h) #include // __rdtsc #endif -FILE_SCOPE u32 DqnRnd_MakeSeedInternal() +FILE_SCOPE u32 DqnRndInternal_MakeSeed() { #if defined(DQN_WIN32_PLATFORM) || defined(DQN_UNIX_PLATFORM) i64 numClockCycles = __rdtsc(); @@ -5207,43 +5203,46 @@ FILE_SCOPE u32 DqnRnd_MakeSeedInternal() #endif } -DQN_FILE_SCOPE void DqnRnd_PCGInitWithSeed(DqnRandPCGState *pcg, u32 seed) +void DqnRndPCG::InitWithSeed(u32 seed) { u64 value = (((u64)seed) << 1ULL) | 1ULL; - value = DqnRnd_Murmur3Avalanche64Internal(value); - pcg->state[0] = 0U; - pcg->state[1] = (value << 1ULL) | 1ULL; - DqnRnd_PCGNext(pcg); - pcg->state[0] += DqnRnd_Murmur3Avalanche64Internal(value); - DqnRnd_PCGNext(pcg); + value = DqnRndInternal_Murmur3Avalanche64(value); + this->state[0] = 0U; + this->state[1] = (value << 1ULL) | 1ULL; + this->Next(); + this->state[0] += DqnRndInternal_Murmur3Avalanche64(value); + this->Next(); } -DQN_FILE_SCOPE void DqnRnd_PCGInit(DqnRandPCGState *pcg) +void DqnRndPCG::Init() { - u32 seed = DqnRnd_MakeSeedInternal(); - DqnRnd_PCGInitWithSeed(pcg, seed); + u32 seed = DqnRndInternal_MakeSeed(); + this->InitWithSeed(seed); } -DQN_FILE_SCOPE u32 DqnRnd_PCGNext(DqnRandPCGState *pcg) +u32 DqnRndPCG::Next() { - u64 oldstate = pcg->state[0]; - pcg->state[0] = oldstate * 0x5851f42d4c957f2dULL + pcg->state[1]; + u64 oldstate = this->state[0]; + this->state[0] = oldstate * 0x5851f42d4c957f2dULL + this->state[1]; u32 xorshifted = (u32)(((oldstate >> 18ULL) ^ oldstate) >> 27ULL); u32 rot = (u32)(oldstate >> 59ULL); return (xorshifted >> rot) | (xorshifted << ((-(i32)rot) & 31)); } -DQN_FILE_SCOPE f32 DqnRnd_PCGNextf(DqnRandPCGState *pcg) +f32 DqnRndPCG::Nextf() { - return DqnRnd_F32NormalizedFromU32Internal(DqnRnd_PCGNext(pcg)); + f32 result = DqnRndInternal_F32NormalizedFromU32(this->Next()); + return result; } -DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max) +i32 DqnRndPCG::Range(i32 min, i32 max) { i32 const range = (max - min) + 1; if (range <= 0) return min; - i32 const value = (i32)(DqnRnd_PCGNextf(pcg) * range); - return min + value; + + i32 const value = (i32)(this->Nextf() * range); + i32 result = min + value; + return result; } //////////////////////////////////////////////////////////////////////////////// diff --git a/dqn_unit_test.cpp b/dqn_unit_test.cpp index 72cdbc0..7510a41 100644 --- a/dqn_unit_test.cpp +++ b/dqn_unit_test.cpp @@ -641,18 +641,19 @@ void DqnTimer_Test() void DqnRnd_Test() { LogHeader("Random Number Generator Test"); - DqnRandPCGState pcg; - DqnRnd_PCGInit(&pcg); + + DqnRndPCG pcg; pcg.Init(); for (i32 i = 0; i < 1000000; i++) { i32 min = -100; i32 max = 1000000000; - i32 result = DqnRnd_PCGRange(&pcg, min, max); + i32 result = pcg.Range(min, max); DQN_ASSERT(result >= min && result <= max); - f32 randF32 = DqnRnd_PCGNextf(&pcg); + f32 randF32 = pcg.Nextf(); DQN_ASSERT(randF32 >= 0.0f && randF32 <= 1.0f); } + printf("RandomTest(): RndPCG: Completed successfully\n"); printf("RandomTest(): Completed successfully\n"); } @@ -1992,8 +1993,7 @@ FILE_SCOPE void DqnJobQueue_Test() void DqnQuickSort_Test() { LogHeader("DqnSort vs std::Sort"); - DqnRandPCGState state = {}; - DqnRnd_PCGInit(&state); + DqnRndPCG state; state.Init(); if (1) { DqnMemStack stack = {}; @@ -2017,7 +2017,7 @@ void DqnQuickSort_Test() // Populate with random numbers for (u32 i = 0; i < numInts; i++) { - dqnCPPArray[i] = DqnRnd_PCGNext(&state); + dqnCPPArray[i] = state.Next(); stdArray[i] = dqnCPPArray[i]; }