]>
jfr.im git - irc/quakenet/newserv.git/blob - lib/prng.c
2 ------------------------------------------------------------------------------
3 rand.c: By Bob Jenkins. My random number generator, ISAAC. Public Domain
5 960327: Creation (addition of randinit, really)
6 970719: use context, not global variables, for internal state
7 980324: make a portable version
8 010626: Note this is public domain
9 ------------------------------------------------------------------------------
16 #define ind(mm,x) ((mm)[(x>>2)&(RANDSIZ-1)])
17 #define rngstep(mix,a,b,mm,m,m2,r,x) \
20 a = ((a^(mix)) + *(m2++)) & 0xffffffff; \
21 *(m++) = y = (ind(mm,x) + a + b) & 0xffffffff; \
22 *(r++) = b = (ind(mm,y>>RANDSIZL) + x) & 0xffffffff; \
28 register ub4 a
,b
,x
,y
,*m
,*mm
,*m2
,*r
,*mend
;
29 mm
=ctx
->randmem
; r
=ctx
->randrsl
;
30 a
= ctx
->randa
; b
= (ctx
->randb
+ (++ctx
->randc
)) & 0xffffffff;
31 for (m
= mm
, mend
= m2
= m
+(RANDSIZ
/2); m
<mend
; )
33 rngstep( a
<<13, a
, b
, mm
, m
, m2
, r
, x
);
34 rngstep( a
>>6 , a
, b
, mm
, m
, m2
, r
, x
);
35 rngstep( a
<<2 , a
, b
, mm
, m
, m2
, r
, x
);
36 rngstep( a
>>16, a
, b
, mm
, m
, m2
, r
, x
);
38 for (m2
= mm
; m2
<mend
; )
40 rngstep( a
<<13, a
, b
, mm
, m
, m2
, r
, x
);
41 rngstep( a
>>6 , a
, b
, mm
, m
, m2
, r
, x
);
42 rngstep( a
<<2 , a
, b
, mm
, m
, m2
, r
, x
);
43 rngstep( a
>>16, a
, b
, mm
, m
, m2
, r
, x
);
45 ctx
->randb
= b
; ctx
->randa
= a
;
49 #define mix(a,b,c,d,e,f,g,h) \
51 a^=b<<11; d+=a; b+=c; \
52 b^=c>>2; e+=b; c+=d; \
53 c^=d<<8; f+=c; d+=e; \
54 d^=e>>16; g+=d; e+=f; \
55 e^=f<<10; h+=e; f+=g; \
56 f^=g>>4; a+=f; g+=h; \
57 g^=h<<8; b+=g; h+=a; \
58 h^=a>>9; c+=h; a+=b; \
61 /* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */
62 void prnginit(ctx
, flag
)
69 ctx
->randa
= ctx
->randb
= ctx
->randc
= 0;
72 a
=b
=c
=d
=e
=f
=g
=h
=0x9e3779b9; /* the golden ratio */
74 for (i
=0; i
<4; ++i
) /* scramble it */
81 /* initialize using the contents of r[] as the seed */
82 for (i
=0; i
<RANDSIZ
; i
+=8)
84 a
+=r
[i
]; b
+=r
[i
+1]; c
+=r
[i
+2]; d
+=r
[i
+3];
85 e
+=r
[i
+4]; f
+=r
[i
+5]; g
+=r
[i
+6]; h
+=r
[i
+7];
87 m
[i
]=a
; m
[i
+1]=b
; m
[i
+2]=c
; m
[i
+3]=d
;
88 m
[i
+4]=e
; m
[i
+5]=f
; m
[i
+6]=g
; m
[i
+7]=h
;
90 /* do a second pass to make all of the seed affect all of m */
91 for (i
=0; i
<RANDSIZ
; i
+=8)
93 a
+=m
[i
]; b
+=m
[i
+1]; c
+=m
[i
+2]; d
+=m
[i
+3];
94 e
+=m
[i
+4]; f
+=m
[i
+5]; g
+=m
[i
+6]; h
+=m
[i
+7];
96 m
[i
]=a
; m
[i
+1]=b
; m
[i
+2]=c
; m
[i
+3]=d
;
97 m
[i
+4]=e
; m
[i
+5]=f
; m
[i
+6]=g
; m
[i
+7]=h
;
102 for (i
=0; i
<RANDSIZ
; i
+=8)
104 /* fill in mm[] with messy stuff */
105 mix(a
,b
,c
,d
,e
,f
,g
,h
);
106 m
[i
]=a
; m
[i
+1]=b
; m
[i
+2]=c
; m
[i
+3]=d
;
107 m
[i
+4]=e
; m
[i
+5]=f
; m
[i
+6]=g
; m
[i
+7]=h
;
111 isaac(ctx
); /* fill in the first set of results */
112 ctx
->randcnt
=RANDSIZ
; /* prepare to use the first set of results */
121 ctx
.randa
=ctx
.randb
=ctx
.randc
=(ub4
)0;
122 for (i
=0; i
<256; ++i
) ctx
.randrsl
[i
]=(ub4
)0;
123 prnginit(&ctx
, TRUE
);
127 for (j
=0; j
<256; ++j
)
129 printf("%.8lx",ctx
.randrsl
[j
]);
130 if ((j
&7)==7) printf("\n");