source: src/main/java/agents/anac/y2019/harddealer/math3/random/ISAACRandom.java

Last change on this file was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

  • Property svn:executable set to *
File size: 8.1 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package agents.anac.y2019.harddealer.math3.random;
19
20import java.io.Serializable;
21
22import agents.anac.y2019.harddealer.math3.util.FastMath;
23
24/**
25 * <a href="http://burtleburtle.net/bob/rand/isaacafa.html">
26 * ISAAC: a fast cryptographic pseudo-random number generator</a>
27 * <br/>
28 * ISAAC (Indirection, Shift, Accumulate, Add, and Count) generates 32-bit
29 * random numbers.
30 * ISAAC has been designed to be cryptographically secure and is inspired
31 * by RC4.
32 * Cycles are guaranteed to be at least 2<sup>40</sup> values long, and they
33 * are 2<sup>8295</sup> values long on average.
34 * The results are uniformly distributed, unbiased, and unpredictable unless
35 * you know the seed.
36 * <br/>
37 * This code is based (with minor changes and improvements) on the original
38 * implementation of the algorithm by Bob Jenkins.
39 * <br/>
40 *
41 * @since 3.0
42 */
43public class ISAACRandom extends BitsStreamGenerator implements Serializable {
44 /** Serializable version identifier */
45 private static final long serialVersionUID = 7288197941165002400L;
46 /** Log of size of rsl[] and mem[] */
47 private static final int SIZE_L = 8;
48 /** Size of rsl[] and mem[] */
49 private static final int SIZE = 1 << SIZE_L;
50 /** Half-size of rsl[] and mem[] */
51 private static final int H_SIZE = SIZE >> 1;
52 /** For pseudo-random lookup */
53 private static final int MASK = SIZE - 1 << 2;
54 /** The golden ratio */
55 private static final int GLD_RATIO = 0x9e3779b9;
56 /** The results given to the user */
57 private final int[] rsl = new int[SIZE];
58 /** The internal state */
59 private final int[] mem = new int[SIZE];
60 /** Count through the results in rsl[] */
61 private int count;
62 /** Accumulator */
63 private int isaacA;
64 /** The last result */
65 private int isaacB;
66 /** Counter, guarantees cycle is at least 2^40 */
67 private int isaacC;
68 /** Service variable. */
69 private final int[] arr = new int[8];
70 /** Service variable. */
71 private int isaacX;
72 /** Service variable. */
73 private int isaacI;
74 /** Service variable. */
75 private int isaacJ;
76
77
78 /**
79 * Creates a new ISAAC random number generator.
80 * <br/>
81 * The instance is initialized using a combination of the
82 * current time and system hash code of the instance as the seed.
83 */
84 public ISAACRandom() {
85 setSeed(System.currentTimeMillis() + System.identityHashCode(this));
86 }
87
88 /**
89 * Creates a new ISAAC random number generator using a single long seed.
90 *
91 * @param seed Initial seed.
92 */
93 public ISAACRandom(long seed) {
94 setSeed(seed);
95 }
96
97 /**
98 * Creates a new ISAAC random number generator using an int array seed.
99 *
100 * @param seed Initial seed. If {@code null}, the seed will be related
101 * to the current time.
102 */
103 public ISAACRandom(int[] seed) {
104 setSeed(seed);
105 }
106
107 /** {@inheritDoc} */
108 @Override
109 public void setSeed(int seed) {
110 setSeed(new int[]{seed});
111 }
112
113 /** {@inheritDoc} */
114 @Override
115 public void setSeed(long seed) {
116 setSeed(new int[]{(int) (seed >>> 32), (int) (seed & 0xffffffffL)});
117 }
118
119 /** {@inheritDoc} */
120 @Override
121 public void setSeed(int[] seed) {
122 if (seed == null) {
123 setSeed(System.currentTimeMillis() + System.identityHashCode(this));
124 return;
125 }
126 final int seedLen = seed.length;
127 final int rslLen = rsl.length;
128 System.arraycopy(seed, 0, rsl, 0, FastMath.min(seedLen, rslLen));
129 if (seedLen < rslLen) {
130 for (int j = seedLen; j < rslLen; j++) {
131 long k = rsl[j - seedLen];
132 rsl[j] = (int) (0x6c078965L * (k ^ k >> 30) + j & 0xffffffffL);
133 }
134 }
135 initState();
136 }
137
138 /** {@inheritDoc} */
139 @Override
140 protected int next(int bits) {
141 if (count < 0) {
142 isaac();
143 count = SIZE - 1;
144 }
145 return rsl[count--] >>> 32 - bits;
146 }
147
148 /** Generate 256 results */
149 private void isaac() {
150 isaacI = 0;
151 isaacJ = H_SIZE;
152 isaacB += ++isaacC;
153 while (isaacI < H_SIZE) {
154 isaac2();
155 }
156 isaacJ = 0;
157 while (isaacJ < H_SIZE) {
158 isaac2();
159 }
160 }
161
162 /** Intermediate internal loop. */
163 private void isaac2() {
164 isaacX = mem[isaacI];
165 isaacA ^= isaacA << 13;
166 isaacA += mem[isaacJ++];
167 isaac3();
168 isaacX = mem[isaacI];
169 isaacA ^= isaacA >>> 6;
170 isaacA += mem[isaacJ++];
171 isaac3();
172 isaacX = mem[isaacI];
173 isaacA ^= isaacA << 2;
174 isaacA += mem[isaacJ++];
175 isaac3();
176 isaacX = mem[isaacI];
177 isaacA ^= isaacA >>> 16;
178 isaacA += mem[isaacJ++];
179 isaac3();
180 }
181
182 /** Lowest level internal loop. */
183 private void isaac3() {
184 mem[isaacI] = mem[(isaacX & MASK) >> 2] + isaacA + isaacB;
185 isaacB = mem[(mem[isaacI] >> SIZE_L & MASK) >> 2] + isaacX;
186 rsl[isaacI++] = isaacB;
187 }
188
189 /** Initialize, or reinitialize, this instance of rand. */
190 private void initState() {
191 isaacA = 0;
192 isaacB = 0;
193 isaacC = 0;
194 for (int j = 0; j < arr.length; j++) {
195 arr[j] = GLD_RATIO;
196 }
197 for (int j = 0; j < 4; j++) {
198 shuffle();
199 }
200 // fill in mem[] with messy stuff
201 for (int j = 0; j < SIZE; j += 8) {
202 arr[0] += rsl[j];
203 arr[1] += rsl[j + 1];
204 arr[2] += rsl[j + 2];
205 arr[3] += rsl[j + 3];
206 arr[4] += rsl[j + 4];
207 arr[5] += rsl[j + 5];
208 arr[6] += rsl[j + 6];
209 arr[7] += rsl[j + 7];
210 shuffle();
211 setState(j);
212 }
213 // second pass makes all of seed affect all of mem
214 for (int j = 0; j < SIZE; j += 8) {
215 arr[0] += mem[j];
216 arr[1] += mem[j + 1];
217 arr[2] += mem[j + 2];
218 arr[3] += mem[j + 3];
219 arr[4] += mem[j + 4];
220 arr[5] += mem[j + 5];
221 arr[6] += mem[j + 6];
222 arr[7] += mem[j + 7];
223 shuffle();
224 setState(j);
225 }
226 isaac();
227 count = SIZE - 1;
228 clear();
229 }
230
231 /** Shuffle array. */
232 private void shuffle() {
233 arr[0] ^= arr[1] << 11;
234 arr[3] += arr[0];
235 arr[1] += arr[2];
236 arr[1] ^= arr[2] >>> 2;
237 arr[4] += arr[1];
238 arr[2] += arr[3];
239 arr[2] ^= arr[3] << 8;
240 arr[5] += arr[2];
241 arr[3] += arr[4];
242 arr[3] ^= arr[4] >>> 16;
243 arr[6] += arr[3];
244 arr[4] += arr[5];
245 arr[4] ^= arr[5] << 10;
246 arr[7] += arr[4];
247 arr[5] += arr[6];
248 arr[5] ^= arr[6] >>> 4;
249 arr[0] += arr[5];
250 arr[6] += arr[7];
251 arr[6] ^= arr[7] << 8;
252 arr[1] += arr[6];
253 arr[7] += arr[0];
254 arr[7] ^= arr[0] >>> 9;
255 arr[2] += arr[7];
256 arr[0] += arr[1];
257 }
258
259 /** Set the state by copying the internal arrays.
260 *
261 * @param start First index into {@link #mem} array.
262 */
263 private void setState(int start) {
264 mem[start] = arr[0];
265 mem[start + 1] = arr[1];
266 mem[start + 2] = arr[2];
267 mem[start + 3] = arr[3];
268 mem[start + 4] = arr[4];
269 mem[start + 5] = arr[5];
270 mem[start + 6] = arr[6];
271 mem[start + 7] = arr[7];
272 }
273}
Note: See TracBrowser for help on using the repository browser.