SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
CycleBasedLFSR.java
1/*
2 * Class: CycleBasedLFSR
3 * Description:
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 * SSJ is free software: you can redistribute it and/or modify it under
12 * the terms of the GNU General Public License (GPL) as published by the
13 * Free Software Foundation, either version 3 of the License, or
14 * any later version.
15
16 * SSJ is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20
21 * A copy of the GNU General Public License is available at
22 <a href="http://www.gnu.org/licenses">GPL licence site</a>.
23 */
24package umontreal.ssj.hups;
25
26import umontreal.ssj.util.PrintfFormat;
27import cern.colt.list.*;
28import java.io.*;
29
75 private int J = 1; // Nombre de polynomes a combiner
76 private int k1 = 0; // Degre du premier polynome.
77 private int k2 = 0; // Degre du second polynome.
78 private int step1; // Nombre de repetition de la recurence.
79 private int step2;
80 private int nbcoeff1; // Nombre de coefficient du polynome.
81 private int nbcoeff2;
82 private int[] nocoeff1; // Liste des coefficients non nulls.
83 private int[] nocoeff2;
84 private int[] posa1; // Position des bits de x1 des coefficients a1.
85 private int[] posa2;
86 private int[] shifta1; // 1 << posa1
87 private int[] shifta2;
88 private int x1 = 0; // Memorise les x[n-i] de la recurence.
89 private int x2 = 0;
90 private int state = 0; // Etat present du generateur.
91 private int value = 0; // = (x1 ^ x2) & maskX
92 private int maskX; // Recupere les bits 0 a k-1 de x1 ou x2. k = k1+k2
93 private int maskX1; // Recupere les bits 0 a k1-1 de x1
94 private int maskX2; // Recupere les bits 0 a k2-1 de x2
95 private int maskX1Shift; // Recupere les bits k2 a k-1 de x1
96
107 public CycleBasedLFSR(int step1, int nbcoeff1, int[] nocoeff1) {
108 this.step1 = step1;
109 this.nbcoeff1 = nbcoeff1 - 1;
110 this.nocoeff1 = nocoeff1;
111 J = 1;
112 init();
113 }
114
120 public CycleBasedLFSR(int step1, int step2, int nbcoeff1, int nbcoeff2, int[] nocoeff1, int[] nocoeff2) {
121 this.step1 = step1;
122 this.step2 = step2;
123 this.nbcoeff1 = nbcoeff1 - 1;
124 this.nbcoeff2 = nbcoeff2 - 1;
125 this.nocoeff1 = nocoeff1;
126 this.nocoeff2 = nocoeff2;
127 J = 2;
128 init();
129 }
130
170 public CycleBasedLFSR(String filename, int no) {
171 readFile(filename, no);
172 init();
173 }
174
175 // Initialise les variables, et appelle fillCyclesLFSR()
176 private void init() {
177 k1 = nocoeff1[0];
178 posa1 = new int[nbcoeff1];
179 shifta1 = new int[nbcoeff1];
180 for (int i = 0; i < nbcoeff1; ++i) {
181 posa1[i] = k1 - nocoeff1[i + 1] - 1;
182 shifta1[i] = 1 << posa1[i];
183 }
184
185 if (J == 2) {
186 k2 = nocoeff2[0];
187 posa2 = new int[nbcoeff2];
188 shifta2 = new int[nbcoeff2];
189 for (int i = 0; i < nbcoeff2; ++i) {
190 posa2[i] = k2 - nocoeff2[i + 1] - 1;
191 shifta2[i] = 1 << posa2[i];
192 }
193 }
194
195 if (k1 + k2 > 31) {
196 System.err.println("The degree of the combined polynomials must be < 31");
197 System.err.println("k1 = " + k1 + " k2 = " + k2);
198 System.exit(1);
199 }
200
201 maskX1 = (1 << k1) - 1;
202 maskX2 = (1 << k2) - 1;
203 maskX1Shift = maskX1 << k2;
204 maskX = (1 << (k1 + k2)) - 1;
205
206 numBits = k1 + k2;
207 normFactor = 1.0 / (1L << numBits);
208
209 fillCyclesLFSR();
210 }
211
216 public String toString() {
217 int i;
218 String s = "CycleBasedLFSR:" + PrintfFormat.NEWLINE + "First Polynome: Step: " + step1 + " Coefficients: ";
219 for (i = 0; i < nbcoeff1; i++) {
220 s += nocoeff1[i] + ", ";
221 }
222 s += nocoeff1[i];
223
224 if (J == 1)
225 return s;
226
227 s += PrintfFormat.NEWLINE + "Second Polynome: Step: " + step2 + " Coefficients: ";
228 for (i = 0; i < nbcoeff2; i++) {
229 s += nocoeff2[i] + ", ";
230 }
231 s += nocoeff2[i];
232 return s;
233 }
234
235 // Produit l'etat suivant du generateur
236 // x1[n] = a1[1]*x1[n-1] + a1[2]*x1[n-2] + ... + a1[k1]*x1[n-k1]
237 // repete step1 fois
238 // x2[n] = a2[1]*x2[n-1] + a2[2]*x2[n-2] + ... + a2[k2]*x2[n-k2]
239 // repete step2 fois
240 // x1[n-1], x1[n-2],...,x1[n-k1] sont les bits 0, 1,..., k1-1, de l'entier x1
241 // La position des a1 non nuls est dans le tableau posa1 de taille nbcoeff1
242 // shifta1[i] = 1 << posa1[i]
243 // value = (x1 ^ x2) & maskX
244 // state = x1x2
245 private void nextState() {
246 int i;
247 int b = 0;
248 int s = 0;
249 // Recurence pour le premier polynome.
250 for (s = 0; s < step1; s++) {
251 b = 0;
252 for (i = 0; i < nbcoeff1; i++) {
253 b ^= (x1 & shifta1[i]) >> posa1[i];
254 }
255 x1 = x1 << 1;
256 x1 |= b;
257 }
258
259 if (J == 1) {
260 state = x1 & maskX1;
261 value = state;
262 return;
263 }
264
265 // Recurence pour le second polynome.
266 for (s = 0; s < step2; s++) {
267 b = 0;
268 for (i = 0; i < nbcoeff2; i++) {
269 b ^= (x2 & shifta2[i]) >> posa2[i];
270 }
271 x2 = x2 << 1;
272 x2 |= b;
273 }
274
275 // value est ce qui est memorise dans les cycles.
276 value = (x1 ^ x2) & maskX;
277
278 // L'etat du generateur est constitue de l'etat des recurences x1 et x2.
279 // L'etat de la recurence x1 est un nombre de k1 bits situe dans les
280 // bits k2 a k-1. k = k1 + k2.
281 // L'etat de la recurence x2 est un nombre de k2 bits situe dans les
282 // bits k1 a k-1.
283 // On forme a partir de ses deux etats un nombre de k bits.
284 // Les k1 bits de x1 a gauche, et les k2 bits de x2 a droite.
285 // state est utilise pour trouver les cycles.
286 // On ne peut pas utiliser value pour trouver les cycles, puisque qu'on
287 // ne peut pas retrouver x1 et x2 a partir de x1 ^ x2.
288 state = (x1 & maskX1Shift) | ((x2 >>> k1) & maskX2);
289 }
290
291 // A partir de l'etat x1x2 on remplit les nombres x1 et x2.
292 private void validateState(int x1x2) {
293 int b = 0;
294 int s = 0;
295 int i;
296
297 // L'etat de x1 est dans la partie gauche de x1x2
298 x1 = x1x2 >> k2;
299 // On ramene les k1 bits a la position k2 a k-1
300 // Les bits de k a 31 de x1, ne sont jamais utilises.
301 for (s = 0; s < k2; s++) {
302 b = 0;
303 for (i = 0; i < nbcoeff1; i++) {
304 b ^= (x1 & shifta1[i]) >> posa1[i];
305 }
306 x1 = x1 << 1;
307 x1 |= b;
308 }
309
310 if (J == 1) {
311 state = x1 & maskX1;
312 value = state;
313 return;
314 }
315
316 x2 = x1x2 & maskX2;
317 // On ramene les k2 bits a la position k1 a k-1
318 for (s = 0; s < k1; s++) {
319 b = 0;
320 for (i = 0; i < nbcoeff2; i++) {
321 b ^= (x2 & shifta2[i]) >> posa2[i];
322 }
323 x2 = x2 << 1;
324 x2 |= b;
325 }
326 // value est ce qui est memorise dans les cycles.
327 value = (x1 ^ x2) & maskX;
328 }
329
330 // Remplit les cycles avec le generateur LFSR.
331 // Le nombre de valeurs dans l'ensemble des cycles est de 2^(k1+k2).
332 // Cette methode fonctionne pour tous les polynomes, meme ceux dont
333 // la periode n'est pas maximale.
334 private void fillCyclesLFSR() {
335 int n = 1 << (k1 + k2); // Nombre de points dans l'ensemble.
336 IntArrayList c; // Array used to store the current cycle.
337 int i;
338 boolean stateVisited[] = new boolean[n];
339
340 // Indicates which states have been visited so far.
341 for (i = 0; i < n; i++)
342 stateVisited[i] = false;
343 int startState = 0; // First state of the cycle currently considered.
344 numPoints = 0;
345 while (startState < n) {
346 stateVisited[startState] = true;
347 c = new IntArrayList();
348 c.add(value);
349 nextState();
350 while (state != startState) {
351 stateVisited[state] = true;
352 c.add(value);
353 nextState();
354 }
355 addCycle(c);
356// System.out.println("Size of Cycle: " + c.size());
357 for (i = startState + 1; i < n; i++)
358 if (stateVisited[i] == false)
359 break;
360 startState = i;
361 validateState(i);
362 }
363 }
364
365 // Lit le fichier contenant les polynomes pour plusieurs generateurs.
366 // no indique le choix du generateur dans le fichier.
367 private void readFile(String fileName, int no) {
368 BufferedReader input = null;
369 try {
370 if ((new File(fileName)).exists()) {
371 input = new BufferedReader(new FileReader(fileName));
372 } else {
373 DataInputStream dataInput;
374 dataInput = new DataInputStream(
375 F2wStructure.class.getClassLoader().getResourceAsStream("umontreal/ssj/hups/dataLFSR/" + fileName));
376 input = new BufferedReader(new InputStreamReader(dataInput));
377 }
378 } catch (FileNotFoundException e) {
379 System.err.println("File " + fileName + " not found" + PrintfFormat.NEWLINE);
380 System.exit(1);
381 }
382
383 // La numerotation des generateurs debute a 1
384 if (no < 1)
385 no = 1;
386
387 int[] numbers;
388
389 // La premiere ligne valide est le nombre de polynomes
390 String line = readOneLine(input);
391 numbers = lineToNumbers(line);
392 J = numbers[0];
393 if (J != 1 && J != 2) {
394 System.err.println("Error: J = " + J + PrintfFormat.NEWLINE
395 + "CycleBasedLFSR works only for the cases of one or two polynomials");
396 System.exit(1);
397 }
398
399 // Nombre ne lignes qu'il faut sauter avant de lire les polynomes.
400 int nbLines = (J + 1) * (no - 1);
401
402 // On saute nbLines valides
403 for (int i = 0; i < nbLines; i++) {
404 line = readOneLine(input);
405 if (line == null) {
406 // Il n'y a aucune ligne qui correspond a no.
407 System.err.println("Error CycleBasedLFSR:" + PrintfFormat.NEWLINE + " no data in file " + fileName + " for "
408 + no + "-th LFSR");
409 System.exit(1);
410 }
411 }
412
413 // Lecture des valeurs des J steps.
414 line = readOneLine(input);
415 if (line == null) {
416 // Il n'y a aucune ligne qui correspond a no.
417 System.err.println("Error CycleBasedLFSR:" + PrintfFormat.NEWLINE + " no data in file " + fileName + " for "
418 + no + "-th LFSR");
419 System.exit(1);
420 }
421 numbers = lineToNumbers(line);
422
423 // Lecture des J polynomes.
424 if (J == 1) {
425 step1 = numbers[0];
426 line = readOneLine(input);
427 nocoeff1 = lineToNumbers(line);
428 nbcoeff1 = nocoeff1.length - 1;
429 } else if (J == 2) {
430 step1 = numbers[0];
431 step2 = numbers[1];
432 line = readOneLine(input);
433 nocoeff1 = lineToNumbers(line);
434 nbcoeff1 = nocoeff1.length - 1;
435 line = readOneLine(input);
436 nocoeff2 = lineToNumbers(line);
437 nbcoeff2 = nocoeff2.length - 1;
438 }
439 }
440
441 // Lit une ligne du fichier en ignorant les lignes blanches
442 // et les commentaires.
443 private String readOneLine(BufferedReader input) {
444 String line;
445
446 try {
447 while (true) {
448 line = input.readLine();
449 if (line == null)
450 return null;
451 line = line.trim();
452
453 // On saute les lignes blanches.
454 if (line.length() == 0) {
455 line = input.readLine();
456 continue;
457 }
458
459 // On saute les lignes de commentaires
460 if (line.charAt(0) == '#') {
461 line = input.readLine();
462 continue;
463 }
464
465 // On elimine les commentaires a la fin de la ligne
466 int index = line.indexOf('#');
467 if (index >= 0) {
468 line = line.substring(0, index).trim();
469 }
470 return line;
471 }
472 } catch (IOException e) {
473 System.err.println(e);
474 System.exit(1);
475 }
476 return null;
477 }
478
479 // Convertit la String line en tableau d'entiers
480 private int[] lineToNumbers(String line) {
481 int[] numbers;
482 String[] snumbers;
483
484 // On separent les nombres.
485 snumbers = line.split("\\s++");
486
487 int nb = snumbers.length;
488 numbers = new int[nb];
489 for (int i = 0; i < nb; i++) {
490 numbers[i] = Integer.valueOf(snumbers[i]).intValue();
491 }
492 return numbers;
493 }
494
495}
CycleBasedLFSR(String filename, int no)
Constructs a point set after reading its parameters from file filename; the parameters associated wit...
CycleBasedLFSR(int step1, int step2, int nbcoeff1, int nbcoeff2, int[] nocoeff1, int[] nocoeff2)
Constructs a point set based on a combination of two polynomials in base 2 with points.
String toString()
This method returns a string containing the polynomials and the stepping parameters.
CycleBasedLFSR(int step1, int nbcoeff1, int[] nocoeff1)
Similar to CycleBasedPointSet, except that the successive values in the cycles are stored as integers...
void addCycle(AbstractList c)
Adds the cycle c to the list of all cycles.
int numPoints
Number of points.
static final String NEWLINE
End-of-line symbol or line separator.