SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
LFSR113.java
1/*
2 * Class: LFSR113
3 * Description: 32-bit composite linear feedback shift register proposed by L'Ecuyer
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.rng;
26
27import java.io.Serializable;
28
47public class LFSR113 extends RandomStreamBase {
48
49 private static final long serialVersionUID = 70510L;
50 // La date de modification a l'envers, lire 10/05/2007
51
52 // generator constant: make sure that double values 0 and 1 never occur
53 private static final double NORM = 1.0 / 0x100000001L; // 2^32 + 1
54
55 // state variables:
56 private int z0;
57 private int z1;
58 private int z2;
59 private int z3;
60
61 // stream and substream variables :
62 private int[] stream;
63 private int[] substream;
64 private static int[] curr_stream = { 987654321, 987654321, 987654321, 987654321 };
65
69 public LFSR113() {
70 name = null;
71
72 stream = new int[4];
73 substream = new int[4];
74
75 for (int i = 0; i < 4; i++)
76 stream[i] = curr_stream[i];
77
79
80 // Les operations qui suivent permettent de faire sauter en avant
81 // de 2^90 iterations chacunes des composantes du generateur.
82 // L'etat interne apres le saut est cependant legerement different
83 // de celui apres 2^90 iterations puisqu'il ignore l'etat dans
84 // lequel se retrouvent les premiers bits de chaque composantes,
85 // puisqu'ils sont ignores dans la recurrence. L'etat redevient
86 // identique a ce que l'on aurait avec des iterations normales
87 // apres un appel a nextValue().
88
89 int z, b;
90
91 z = curr_stream[0] & -2;
92 b = (z << 6) ^ z;
93 z = (z) ^ (z << 2) ^ (z << 3) ^ (z << 10) ^ (z << 13) ^ (z << 16) ^ (z << 19) ^ (z << 22) ^ (z << 25) ^ (z << 27)
94 ^ (z << 28) ^ (b >>> 3) ^ (b >>> 4) ^ (b >>> 6) ^ (b >>> 9) ^ (b >>> 12) ^ (b >>> 15) ^ (b >>> 18)
95 ^ (b >>> 21);
96 curr_stream[0] = z;
97
98 z = curr_stream[1] & -8;
99 b = (z << 2) ^ z;
100 z = (b >>> 13) ^ (z << 16);
101 curr_stream[1] = z;
102
103 z = curr_stream[2] & -16;
104 b = (z << 13) ^ z;
105 z = (z << 2) ^ (z << 4) ^ (z << 10) ^ (z << 12) ^ (z << 13) ^ (z << 17) ^ (z << 25) ^ (b >>> 3) ^ (b >>> 11)
106 ^ (b >>> 15) ^ (b >>> 16) ^ (b >>> 24);
107 curr_stream[2] = z;
108
109 z = curr_stream[3] & -128;
110 b = (z << 3) ^ z;
111 z = (z << 9) ^ (z << 10) ^ (z << 11) ^ (z << 14) ^ (z << 16) ^ (z << 18) ^ (z << 23) ^ (z << 24) ^ (b >>> 1)
112 ^ (b >>> 2) ^ (b >>> 7) ^ (b >>> 9) ^ (b >>> 11) ^ (b >>> 14) ^ (b >>> 15) ^ (b >>> 16) ^ (b >>> 23)
113 ^ (b >>> 24);
114 curr_stream[3] = z;
115 }
116
122 public LFSR113(String name) {
123 this();
124 this.name = name;
125 }
126
138 public static void setPackageSeed(int[] seed) {
139 checkSeed(seed);
140 for (int i = 0; i < 4; i++)
141 curr_stream[i] = seed[i];
142 }
143
144 private static void checkSeed(int[] seed) {
145 if (seed.length < 4)
146 throw new IllegalArgumentException("Seed must contain 4 values");
147 if ((seed[0] >= 0 && seed[0] < 2) || (seed[1] >= 0 && seed[1] < 8) || (seed[2] >= 0 && seed[2] < 16)
148 || (seed[3] >= 0 && seed[3] < 128))
149 throw new IllegalArgumentException(
150 "The seed elements must be either negative or greater than 1, 7, 15 and 127 respectively");
151 }
152
164 public void setSeed(int[] seed) {
165 checkSeed(seed);
166 for (int i = 0; i < 4; i++)
167 stream[i] = seed[i];
169 }
170
177 public int[] getState() {
178 return new int[] { z0, z1, z2, z3 };
179 }
180
186 public LFSR113 clone() {
187 LFSR113 retour = null;
188 retour = (LFSR113) super.clone();
189 retour.stream = new int[4];
190 retour.substream = new int[4];
191 for (int i = 0; i < 4; i++) {
192 retour.substream[i] = substream[i];
193 retour.stream[i] = stream[i];
194 }
195 return retour;
196 }
197
198 public void resetStartStream() {
199 for (int i = 0; i < 4; i++)
200 substream[i] = stream[i];
202 }
203
204 public void resetStartSubstream() {
205 z0 = substream[0];
206 z1 = substream[1];
207 z2 = substream[2];
208 z3 = substream[3];
209 }
210 /*
211 * // La version de Mario: beaucoup plus lent que l'ancienne version: on garde
212 * // l'ancienne version. public void resetNextSubstream() { byte [] c0 = new
213 * byte[] {0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1,
214 * 0, 0, 1, 0, 0, 0, 1, 1}; byte [] c1 = new byte[] {1, 0, 0, 0, 1, 1, 1, 1, 1,
215 * 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0}; byte [] c2
216 * = new byte[] {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
217 * 0, 1, 0, 1, 0, 0, 0, 0, 0, 0}; byte [] c3 = new byte[] {1, 0, 0, 1, 1, 1, 1,
218 * 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int
219 * x0 = 0; int x1 = 0; int x2 = 0; int x3 = 0; resetStartSubstream(); for (int i
220 * = 0; i < 31; ++i) { if (c0[i] == 1) x0 ^= z0; if (c1[i] == 1) x1 ^= z1; if
221 * (c2[i] == 1) x2 ^= z2; if (c3[i] == 1) x3 ^= z3;
222 *
223 * int b; b = (((z0 << 6) ^ z0) >>> 13); z0 = (((z0 & -2) << 18) ^ b); b = (((z1
224 * << 2) ^ z1) >>> 27); z1 = (((z1 & -8) << 2) ^ b); b = (((z2 << 13) ^ z2) >>>
225 * 21); z2 = (((z2 & -16) << 7) ^ b); b = (((z3 << 3) ^ z3) >>> 12); z3 = (((z3
226 * & -128) << 13) ^ b); } substream[0] = x0; substream[1] = x1; substream[2] =
227 * x2; substream[3] = x3; resetStartSubstream(); }
228 */
229
230 public void resetNextSubstream() {
231 // Les operations qui suivent permettent de faire sauter en avant
232 // de 2^55 iterations chacunes des composantes du generateur.
233 // L'etat interne apres le saut est cependant legerement different
234 // de celui apres 2^55 iterations puisqu'il ignore l'etat dans
235 // lequel se retrouvent les premiers bits de chaque composantes,
236 // puisqu'ils sont ignores dans la recurrence. L'etat redevient
237 // identique a ce que l'on aurait avec des iterations normales
238 // apres un appel a nextValue().
239
240 int z, b;
241
242 z = substream[0] & -2;
243 b = (z << 6) ^ z;
244 z = (z) ^ (z << 3) ^ (z << 4) ^ (z << 6) ^ (z << 7) ^ (z << 8) ^ (z << 10) ^ (z << 11) ^ (z << 13) ^ (z << 14)
245 ^ (z << 16) ^ (z << 17) ^ (z << 18) ^ (z << 22) ^ (z << 24) ^ (z << 25) ^ (z << 26) ^ (z << 28) ^ (z << 30);
246 z ^= (b >>> 1) ^ (b >>> 3) ^ (b >>> 5) ^ (b >>> 6) ^ (b >>> 7) ^ (b >>> 9) ^ (b >>> 13) ^ (b >>> 14) ^ (b >>> 15)
247 ^ (b >>> 17) ^ (b >>> 18) ^ (b >>> 20) ^ (b >>> 21) ^ (b >>> 23) ^ (b >>> 24) ^ (b >>> 25) ^ (b >>> 26)
248 ^ (b >>> 27) ^ (b >>> 30);
249 substream[0] = z;
250
251 z = substream[1] & -8;
252 b = z ^ (z << 1);
253 b ^= (b << 2);
254 b ^= (b << 4);
255 b ^= (b << 8);
256
257 b <<= 8;
258 b ^= (z << 22) ^ (z << 25) ^ (z << 27);
259 if ((z & 0x80000000) != 0)
260 b ^= 0xABFFF000;
261 if ((z & 0x40000000) != 0)
262 b ^= 0x55FFF800;
263 z = b ^ (z >>> 7) ^ (z >>> 20) ^ (z >>> 21);
264 substream[1] = z;
265
266 z = substream[2] & -16;
267 b = (z << 13) ^ z;
268 z = (b >>> 3) ^ (b >>> 17) ^ (z << 10) ^ (z << 11) ^ (z << 25);
269 substream[2] = z;
270
271 z = substream[3] & -128;
272 b = (z << 3) ^ z;
273 z = (z << 14) ^ (z << 16) ^ (z << 20) ^ (b >>> 5) ^ (b >>> 9) ^ (b >>> 11);
274 substream[3] = z;
275
277 }
278
279 public String toString() {
280 if (name == null)
281 return "The state of the LFSR113 is: { " + z0 + ", " + z1 + ", " + z2 + ", " + z3 + " }";
282 else
283 return "The state of " + name + " is: { " + z0 + ", " + z1 + ", " + z2 + ", " + z3 + " }";
284 }
285
286 private long nextNumber() {
287 int b;
288 b = (((z0 << 6) ^ z0) >>> 13);
289 z0 = (((z0 & -2) << 18) ^ b);
290 b = (((z1 << 2) ^ z1) >>> 27);
291 z1 = (((z1 & -8) << 2) ^ b);
292 b = (((z2 << 13) ^ z2) >>> 21);
293 z2 = (((z2 & -16) << 7) ^ b);
294 b = (((z3 << 3) ^ z3) >>> 12);
295 z3 = (((z3 & -128) << 13) ^ b);
296
297 long r = (z0 ^ z1 ^ z2 ^ z3);
298
299 if (r <= 0)
300 r += 0x100000000L; // 2^32
301
302 return r;
303 }
304
305 protected double nextValue() {
306 // Make sure that double values 0 and 1 never occur
307 return nextNumber() * NORM;
308 }
309
310 public int nextInt(int i, int j) {
311 if (i > j)
312 throw new IllegalArgumentException(i + " is larger than " + j + ".");
313 long d = j - i + 1L;
314 long q = 0x100000000L / d;
315 long r = 0x100000000L % d;
316 long res;
317
318 do {
319 res = nextNumber();
320 } while (res >= 0x100000000L - r);
321
322 return (int) (res / q) + i;
323 }
324
325}
double nextValue()
This method should return the next random number (between 0 and 1) from the current stream.
Definition LFSR113.java:305
int[] getState()
Returns the current state of the stream, represented as an array of four integers.
Definition LFSR113.java:177
void resetStartSubstream()
Reinitializes the stream to the beginning of its current substream:
Definition LFSR113.java:204
void resetNextSubstream()
Reinitializes the stream to the beginning of its next substream:
Definition LFSR113.java:230
LFSR113 clone()
Clones the current generator and return its copy.
Definition LFSR113.java:186
String toString()
Returns a string containing the current state of this stream.
Definition LFSR113.java:279
void resetStartStream()
Reinitializes the stream to its initial state : and are set to .
Definition LFSR113.java:198
void setSeed(int[] seed)
This method is discouraged for normal use.
Definition LFSR113.java:164
static void setPackageSeed(int[] seed)
Sets the initial seed for the class LFSR113 to the four integers of the vector seed[0....
Definition LFSR113.java:138
LFSR113(String name)
Constructs a new stream with the identifier name.
Definition LFSR113.java:122
int nextInt(int i, int j)
Calls nextDouble once to create one integer between i and j.
Definition LFSR113.java:310
LFSR113()
Constructs a new stream.
Definition LFSR113.java:69
This class provides a convenient foundation on which RNGs can be built.