/
asg.cc
90 lines (77 loc) · 2.18 KB
/
asg.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* This class implements a 160-bit pseudo-random number generator.
* This generator combines David Jone's JKISS generator with an alternating
* step generator utilizing a 32-bit Galois m_lfsr as a gate.
* It passes all tests in TestU01 BigCrush.
* This software is derived from LibRNG, a public domain pseudo-random number
* library. (http://www.github.com/bhickey/librng)
*/
#include "AppHdr.h"
#include "asg.h"
static AsgKISS asg_rng[2];
AsgKISS &AsgKISS::generator(int which)
{
ASSERT(which >= 0);
ASSERT((size_t) which < ARRAYSZ(asg_rng));
return asg_rng[which];
}
uint32_t
AsgKISS::get_uint32()
{
m_lcg = (314527869 * m_lcg + 1234567);
m_lfsr = (m_lfsr >> 1) ^ (-(int32_t)(m_lfsr & 1U) & 0xD0000001U);
if (m_lfsr & 1)
{
m_xorshift ^= m_xorshift << 5;
m_xorshift ^= m_xorshift >> 7;
m_xorshift ^= m_xorshift << 22;
}
else
{
uint64_t t = 4294584393ULL * m_mwcm + m_mwcc;
m_mwcc = t >> 32;
m_mwcm = t;
}
return m_lcg + m_mwcm + m_xorshift;
}
AsgKISS::AsgKISS()
{
m_lcg = 12345678;
m_mwcm = 43219876;
m_mwcc = 6543217;
m_xorshift = 987654321;
m_lfsr = 76543210;
}
AsgKISS::AsgKISS(uint32_t init_key[], int key_length)
{
m_lcg = (key_length > 0 ? init_key[0] : 12345678);
m_mwcm = (key_length > 1 ? init_key[1] : 43219876);
m_mwcc = (key_length > 2 ? init_key[2] : 6543217);
m_xorshift = (key_length > 3 ? init_key[3] : 987654321);
m_lfsr = (key_length > 4 ? init_key[4] : 7654321);
// m_lfsr must not be set to zero.
if (!m_lfsr)
{
m_lfsr = 7654321;
while (!(m_lfsr = get_uint32()));
}
}
uint32_t get_uint32(int generator)
{
return AsgKISS::generator(generator).get_uint32();
}
void seed_asg(uint32_t seed_array[], int seed_len)
{
{
const AsgKISS seeded(seed_array, seed_len);
asg_rng[0] = seeded;
}
// Use the just seeded RNG to initialize the rest.
for (size_t i = 1; i < ARRAYSZ(asg_rng); ++i)
{
uint32_t key[5];
for (size_t j = 0; j < ARRAYSZ(key); ++j)
key[j] = asg_rng[0].get_uint32();
const AsgKISS seeded(key, ARRAYSZ(key));
asg_rng[i] = seeded;
}
}