/* ------------------------------------------------------------------------------ readable.c: My random number generator, ISAAC. (c) Bob Jenkins, March 1996, Public Domain You may use this code in any way you wish, and it is free. No warrantee. * May 2008 -- made it not depend on standard.h ------------------------------------------------------------------------------ The original version of this file was downloaded from Bob Jenkins website: http://burtleburtle.net/bob/rand/isaacafa.html The isaac and randinit functions have been slightly modified to silence warnings in modern compilers; the get_entropy and get_random_bytes have been added. These changes were made by R M Yorston and are also dedicated to the public domain. */ #include "libbb.h" /* external results */ static uint32_t randrsl[256]; /* internal state */ static uint32_t mm[256]; static uint32_t aa=0, bb=0, cc=0; static void isaac(void) { register uint32_t 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; \ } static void randinit(int flag) { int i; uint32_t a,b,c,d,e,f,g,h; aa=bb=cc=0; a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */ for (i=0; i<4; ++i) /* scramble it */ { 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 */ } /* call 'fn' to put data in 'dt' then copy it to generator state */ #define GET_DATA(fn, dt) \ fn(&dt); \ u = (uint32_t *)&dt; \ for (j=0; j 0) { int bytes_left = RAND_BYTES - rand_index; if (bytes_left >= count) { /* we have enough random bytes */ memcpy(buf, ptr+rand_index, count); rand_index += count; count = 0; } else { /* insufficient bytes, use what we have */ memcpy(buf, ptr+rand_index, bytes_left); buf += bytes_left; count -= bytes_left; rand_index += bytes_left; } if (rand_index >= RAND_BYTES) { /* generate more */ isaac(); rand_index = 0; } } return save_count; }