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