/** * BlackHole Source File * * GNU Copyright (C) 2008 Gaspar Sinai gaspar(at)adys.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * dated June 1991. See file COPYYING for details. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package sinai.gaspar.blackhole; import java.awt.Panel; /** * A Prime stack that will rotate. * This class is used in BoardPanel for the applet version. * * @author Gaspar Sinai * @version 2008-04-30 */ public class PrimeStack { private int cells = 2; private boolean primeList[]; private long current; private IChangeListener changeListener = null; /** * @param cells are cells in a row/column. */ public PrimeStack (int cells) { this.cells = cells; this.primeList = new boolean[cells*cells]; long start = 1L; markPrimes (primeList, start); current = primeList.length + start; } public void setChangeListener (IChangeListener changeListener) { this.changeListener = changeListener; } public synchronized void setStart (long start) { markPrimes (primeList, start); current = primeList.length + start; if (changeListener != null) changeListener.changed (); } /** * @return the first number in the sequence. */ public synchronized long getStart () { return current - (long) primeList.length; } /** * @return true if number in our sequence at index is prime. * The sequence starts with getStart() */ public boolean isPrimeAt (int index) { if (index < 0 || index > primeList.length) return false; return primeList[index]; } /** * Shift the whole map. */ public synchronized void forward () { for (int i=1; i0; i--) { primeList[i] = primeList[i-1]; } current--; primeList[0] = isPrime (current-primeList.length); if (changeListener != null) changeListener.changed (); } // The first primes, 2 excluded private static final long preTest[]; static { // 5000th prime is 48619 (not including 2) // 48619 * 48619 = 2363807161 // This is the largest number that can be tested with the array. preTest = new long[5000]; // 40 kbytes int index =0; long number = 3; while (index < preTest.length) { // This would require sqrt (number) steps, so the array can // built while isPrime is using it. if (isPrime (number)) { preTest[index++] = number; } number++; } } /** * @param number is the number to test * @return true if number is a prime. */ public static boolean isPrime (long number) { if (number < 2) return false; if (number < 4) return true; if (number % 2 == 0) return false; long divisor = 1; long limit = number; int index = 0; int len = preTest.length; // Go through a pre-set of prime numbers first. while (limit > divisor && index < len) { divisor = preTest [index++]; // if divisor is 0, internal error. if ((number % divisor) == 0) return false; limit = number / divisor; } divisor = divisor + 2; while (limit > divisor) { if ((number % divisor) == 0) return false; limit = number / divisor; divisor = divisor + 2; } return true; } /** * Mark prime number in the array, where array[0] represents * start. */ public static void markPrimes (boolean array[], long start) { // This method will be faster. 100 is experimental. if (start / array.length > 100) { for (long i=0; i 1) ; } long arrayLength = array.length; long limitCheck = (start + arrayLength) / 41; // 41 is experimental for (long i=2; i= 0 && index < arrayLength) { if (array[(int)index] == false) continue; } else { if (i= 0) { array[(int) (mark-start)] = false; } mark += i; } } } }