2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 ------------------------------------------------------------------------------
17 By Bob Jenkins, 1996, Public Domain
19 960327: Creation (addition of randinit, really)
20 970719: use context, not global variables, for internal state
21 980324: renamed seed to flag
22 980605: recommend ISAAC_LOG2_SIZE=4 for noncryptography.
23 010626: note this is public domain
24 ------------------------------------------------------------------------------
26 Modified for CLIB by Eliot Dresselhaus.
27 Dear Bob, Thanks for all the great work. - Eliot
29 modifications copyright (c) 2003 Eliot Dresselhaus
31 Permission is hereby granted, free of charge, to any person obtaining
32 a copy of this software and associated documentation files (the
33 "Software"), to deal in the Software without restriction, including
34 without limitation the rights to use, copy, modify, merge, publish,
35 distribute, sublicense, and/or sell copies of the Software, and to
36 permit persons to whom the Software is furnished to do so, subject to
37 the following conditions:
39 The above copyright notice and this permission notice shall be
40 included in all copies or substantial portions of the Software.
42 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
43 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
45 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
46 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
47 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
48 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
51 /* ISAAC is Bob Jenkins' random number generator.
52 http://burtleburtle.net/bob/rand/isaacafa.html */
54 #include <vppinfra/random_isaac.h>
56 #if uword_bits != 32 && uword_bits != 64
57 #error "isaac only works for 32 or 64 bit words"
62 #define ind32(mm,x) (*(u32 *)((u8 *)(mm) + ((x) & ((ISAAC_SIZE-1)<<2))))
63 #define rngstep32(mix,a,b,mm,m,m2,r,x,y) \
66 a = (a^(mix)) + *(m2++); \
67 *(m++) = y = ind32(mm,x) + a + b; \
68 *(r++) = b = ind32(mm,y>>ISAAC_LOG2_SIZE) + x; \
71 void isaac (isaac_t * ctx, uword * results)
73 u32 a, b, c, x, y, * m, * mm, * m2, * r, * mend;
82 mend = m2 = mm + ARRAY_LEN (ctx->memory) / 2;
86 rngstep32 (a<<13, a, b, mm, m, m2, r, x, y);
87 rngstep32 (a>>6 , a, b, mm, m, m2, r, x, y);
88 rngstep32 (a<<2 , a, b, mm, m, m2, r, x, y);
89 rngstep32 (a>>16, a, b, mm, m, m2, r, x, y);
95 rngstep32 (a<<13, a, b, mm, m, m2, r, x, y);
96 rngstep32 (a>>6 , a, b, mm, m, m2, r, x, y);
97 rngstep32 (a<<2 , a, b, mm, m, m2, r, x, y);
98 rngstep32 (a>>16, a, b, mm, m, m2, r, x, y);
106 /* Perform 2 isaac runs with different contexts simultaneously. */
107 void isaac2 (isaac_t * ctx, uword * results)
110 u32 a##n, b##n, c##n, x##n, y##n, * m##n, * mm##n, * m2##n, * r##n, * mend##n
113 (void)mend1; /* "set but unused variable" error on mend1 with gcc 4.9 */
118 mm##n = ctx[(n)].memory; \
119 r##n = results + (n) * ISAAC_SIZE; \
124 mend##n = m2##n = mm##n + ARRAY_LEN (ctx[(n)].memory) / 2; \
134 rngstep32 (a0<<13, a0, b0, mm0, m0, m20, r0, x0, y0);
135 rngstep32 (a1<<13, a1, b1, mm1, m1, m21, r1, x1, y1);
136 rngstep32 (a0>>6 , a0, b0, mm0, m0, m20, r0, x0, y0);
137 rngstep32 (a1>>6 , a1, b1, mm1, m1, m21, r1, x1, y1);
138 rngstep32 (a0<<2 , a0, b0, mm0, m0, m20, r0, x0, y0);
139 rngstep32 (a1<<2 , a1, b1, mm1, m1, m21, r1, x1, y1);
140 rngstep32 (a0>>16, a0, b0, mm0, m0, m20, r0, x0, y0);
141 rngstep32 (a1>>16, a1, b1, mm1, m1, m21, r1, x1, y1);
148 rngstep32 (a0<<13, a0, b0, mm0, m0, m20, r0, x0, y0);
149 rngstep32 (a1<<13, a1, b1, mm1, m1, m21, r1, x1, y1);
150 rngstep32 (a0>>6 , a0, b0, mm0, m0, m20, r0, x0, y0);
151 rngstep32 (a1>>6 , a1, b1, mm1, m1, m21, r1, x1, y1);
152 rngstep32 (a0<<2 , a0, b0, mm0, m0, m20, r0, x0, y0);
153 rngstep32 (a1<<2 , a1, b1, mm1, m1, m21, r1, x1, y1);
154 rngstep32 (a0>>16, a0, b0, mm0, m0, m20, r0, x0, y0);
155 rngstep32 (a1>>16, a1, b1, mm1, m1, m21, r1, x1, y1);
166 #define mix32(a,b,c,d,e,f,g,h) \
168 a^=b<<11; d+=a; b+=c; \
169 b^=c>>2; e+=b; c+=d; \
170 c^=d<<8; f+=c; d+=e; \
171 d^=e>>16; g+=d; e+=f; \
172 e^=f<<10; h+=e; f+=g; \
173 f^=g>>4; a+=f; g+=h; \
174 g^=h<<8; b+=g; h+=a; \
175 h^=a>>9; c+=h; a+=b; \
178 void isaac_init (isaac_t * ctx, uword * seeds)
181 u32 a, b, c, d, e, f, g, h, * m, * r;
183 ctx->a = ctx->b = ctx->c = 0;
187 a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */
189 for (i = 0; i < 4; ++i) /* scramble it */
190 mix32(a,b,c,d,e,f,g,h);
192 /* initialize using the contents of r[] as the seed */
193 for (i=0; i<ISAAC_SIZE; i+=8)
195 a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
196 e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
197 mix32(a,b,c,d,e,f,g,h);
198 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
199 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
202 /* do a second pass to make all of the seed affect all of m */
203 for (i=0; i<ISAAC_SIZE; i+=8)
205 a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
206 e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
207 mix32(a,b,c,d,e,f,g,h);
208 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
209 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
212 #endif /* uword_bits == 32 */
216 #define ind64(mm,x) (*(u64 *)((u8 *)(mm) + ((x) & ((ISAAC_SIZE-1)<<3))))
217 #define rngstep64(mix,a,b,mm,m,m2,r,x,y) \
220 a = (mix) + *(m2++); \
221 *(m++) = y = ind64(mm,x) + a + b; \
222 *(r++) = b = ind64(mm,y>>ISAAC_LOG2_SIZE) + x; \
225 void isaac (isaac_t * ctx, uword * results)
227 u64 a, b, c, x, y, * m, * mm, * m2, * r, * mend;
236 mend = m2 = mm + ARRAY_LEN (ctx->memory) / 2;
240 rngstep64 (~(a^(a<<21)), a, b, mm, m, m2, r, x, y);
241 rngstep64 ( a^(a>>5) , a, b, mm, m, m2, r, x, y);
242 rngstep64 ( a^(a<<12) , a, b, mm, m, m2, r, x, y);
243 rngstep64 ( a^(a>>33) , a, b, mm, m, m2, r, x, y);
249 rngstep64 (~(a^(a<<21)), a, b, mm, m, m2, r, x, y);
250 rngstep64 ( a^(a>>5) , a, b, mm, m, m2, r, x, y);
251 rngstep64 ( a^(a<<12) , a, b, mm, m, m2, r, x, y);
252 rngstep64 ( a^(a>>33) , a, b, mm, m, m2, r, x, y);
260 /* Perform 2 isaac runs with different contexts simultaneously. */
261 void isaac2 (isaac_t * ctx, uword * results)
264 u64 a##n, b##n, c##n, x##n, y##n, * m##n, * mm##n, * m2##n, * r##n, * mend##n
272 mm##n = ctx[(n)].memory; \
273 r##n = results + (n) * ISAAC_SIZE; \
278 mend##n = m2##n = mm##n + ARRAY_LEN (ctx[(n)].memory) / 2; \
286 (void) mend1; /* compiler warning */
290 rngstep64 (~(a0^(a0<<21)), a0, b0, mm0, m0, m20, r0, x0, y0);
291 rngstep64 (~(a1^(a1<<21)), a1, b1, mm1, m1, m21, r1, x1, y1);
292 rngstep64 ( a0^(a0>>5) , a0, b0, mm0, m0, m20, r0, x0, y0);
293 rngstep64 ( a1^(a1>>5) , a1, b1, mm1, m1, m21, r1, x1, y1);
294 rngstep64 ( a0^(a0<<12) , a0, b0, mm0, m0, m20, r0, x0, y0);
295 rngstep64 ( a1^(a1<<12) , a1, b1, mm1, m1, m21, r1, x1, y1);
296 rngstep64 ( a0^(a0>>33) , a0, b0, mm0, m0, m20, r0, x0, y0);
297 rngstep64 ( a1^(a1>>33) , a1, b1, mm1, m1, m21, r1, x1, y1);
304 rngstep64 (~(a0^(a0<<21)), a0, b0, mm0, m0, m20, r0, x0, y0);
305 rngstep64 (~(a1^(a1<<21)), a1, b1, mm1, m1, m21, r1, x1, y1);
306 rngstep64 ( a0^(a0>>5) , a0, b0, mm0, m0, m20, r0, x0, y0);
307 rngstep64 ( a1^(a1>>5) , a1, b1, mm1, m1, m21, r1, x1, y1);
308 rngstep64 ( a0^(a0<<12) , a0, b0, mm0, m0, m20, r0, x0, y0);
309 rngstep64 ( a1^(a1<<12) , a1, b1, mm1, m1, m21, r1, x1, y1);
310 rngstep64 ( a0^(a0>>33) , a0, b0, mm0, m0, m20, r0, x0, y0);
311 rngstep64 ( a1^(a1>>33) , a1, b1, mm1, m1, m21, r1, x1, y1);
322 #define mix64(a,b,c,d,e,f,g,h) \
324 a-=e; f^=h>>9; h+=a; \
325 b-=f; g^=a<<9; a+=b; \
326 c-=g; h^=b>>23; b+=c; \
327 d-=h; a^=c<<15; c+=d; \
328 e-=a; b^=d>>14; d+=e; \
329 f-=b; c^=e<<20; e+=f; \
330 g-=c; d^=f>>17; f+=g; \
331 h-=d; e^=g<<14; g+=h; \
334 void isaac_init (isaac_t * ctx, uword * seeds)
337 u64 a, b, c, d, e, f, g, h, * m, * r;
339 ctx->a = ctx->b = ctx->c = 0;
343 a = b = c = d = e = f = g = h = 0x9e3779b97f4a7c13LL; /* the golden ratio */
345 for (i=0; i<4; ++i) /* scramble it */
346 mix64(a,b,c,d,e,f,g,h);
348 for (i=0; i<ISAAC_SIZE; i+=8) /* fill in mm[] with messy stuff */
350 a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
351 e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
352 mix64(a,b,c,d,e,f,g,h);
353 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
354 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
357 /* do a second pass to make all of the seed affect all of mm */
358 for (i=0; i<ISAAC_SIZE; i+=8)
360 a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
361 e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
362 mix64(a,b,c,d,e,f,g,h);
363 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
364 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
367 #endif /* uword_bits == 64 */