mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-21 10:04:18 +00:00
68 lines
1.2 KiB
C++
68 lines
1.2 KiB
C++
|
#include "prng.h"
|
||
|
|
||
|
#include <base/system.h>
|
||
|
|
||
|
// From https://www.mscs.dal.ca/~selinger/random/, 2020-05-25.
|
||
|
|
||
|
#define NAME "glibc-rand-emu"
|
||
|
|
||
|
CPrng::CPrng() :
|
||
|
m_Seeded(false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
const char *CPrng::Description() const
|
||
|
{
|
||
|
if(!m_Seeded)
|
||
|
{
|
||
|
return NAME ":unseeded";
|
||
|
}
|
||
|
return m_aDescription;
|
||
|
}
|
||
|
|
||
|
// Handles indices from -32 to +infty correctly.
|
||
|
#define INDEX(i) (((i) + 32) % 32)
|
||
|
#define r(i) (m_aState[INDEX(i)])
|
||
|
void CPrng::Seed(unsigned int Seed)
|
||
|
{
|
||
|
// The PRNG behaves badly when seeded with 0.
|
||
|
if(Seed == 0)
|
||
|
{
|
||
|
Seed = 1;
|
||
|
}
|
||
|
|
||
|
m_Seeded = true;
|
||
|
str_format(m_aDescription, sizeof(m_aDescription), "%s:%08x", NAME, Seed);
|
||
|
|
||
|
int s = Seed;
|
||
|
|
||
|
r(0) = s;
|
||
|
r(1) = (16807 * (int64)(int)r(0)) % 2147483647;
|
||
|
for(int i = 1; i <= 30; i++)
|
||
|
{
|
||
|
r(i) = (16807 * (int64)r(i - 1)) % 2147483647;
|
||
|
}
|
||
|
r(31) = r(0);
|
||
|
r(32) = r(1);
|
||
|
r(33) = r(2);
|
||
|
|
||
|
m_Index = INDEX(34);
|
||
|
for(int i = 34; i <= 343; i++)
|
||
|
{
|
||
|
RandomInt();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int CPrng::RandomInt()
|
||
|
{
|
||
|
dbg_assert(m_Seeded, "prng needs to be seeded before it can generate random numbers");
|
||
|
int i = m_Index;
|
||
|
|
||
|
r(i) = r(i - 3) + r(i - 31); // modulo 4294967296 is implicit.
|
||
|
|
||
|
int Result = r(i) >> 1;
|
||
|
m_Index = INDEX(i + 1);
|
||
|
return Result;
|
||
|
}
|