|
|
@@ -0,0 +1,115 @@
|
|
|
+/*
|
|
|
+ * I-BS.pl PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
|
+ * Copyright (c) 2012, I-BS.pl and/or its affiliates. All rights reserved.
|
|
|
+ */
|
|
|
+package net.ranides.assira.math;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Random;
|
|
|
+import static org.junit.Assert.*;
|
|
|
+import org.junit.Ignore;
|
|
|
+import org.junit.Test;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Uwaga - test musi mieć dostępne 512 MB pamięci. Patrz: "pom.xml"
|
|
|
+ * @author ranides
|
|
|
+ */
|
|
|
+@SuppressWarnings("PMD.SystemPrintln")
|
|
|
+public class LFSRTest {
|
|
|
+
|
|
|
+ private static final int MAX_CYCLE = 64 * 1000 * 1000;
|
|
|
+
|
|
|
+ private BS buffer;
|
|
|
+
|
|
|
+ public LFSRTest() {
|
|
|
+ }
|
|
|
+
|
|
|
+ private BS resetBuffer() {
|
|
|
+ if( buffer == null) {
|
|
|
+ buffer = new BS();
|
|
|
+ }
|
|
|
+ return buffer;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int testCycle(Random generator, int seed) {
|
|
|
+ // Intel Core i3 540 @ 3.07GHz
|
|
|
+ // Czas przeszukiwania 320 mln / 164 s
|
|
|
+ //
|
|
|
+ // czyli 1 seed na około 40 minut
|
|
|
+ resetBuffer();
|
|
|
+
|
|
|
+ buffer.clear(true);
|
|
|
+ for (int i = 0; i<MAX_CYCLE; i++) {
|
|
|
+ if( buffer.exists( generator.nextInt() ) ) {
|
|
|
+ System.out.printf("cycle length for seed %d = %d.\n", seed, i);
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ buffer.clear(false);
|
|
|
+ for (int i = 0; i<MAX_CYCLE; i++) {
|
|
|
+ if( buffer.exists( generator.nextInt() ) ) {
|
|
|
+ System.out.printf("cycle length for seed %d = %d.\n", seed, i);
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ System.out.printf("cycle length for seed %d > %d.\n", seed, MAX_CYCLE);
|
|
|
+ return MAX_CYCLE;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Ignore("manual slow")
|
|
|
+ @Test
|
|
|
+ public void testCycles() {
|
|
|
+
|
|
|
+ assertEquals( 115135, testCycle(new Random(0), 0) );
|
|
|
+ assertEquals( 94482, testCycle(new Random(17), 17) );
|
|
|
+ assertEquals( 78192, testCycle(new Random(32), 32) );
|
|
|
+ assertEquals( 192385, testCycle(new Random(40), 40) );
|
|
|
+ assertEquals( 66466, testCycle(new Random(170), 170) );
|
|
|
+ assertEquals( 112008, testCycle(new Random(197), 197) );
|
|
|
+
|
|
|
+ assertEquals( 1, testCycle(new LFSR(0), 0) );
|
|
|
+ assertEquals( MAX_CYCLE, testCycle(new LFSR(17), 17) );
|
|
|
+ assertEquals( MAX_CYCLE, testCycle(new LFSR(32), 32) );
|
|
|
+ assertEquals( MAX_CYCLE, testCycle(new LFSR(40), 40) );
|
|
|
+ assertEquals( MAX_CYCLE, testCycle(new LFSR(170), 170) );
|
|
|
+ assertEquals( MAX_CYCLE, testCycle(new LFSR(197), 197) );
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class BS {
|
|
|
+
|
|
|
+ private char words[] = new char[128 * 1024 * 1024];
|
|
|
+ private boolean pmode;
|
|
|
+
|
|
|
+ public boolean exists(int value) {
|
|
|
+ return pmode ? existsP(value) : existsN(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean existsP(int value) {
|
|
|
+ if(value < 0) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ int offset = value / 16;
|
|
|
+ int mask = 1 << (value % 16);
|
|
|
+ boolean exists = (mask == (words[offset] & mask));
|
|
|
+ words[offset] |= mask;
|
|
|
+ return exists;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean existsN(int value) {
|
|
|
+ if(value > 0) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ return existsP(-value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void clear(boolean pmode) {
|
|
|
+ Arrays.fill(words, 0, words.length, '\0');
|
|
|
+ this.pmode = pmode;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|