]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | ------------------------------------------------------------------------------ | |
3 | rand.c: By Bob Jenkins. My random number generator, ISAAC. Public Domain | |
4 | MODIFIED: | |
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 | ------------------------------------------------------------------------------ | |
10 | */ | |
11 | #ifndef PRNG | |
12 | #include "prng.h" | |
13 | #endif | |
14 | ||
15 | ||
16 | #define ind(mm,x) ((mm)[(x>>2)&(RANDSIZ-1)]) | |
17 | #define rngstep(mix,a,b,mm,m,m2,r,x) \ | |
18 | { \ | |
19 | x = *m; \ | |
20 | a = ((a^(mix)) + *(m2++)) & 0xffffffff; \ | |
21 | *(m++) = y = (ind(mm,x) + a + b) & 0xffffffff; \ | |
22 | *(r++) = b = (ind(mm,y>>RANDSIZL) + x) & 0xffffffff; \ | |
23 | } | |
24 | ||
25 | void isaac(ctx) | |
26 | prngctx *ctx; | |
27 | { | |
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; ) | |
32 | { | |
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); | |
37 | } | |
38 | for (m2 = mm; m2<mend; ) | |
39 | { | |
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); | |
44 | } | |
45 | ctx->randb = b; ctx->randa = a; | |
46 | } | |
47 | ||
48 | ||
49 | #define mix(a,b,c,d,e,f,g,h) \ | |
50 | { \ | |
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; \ | |
59 | } | |
60 | ||
61 | /* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */ | |
62 | void prnginit(ctx, flag) | |
63 | prngctx *ctx; | |
64 | word flag; | |
65 | { | |
66 | word i; | |
67 | ub4 a,b,c,d,e,f,g,h; | |
68 | ub4 *m,*r; | |
69 | ctx->randa = ctx->randb = ctx->randc = 0; | |
70 | m=ctx->randmem; | |
71 | r=ctx->randrsl; | |
72 | a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */ | |
73 | ||
74 | for (i=0; i<4; ++i) /* scramble it */ | |
75 | { | |
76 | mix(a,b,c,d,e,f,g,h); | |
77 | } | |
78 | ||
79 | if (flag) | |
80 | { | |
81 | /* initialize using the contents of r[] as the seed */ | |
82 | for (i=0; i<RANDSIZ; i+=8) | |
83 | { | |
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]; | |
86 | mix(a,b,c,d,e,f,g,h); | |
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; | |
89 | } | |
90 | /* do a second pass to make all of the seed affect all of m */ | |
91 | for (i=0; i<RANDSIZ; i+=8) | |
92 | { | |
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]; | |
95 | mix(a,b,c,d,e,f,g,h); | |
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; | |
98 | } | |
99 | } | |
100 | else | |
101 | { | |
102 | for (i=0; i<RANDSIZ; i+=8) | |
103 | { | |
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; | |
108 | } | |
109 | } | |
110 | ||
111 | isaac(ctx); /* fill in the first set of results */ | |
112 | ctx->randcnt=RANDSIZ; /* prepare to use the first set of results */ | |
113 | } | |
114 | ||
115 | ||
116 | #ifdef NEVER | |
117 | int main() | |
118 | { | |
119 | ub4 i,j; | |
120 | prngctx ctx; | |
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); | |
124 | for (i=0; i<2; ++i) | |
125 | { | |
126 | isaac(&ctx); | |
127 | for (j=0; j<256; ++j) | |
128 | { | |
129 | printf("%.8lx",ctx.randrsl[j]); | |
130 | if ((j&7)==7) printf("\n"); | |
131 | } | |
132 | } | |
133 | } | |
134 | #endif |