rand.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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: added main (ifdef'ed out), also rearranged randinit()
  8. 010626: Note that this is public domain
  9. ------------------------------------------------------------------------------
  10. */
  11. #ifndef STANDARD
  12. #include "standard.h"
  13. #endif
  14. #ifndef RAND
  15. #include "rand.h"
  16. #endif
  17. #define ind(mm,x) (*(ub4 *)((ub1 *)(mm) + ((x) & ((RANDSIZ-1)<<2))))
  18. #define rngstep(mix,a,b,mm,m,m2,r,x) \
  19. { \
  20. x = *m; \
  21. a = (a^(mix)) + *(m2++); \
  22. *(m++) = y = ind(mm,x) + a + b; \
  23. *(r++) = b = ind(mm,y>>RANDSIZL) + x; \
  24. }
  25. void isaac(ctx)
  26. randctx *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);
  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. #define mix(a,b,c,d,e,f,g,h) \
  48. { \
  49. a^=b<<11; d+=a; b+=c; \
  50. b^=c>>2; e+=b; c+=d; \
  51. c^=d<<8; f+=c; d+=e; \
  52. d^=e>>16; g+=d; e+=f; \
  53. e^=f<<10; h+=e; f+=g; \
  54. f^=g>>4; a+=f; g+=h; \
  55. g^=h<<8; b+=g; h+=a; \
  56. h^=a>>9; c+=h; a+=b; \
  57. }
  58. /* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */
  59. void randinit(ctx, flag)
  60. randctx *ctx;
  61. word flag;
  62. {
  63. word i;
  64. ub4 a,b,c,d,e,f,g,h;
  65. ub4 *m,*r;
  66. ctx->randa = ctx->randb = ctx->randc = 0;
  67. m=ctx->randmem;
  68. r=ctx->randrsl;
  69. a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */
  70. for (i=0; i<4; ++i) /* scramble it */
  71. {
  72. mix(a,b,c,d,e,f,g,h);
  73. }
  74. if (flag)
  75. {
  76. /* initialize using the contents of r[] as the seed */
  77. for (i=0; i<RANDSIZ; i+=8)
  78. {
  79. a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
  80. e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
  81. mix(a,b,c,d,e,f,g,h);
  82. m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
  83. m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
  84. }
  85. /* do a second pass to make all of the seed affect all of m */
  86. for (i=0; i<RANDSIZ; i+=8)
  87. {
  88. a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
  89. e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
  90. mix(a,b,c,d,e,f,g,h);
  91. m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
  92. m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
  93. }
  94. }
  95. else
  96. {
  97. /* fill in m[] with messy stuff */
  98. for (i=0; i<RANDSIZ; i+=8)
  99. {
  100. mix(a,b,c,d,e,f,g,h);
  101. m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
  102. m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
  103. }
  104. }
  105. isaac(ctx); /* fill in the first set of results */
  106. ctx->randcnt=RANDSIZ; /* prepare to use the first set of results */
  107. }
  108. #ifdef NEVER
  109. int main()
  110. {
  111. ub4 i,j;
  112. randctx ctx;
  113. ctx.randa=ctx.randb=ctx.randc=(ub4)0;
  114. for (i=0; i<256; ++i) ctx.randrsl[i]=(ub4)0;
  115. randinit(&ctx, TRUE);
  116. for (i=0; i<2; ++i)
  117. {
  118. isaac(&ctx);
  119. for (j=0; j<256; ++j)
  120. {
  121. printf("%.8lx",ctx.randrsl[j]);
  122. if ((j&7)==7) printf("\n");
  123. }
  124. }
  125. }
  126. #endif