ISAACAlgorithm.java 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package com.oblivm.backend.rand;
  2. /**
  3. * <h3>ISAAC: a fast cryptographic pseudo-random number generator</h3>
  4. *
  5. * ISAAC (Indirection, Shift, Accumulate, Add, and Count) generates 32-bit
  6. * random numbers.<br>
  7. * ISAAC has been designed to be cryptographically secure and is inspired by
  8. * RC4.<br>
  9. * Cycles are guaranteed to be at least 2<sup>40</sup> values long, and they are
  10. * 2<sup>8295</sup> values long on average.<br>
  11. * The results are uniformly distributed, unbiased, and unpredictable unless you
  12. * know the seed.<br>
  13. * <br>
  14. * This is the original implementation by Bob Jenkins with some minor changes.
  15. * <br>
  16. * <br>
  17. * <b>Changelog:</b><br>
  18. * <ul>
  19. * <li>050325: Added <code>supplementSeed(int[] seed )</code> method; made all
  20. * variables private</li>
  21. * <li>050320: Use <code>System.arraycopy()</code> in
  22. * <code>ISAACAlgorithm(int[] seed)</code></li>
  23. * <li>980224: Translate to Java</li>
  24. * <li>970719: Use context, not global variables, for internal state</li>
  25. * <li>960327: Creation (addition of randinit, really)</li>
  26. * </ul>
  27. *
  28. * @author Bob Jenkins
  29. * @version 050325
  30. */
  31. class ISAACAlgorithm {
  32. private static final int SIZEL = 8; // Log of size of rsl[] and mem[]
  33. private static final int SIZE = 1 << SIZEL; // Size of rsl[] and mem[]
  34. private static final int MASK = (SIZE - 1) << 2; // For pseudorandom lookup
  35. private int count; // Count through the results in rsl[]
  36. private int rsl[]; // The results given to the user
  37. private int mem[]; // The internal state
  38. private int a; // Accumulator
  39. private int b; // The last result
  40. private int c; // Counter, guarantees cycle is at least 2^40
  41. /**
  42. * This constructor creates and initializes an new instance without using a
  43. * seed.<br>
  44. * Equivalent to <code>randinit(ctx,FALSE)</code> in the C implementation.
  45. */
  46. ISAACAlgorithm() {
  47. mem = new int[SIZE];
  48. rsl = new int[SIZE];
  49. init(false);
  50. }
  51. /**
  52. * This constructor creates and initializes an new instance using a
  53. * user-provided seed.<br>
  54. * Equivalent to <code>randinit(ctx, TRUE)</code> after putting seed in
  55. * <code>randctx</code> in the C implementation.
  56. *
  57. * @param seed
  58. * The seed.
  59. */
  60. ISAACAlgorithm(int[] seed) {
  61. mem = new int[SIZE];
  62. rsl = new int[SIZE];
  63. // This is slow and throws an ArrayIndexOutOfBoundsException if
  64. // seed.length > rsl.length ...
  65. /* for (int i = 0; i < seed.length; ++i) rsl[i] = seed[i]; */
  66. // ... this is faster and safe:
  67. System.arraycopy(seed, 0, rsl, 0, (seed.length <= rsl.length) ? seed.length : rsl.length);
  68. init(true);
  69. }
  70. /**
  71. * Generate 256 results.<br>
  72. * This is a small (not fast) implementation.
  73. */
  74. private final void isaac() {
  75. int i, x, y;
  76. b += ++c;
  77. for (i = 0; i < SIZE; ++i) {
  78. x = mem[i];
  79. switch (i & 3) {
  80. case 0:
  81. a ^= a << 13;
  82. break;
  83. case 1:
  84. a ^= a >>> 6;
  85. break;
  86. case 2:
  87. a ^= a << 2;
  88. break;
  89. case 3:
  90. a ^= a >>> 16;
  91. break;
  92. }
  93. a += mem[(i + SIZE / 2) & (SIZE - 1)];
  94. mem[i] = y = mem[((x) & MASK) >> 2] + a + b;
  95. rsl[i] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
  96. }
  97. }
  98. /**
  99. * Initialize or reinitialize this instance.
  100. *
  101. * @param flag
  102. * If <code>true</code> then use the seed (which the constructor
  103. * placed in <code>rsl[]</code>) for initialization.
  104. */
  105. private final void init(boolean flag) {
  106. int i;
  107. int a, b, c, d, e, f, g, h;
  108. a = b = c = d = e = f = g = h = 0x9e3779b9; // The golden ratio
  109. for (i = 0; i < 4; ++i) {
  110. a ^= b << 11;
  111. d += a;
  112. b += c;
  113. b ^= c >>> 2;
  114. e += b;
  115. c += d;
  116. c ^= d << 8;
  117. f += c;
  118. d += e;
  119. d ^= e >>> 16;
  120. g += d;
  121. e += f;
  122. e ^= f << 10;
  123. h += e;
  124. f += g;
  125. f ^= g >>> 4;
  126. a += f;
  127. g += h;
  128. g ^= h << 8;
  129. b += g;
  130. h += a;
  131. h ^= a >>> 9;
  132. c += h;
  133. a += b;
  134. }
  135. for (i = 0; i < SIZE; i += 8) { // Fill in mem[] with messy stuff
  136. if (flag) {
  137. a += rsl[i];
  138. b += rsl[i + 1];
  139. c += rsl[i + 2];
  140. d += rsl[i + 3];
  141. e += rsl[i + 4];
  142. f += rsl[i + 5];
  143. g += rsl[i + 6];
  144. h += rsl[i + 7];
  145. }
  146. a ^= b << 11;
  147. d += a;
  148. b += c;
  149. b ^= c >>> 2;
  150. e += b;
  151. c += d;
  152. c ^= d << 8;
  153. f += c;
  154. d += e;
  155. d ^= e >>> 16;
  156. g += d;
  157. e += f;
  158. e ^= f << 10;
  159. h += e;
  160. f += g;
  161. f ^= g >>> 4;
  162. a += f;
  163. g += h;
  164. g ^= h << 8;
  165. b += g;
  166. h += a;
  167. h ^= a >>> 9;
  168. c += h;
  169. a += b;
  170. mem[i] = a;
  171. mem[i + 1] = b;
  172. mem[i + 2] = c;
  173. mem[i + 3] = d;
  174. mem[i + 4] = e;
  175. mem[i + 5] = f;
  176. mem[i + 6] = g;
  177. mem[i + 7] = h;
  178. }
  179. if (flag) { // Second pass: makes all of seed affect all of mem[]
  180. for (i = 0; i < SIZE; i += 8) {
  181. a += mem[i];
  182. b += mem[i + 1];
  183. c += mem[i + 2];
  184. d += mem[i + 3];
  185. e += mem[i + 4];
  186. f += mem[i + 5];
  187. g += mem[i + 6];
  188. h += mem[i + 7];
  189. a ^= b << 11;
  190. d += a;
  191. b += c;
  192. b ^= c >>> 2;
  193. e += b;
  194. c += d;
  195. c ^= d << 8;
  196. f += c;
  197. d += e;
  198. d ^= e >>> 16;
  199. g += d;
  200. e += f;
  201. e ^= f << 10;
  202. h += e;
  203. f += g;
  204. f ^= g >>> 4;
  205. a += f;
  206. g += h;
  207. g ^= h << 8;
  208. b += g;
  209. h += a;
  210. h ^= a >>> 9;
  211. c += h;
  212. a += b;
  213. mem[i] = a;
  214. mem[i + 1] = b;
  215. mem[i + 2] = c;
  216. mem[i + 3] = d;
  217. mem[i + 4] = e;
  218. mem[i + 5] = f;
  219. mem[i + 6] = g;
  220. mem[i + 7] = h;
  221. }
  222. }
  223. isaac();
  224. count = SIZE;
  225. }
  226. /**
  227. * Get a random integer value.
  228. */
  229. final int nextInt() {
  230. if (0 == count--) {
  231. isaac();
  232. count = SIZE - 1;
  233. }
  234. return (rsl[count]);
  235. }
  236. /**
  237. * Reseeds this random object.<br>
  238. * The given seed supplements (using bitwise xor), rather than replaces, the
  239. * existing seed.
  240. *
  241. * @param seed
  242. * An integer array containing the seed.
  243. */
  244. final void supplementSeed(int[] seed) {
  245. for (int i = 0; i < seed.length; i++)
  246. mem[i % mem.length] ^= seed[i];
  247. }
  248. }