-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrand.cpp
128 lines (110 loc) · 3.15 KB
/
rand.cpp
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//
// -----------------------------------------------------------------------------
// (c) Bob Jenkins, March 1996, Public Domain
// You may use this code in any way you wish, and it is free. No warrantee.
// -----------------------------------------------------------------------------
//
#include "rand.h"
// external results
ub4 randrsl[256];
ub4 randcnt;
// internal state
static ub4 mm[256];
static ub4 aa=0, bb=0, cc=0;
void isaac()
{
register ub4 i,x,y;
cc = cc + 1; // cc just gets incremented once per 256 results
bb = bb + cc; // then combined with bb
for (i=0; i<256; ++i) {
x = mm[i];
switch (i%4) {
case 0: aa = aa^(aa<<13); break;
case 1: aa = aa^(aa>>6); break;
case 2: aa = aa^(aa<<2); break;
case 3: aa = aa^(aa>>16); break;
}
aa = mm[(i+128)%256] + aa;
mm[i] = y = mm[(x>>2)%256] + aa + bb;
randrsl[i] = bb = mm[(y>>10)%256] + x;
// Note that bits 2..9 are chosen from x but 10..17 are chosen
// from y. The only important thing here is that 2..9 and 10..17
// don't overlap. 2..9 and 10..17 were then chosen for speed in
// the optimized version (rand.c)
// See http://burtleburtle.net/bob/rand/isaac.html
// for further explanations and analysis.
}
}
// if (flag!=0), then use the contents of randrsl[] to initialize mm[].
#define mix(a,b,c,d,e,f,g,h) \
{ \
a^=b<<11; d+=a; b+=c; \
b^=c>>2; e+=b; c+=d; \
c^=d<<8; f+=c; d+=e; \
d^=e>>16; g+=d; e+=f; \
e^=f<<10; h+=e; f+=g; \
f^=g>>4; a+=f; g+=h; \
g^=h<<8; b+=g; h+=a; \
h^=a>>9; c+=h; a+=b; \
}
void randinit(int flag)
{
int i;
ub4 a,b,c,d,e,f,g,h;
aa=bb=cc=0;
a=b=c=d=e=f=g=h=0x9e3779b9; // the golden ratio
// scramble it
for (i=0; i<4; ++i) {
mix(a,b,c,d,e,f,g,h);
}
for (i=0; i<256; i+=8) { // fill in mm[] with messy stuff
if (flag) { // use all the information in the seed
a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7];
}
mix(a,b,c,d,e,f,g,h);
mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
}
if (flag) { // do a second pass to make all of the seed affect all of mm
for (i=0; i<256; i+=8) {
a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7];
mix(a,b,c,d,e,f,g,h);
mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
}
}
isaac(); // fill in the first set of results */
randcnt = 256; // prepare to use the first set of results */
}
// Get a random 64-bit number
ull GetRand64()
{
static int i=256, cnt=0;
if (i>254) {
randinit(cnt++);
isaac();
i=0;
}
const ull a = (ull) randrsl[i++] << 32ULL;
const ull b = (ull) randrsl[i++];
return a | b;
}
// for testing uncomment this and you shall see some random stuff on screen
/*
int main()
{
ub4 i,j;
aa=bb=cc=(ub4)0;
for (i=0; i<256; ++i) mm[i]=randrsl[i]=(ub4)0;
randinit(1);
for (i=0; i<2; ++i) {
isaac();
for (j=0; j<256; ++j) {
printf("%.8lx",randrsl[j]);
if ((j&7)==7) printf("\n");
}
}
}
*/