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 composeStateInternal(NumberFactory.makeByteArray(s),
98 super.getStateInternal());
99 }
100
101
102 @Override
103 protected void setStateInternal(byte[] s) {
104 final byte[][] c = splitStateInternal(s, (2 * SIZE + 4) * 4);
105
106 final int[] tmp = NumberFactory.makeIntArray(c[0]);
107 System.arraycopy(tmp, 0, rsl, 0, SIZE);
108 System.arraycopy(tmp, SIZE, mem, 0, SIZE);
109 final int offset = 2 * SIZE;
110 count = tmp[offset];
111 isaacA = tmp[offset + 1];
112 isaacB = tmp[offset + 2];
113 isaacC = tmp[offset + 3];
114
115 super.setStateInternal(c[1]);
116 }
117
118
119
120
121
122
123 private void setSeedInternal(int[] seed) {
124 final int seedLen = seed.length;
125 final int rslLen = rsl.length;
126 System.arraycopy(seed, 0, rsl, 0, Math.min(seedLen, rslLen));
127 if (seedLen < rslLen) {
128 for (int j = seedLen; j < rslLen; j++) {
129 final long k = rsl[j - seedLen];
130 rsl[j] = (int) (0x6c078965L * (k ^ k >> 30) + j & 0xffffffffL);
131 }
132 }
133 initState();
134 }
135
136
137 @Override
138 public int next() {
139 if (count < 0) {
140 isaac();
141 count = SIZE - 1;
142 }
143 return rsl[count--];
144 }
145
146
147 private void isaac() {
148 isaacI = 0;
149 isaacJ = H_SIZE;
150 isaacB += ++isaacC;
151 while (isaacI < H_SIZE) {
152 isaac2();
153 }
154 isaacJ = 0;
155 while (isaacJ < H_SIZE) {
156 isaac2();
157 }
158 }
159
160
161 private void isaac2() {
162 isaacX = mem[isaacI];
163 isaacA ^= isaacA << 13;
164 isaacA += mem[isaacJ++];
165 isaac3();
166 isaacX = mem[isaacI];
167 isaacA ^= isaacA >>> 6;
168 isaacA += mem[isaacJ++];
169 isaac3();
170 isaacX = mem[isaacI];
171 isaacA ^= isaacA << 2;
172 isaacA += mem[isaacJ++];
173 isaac3();
174 isaacX = mem[isaacI];
175 isaacA ^= isaacA >>> 16;
176 isaacA += mem[isaacJ++];
177 isaac3();
178 }
179
180
181 private void isaac3() {
182 mem[isaacI] = mem[(isaacX & MASK) >> 2] + isaacA + isaacB;
183 isaacB = mem[(mem[isaacI] >> SIZE_L & MASK) >> 2] + isaacX;
184 rsl[isaacI++] = isaacB;
185 }
186
187
188 private void initState() {
189 isaacA = 0;
190 isaacB = 0;
191 isaacC = 0;
192 Arrays.fill(arr, GLD_RATIO);
193 for (int j = 0; j < 4; j++) {
194 shuffle();
195 }
196
197 for (int j = 0; j < SIZE; j += 8) {
198 arr[0] += rsl[j];
199 arr[1] += rsl[j + 1];
200 arr[2] += rsl[j + 2];
201 arr[3] += rsl[j + 3];
202 arr[4] += rsl[j + 4];
203 arr[5] += rsl[j + 5];
204 arr[6] += rsl[j + 6];
205 arr[7] += rsl[j + 7];
206 shuffle();
207 setState(j);
208 }
209
210 for (int j = 0; j < SIZE; j += 8) {
211 arr[0] += mem[j];
212 arr[1] += mem[j + 1];
213 arr[2] += mem[j + 2];
214 arr[3] += mem[j + 3];
215 arr[4] += mem[j + 4];
216 arr[5] += mem[j + 5];
217 arr[6] += mem[j + 6];
218 arr[7] += mem[j + 7];
219 shuffle();
220 setState(j);
221 }
222 isaac();
223 count = SIZE - 1;
224 }
225
226
227 private void shuffle() {
228 arr[0] ^= arr[1] << 11;
229 arr[3] += arr[0];
230 arr[1] += arr[2];
231 arr[1] ^= arr[2] >>> 2;
232 arr[4] += arr[1];
233 arr[2] += arr[3];
234 arr[2] ^= arr[3] << 8;
235 arr[5] += arr[2];
236 arr[3] += arr[4];
237 arr[3] ^= arr[4] >>> 16;
238 arr[6] += arr[3];
239 arr[4] += arr[5];
240 arr[4] ^= arr[5] << 10;
241 arr[7] += arr[4];
242 arr[5] += arr[6];
243 arr[5] ^= arr[6] >>> 4;
244 arr[0] += arr[5];
245 arr[6] += arr[7];
246 arr[6] ^= arr[7] << 8;
247 arr[1] += arr[6];
248 arr[7] += arr[0];
249 arr[7] ^= arr[0] >>> 9;
250 arr[2] += arr[7];
251 arr[0] += arr[1];
252 }
253
254
255
256
257
258 private void setState(int start) {
259 mem[start] = arr[0];
260 mem[start + 1] = arr[1];
261 mem[start + 2] = arr[2];
262 mem[start + 3] = arr[3];
263 mem[start + 4] = arr[4];
264 mem[start + 5] = arr[5];
265 mem[start + 6] = arr[6];
266 mem[start + 7] = arr[7];
267 }
268 }