1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.rng.core.source32;
19
20 import java.util.Arrays;
21 import org.apache.commons.rng.core.util.NumberFactory;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class ISAACRandom extends IntProvider {
45
46 private static final int SIZE_L = 8;
47
48 private static final int SIZE = 1 << SIZE_L;
49
50 private static final int H_SIZE = SIZE >> 1;
51
52 private static final int MASK = SIZE - 1 << 2;
53
54 private static final int GLD_RATIO = 0x9e3779b9;
55
56 private final int[] rsl = new int[SIZE];
57
58 private final int[] mem = new int[SIZE];
59
60 private int count;
61
62 private int isaacA;
63
64 private int isaacB;
65
66 private int isaacC;
67
68 private final int[] arr = new int[8];
69
70 private int isaacX;
71
72 private int isaacI;
73
74 private int isaacJ;
75
76
77
78
79
80
81 public ISAACRandom(int[] seed) {
82 setSeedInternal(seed);
83 }
84
85
86 @Override
87 protected byte[] getStateInternal() {
88 final int[] sRsl = Arrays.copyOf(rsl, SIZE);
89 final int[] sMem = Arrays.copyOf(mem, SIZE);
90 final int[] sRem = Arrays.copyOf(new int[] { count, isaacA, isaacB, isaacC }, 4);
91
92 final int[] s = new int[2 * SIZE + sRem.length];
93 System.arraycopy(sRsl, 0, s, 0, SIZE);
94 System.arraycopy(sMem, 0, s, SIZE, SIZE);
95 System.arraycopy(sRem, 0, s, 2 * SIZE, sRem.length);
96
97 return NumberFactory.makeByteArray(s);
98 }
99
100
101 @Override
102 protected void setStateInternal(byte[] s) {
103 checkStateSize(s, (2 * SIZE + 4) * 4);
104
105 final int[] tmp = NumberFactory.makeIntArray(s);
106 System.arraycopy(tmp, 0, rsl, 0, SIZE);
107 System.arraycopy(tmp, SIZE, mem, 0, SIZE);
108 final int offset = 2 * SIZE;
109 count = tmp[offset];
110 isaacA = tmp[offset + 1];
111 isaacB = tmp[offset + 2];
112 isaacC = tmp[offset + 3];
113 }
114
115
116
117
118
119
120 private void setSeedInternal(int[] seed) {
121 final int seedLen = seed.length;
122 final int rslLen = rsl.length;
123 System.arraycopy(seed, 0, rsl, 0, Math.min(seedLen, rslLen));
124 if (seedLen < rslLen) {
125 for (int j = seedLen; j < rslLen; j++) {
126 long k = rsl[j - seedLen];
127 rsl[j] = (int) (0x6c078965L * (k ^ k >> 30) + j & 0xffffffffL);
128 }
129 }
130 initState();
131 }
132
133
134 @Override
135 public int next() {
136 if (count < 0) {
137 isaac();
138 count = SIZE - 1;
139 }
140 return rsl[count--];
141 }
142
143
144 private void isaac() {
145 isaacI = 0;
146 isaacJ = H_SIZE;
147 isaacB += ++isaacC;
148 while (isaacI < H_SIZE) {
149 isaac2();
150 }
151 isaacJ = 0;
152 while (isaacJ < H_SIZE) {
153 isaac2();
154 }
155 }
156
157
158 private void isaac2() {
159 isaacX = mem[isaacI];
160 isaacA ^= isaacA << 13;
161 isaacA += mem[isaacJ++];
162 isaac3();
163 isaacX = mem[isaacI];
164 isaacA ^= isaacA >>> 6;
165 isaacA += mem[isaacJ++];
166 isaac3();
167 isaacX = mem[isaacI];
168 isaacA ^= isaacA << 2;
169 isaacA += mem[isaacJ++];
170 isaac3();
171 isaacX = mem[isaacI];
172 isaacA ^= isaacA >>> 16;
173 isaacA += mem[isaacJ++];
174 isaac3();
175 }
176
177
178 private void isaac3() {
179 mem[isaacI] = mem[(isaacX & MASK) >> 2] + isaacA + isaacB;
180 isaacB = mem[(mem[isaacI] >> SIZE_L & MASK) >> 2] + isaacX;
181 rsl[isaacI++] = isaacB;
182 }
183
184
185 private void initState() {
186 isaacA = 0;
187 isaacB = 0;
188 isaacC = 0;
189 for (int j = 0; j < arr.length; j++) {
190 arr[j] = GLD_RATIO;
191 }
192 for (int j = 0; j < 4; j++) {
193 shuffle();
194 }
195
196 for (int j = 0; j < SIZE; j += 8) {
197 arr[0] += rsl[j];
198 arr[1] += rsl[j + 1];
199 arr[2] += rsl[j + 2];
200 arr[3] += rsl[j + 3];
201 arr[4] += rsl[j + 4];
202 arr[5] += rsl[j + 5];
203 arr[6] += rsl[j + 6];
204 arr[7] += rsl[j + 7];
205 shuffle();
206 setState(j);
207 }
208
209 for (int j = 0; j < SIZE; j += 8) {
210 arr[0] += mem[j];
211 arr[1] += mem[j + 1];
212 arr[2] += mem[j + 2];
213 arr[3] += mem[j + 3];
214 arr[4] += mem[j + 4];
215 arr[5] += mem[j + 5];
216 arr[6] += mem[j + 6];
217 arr[7] += mem[j + 7];
218 shuffle();
219 setState(j);
220 }
221 isaac();
222 count = SIZE - 1;
223 }
224
225
226 private void shuffle() {
227 arr[0] ^= arr[1] << 11;
228 arr[3] += arr[0];
229 arr[1] += arr[2];
230 arr[1] ^= arr[2] >>> 2;
231 arr[4] += arr[1];
232 arr[2] += arr[3];
233 arr[2] ^= arr[3] << 8;
234 arr[5] += arr[2];
235 arr[3] += arr[4];
236 arr[3] ^= arr[4] >>> 16;
237 arr[6] += arr[3];
238 arr[4] += arr[5];
239 arr[4] ^= arr[5] << 10;
240 arr[7] += arr[4];
241 arr[5] += arr[6];
242 arr[5] ^= arr[6] >>> 4;
243 arr[0] += arr[5];
244 arr[6] += arr[7];
245 arr[6] ^= arr[7] << 8;
246 arr[1] += arr[6];
247 arr[7] += arr[0];
248 arr[7] ^= arr[0] >>> 9;
249 arr[2] += arr[7];
250 arr[0] += arr[1];
251 }
252
253
254
255
256
257 private void setState(int start) {
258 mem[start] = arr[0];
259 mem[start + 1] = arr[1];
260 mem[start + 2] = arr[2];
261 mem[start + 3] = arr[3];
262 mem[start + 4] = arr[4];
263 mem[start + 5] = arr[5];
264 mem[start + 6] = arr[6];
265 mem[start + 7] = arr[7];
266 }
267 }