/src/rt/isaac/randport.cpp

http://github.com/jruderman/rust · C++ · 134 lines · 109 code · 11 blank · 14 comment · 11 complexity · 7c5a573a1e4fc463af0bfa0ccb7aed5d MD5 · raw file

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