--- /dev/null
+// Primes.java\r
+\r
+/** Copyright 1998\r
+ * Roedy Green\r
+ * Canadian Mind Products\r
+ * 5317 Barker Avenue\r
+ * Burnaby, BC Canada V5H 2N6\r
+ * tel: (604) 435-3016\r
+ * mailto:roedy@mindprod.com\r
+ * http://mindprod.com\r
+ */\r
+// May be freely distributed for any purpose but military\r
+\r
+import java.util.BitSet;\r
+\r
+/**\r
+ * @author Roedy Green\r
+ * @version 1.10 1998 November 10\r
+ * Calculate primes using Eratostheses Sieve.\r
+ * Tell if a given number is prime.\r
+ * Find a prime just below a given number.\r
+ * Find a prime just above a given number.\r
+ */\r
+ \r
+/* \r
+ * version 1.1 1998 November 10 - new address and phone. \r
+ */\r
+class Primes\r
+ {\r
+\r
+ /**\r
+ * constructors\r
+ */\r
+ Primes()\r
+ {\r
+ ensureCapacity(1000);\r
+ }\r
+\r
+ /**\r
+ * @param capacity - largest number you will be asking if prime.\r
+ * If give too small a number, it will automatically grow by\r
+ * recomputing the sieve array.\r
+ */\r
+ Primes (int capacity)\r
+ {\r
+ ensureCapacity(capacity);\r
+ }\r
+\r
+ /**\r
+ * @param candidate - is this a prime?\r
+ */\r
+ public boolean isPrime(int candidate)\r
+ {\r
+ ensureCapacity(candidate);\r
+ if (candidate < 3) return candidate != 0;\r
+ if (candidate % 2 == 0 ) return false;\r
+ return !b.get(candidate/2);\r
+ }\r
+\r
+ /**\r
+ * @return first prime higher than candidate\r
+ */\r
+ public int above(int candidate)\r
+ {\r
+ do\r
+ {\r
+ // see what we can find in the existing sieve\r
+ for (int i=candidate+1; i<= sieveCapacity; i++)\r
+ {\r
+ if (isPrime(i)) return i;\r
+ }\r
+ // Keep building ever bigger sieves till we succeed.\r
+ // The next prime P' is between P+2 and P^2 - 2.\r
+ // However that is a rather pessimistic upper bound.\r
+ // Ideally some theorem would tell us how big we need to build\r
+ // to find one.\r
+ ensureCapacity(Math.max(candidate*2, sieveCapacity*2));\r
+ } // end do\r
+ while (true);\r
+ } // end above\r
+\r
+ /**\r
+ * @param return first prime less than candidate\r
+ */\r
+ public int below (int candidate)\r
+ {\r
+ for (candidate--; candidate > 0; candidate--)\r
+ {\r
+ if (isPrime(candidate)) return candidate;\r
+ }\r
+ // candidate was 1 or 0 or -ve\r
+ return 0;\r
+ }\r
+\r
+ /**\r
+ * calc all primes in the range 1..n,\r
+ * not the first n primes.\r
+ * @param n, highest candidate, not necessarily prime.\r
+ * @return list of primes 1..n in an array\r
+ */\r
+ public final int[] getPrimes(int n)\r
+ {\r
+ // calculate the primes\r
+ ensureCapacity(n);\r
+\r
+ // pass 1: count primes\r
+ int countPrimes = 0;\r
+ for (int i = 0; i <= n; i++)\r
+ {\r
+ if (isPrime(i)) countPrimes++;\r
+ }\r
+\r
+ // pass 2: construct array of primes\r
+ int [] primes = new int[countPrimes];\r
+ countPrimes = 0;\r
+ for (int i = 0; i <= n; i++)\r
+ {\r
+ if (isPrime(i)) primes[countPrimes++] = i;\r
+ }\r
+ return primes;\r
+ } // end getPrimes\r
+\r
+ /**\r
+ * calculate the sieve, bit map of all primes 0..n\r
+ * @param n highest number evalutated by the sieve, not necessarily prime.\r
+ */\r
+ private final void sieve ( int n )\r
+ {\r
+ // Presume BitSet b set is big enough for our purposes.\r
+ // Presume all even numbers are already marked composite, effectively.\r
+ // Presume all odd numbers are already marked prime (0 in bit map).\r
+ int last = (int)(Math.sqrt(n))+1;\r
+ for (int candidate = 3; candidate <= last; candidate += 2)\r
+ {\r
+ // only look at odd numbers\r
+ if (!b.get(candidate/2) /* if candidate is prime */)\r
+ {\r
+ // Our candidate is prime.\r
+ // Only bother to mark multiples of primes. Others already done.\r
+ // no need to mark even multiples, already done\r
+ int incr = candidate*2;\r
+ for ( int multiple = candidate + incr; multiple < n; multiple += incr)\r
+ {\r
+ b.set(multiple/2); // mark multiple as composite\r
+ } // end for multiple\r
+ } // end if\r
+ } // end for candidate\r
+ // at this point our sieve b is correct, except for 0..2\r
+ } // end sieve\r
+\r
+ /**\r
+ * Ensure have a sieve to tackle primes as big as n.\r
+ * If we don't allocate a sieve big enough and calculate it.\r
+ * @param n - ensure sieve big enough to evaluate n for primality.\r
+ */\r
+ private void ensureCapacity (int n)\r
+ {\r
+ if ( n > sieveCapacity )\r
+ {\r
+ b = new BitSet((n+1)/2);\r
+ // starts out all 0, presume all numbers prime\r
+ sieveCapacity = n;\r
+ sieve(n);\r
+ }\r
+ // otherwise existing sieve is fine\r
+ } // end ensureCapacity\r
+\r
+ private int sieveCapacity;\r
+ // biggest number we have computed in our sieve.\r
+ // our BitSet array is indexed 0..N (odd only)\r
+\r
+ private BitSet b; /* true for each odd number if is composite */\r
+\r
+ /**\r
+ * Demonstrate and test the methods\r
+ */\r
+ public static void main (String[] args)\r
+ {\r
+ // print primes 1..101\r
+ Primes calc = new Primes(106);\r
+ int[] primes = calc.getPrimes(101);\r
+ for (int i=0; i<primes.length; i++)\r
+ {\r
+ System.out.println(primes[i]);\r
+ }\r
+\r
+ // demonstrate isPrime, above, below\r
+ System.out.println(calc.isPrime(149));\r
+ System.out.println(calc.below(149));\r
+ System.out.println(calc.above(149));\r
+\r
+ // print all the primes just greater than powers of 2\r
+ calc = new Primes(10000000);\r
+ for (int pow=8; pow < 10000000; pow*=2)\r
+ System.out.println(calc.above(pow));\r
+\r
+ // Validate that isPrime works by comparing it with brute force\r
+ for (int i=3; i<=151; i++)\r
+ {\r
+ boolean prime = true;\r
+ for (int j=2; j<i; j++)\r
+ {\r
+ if (i % j == 0 )\r
+ {\r
+ prime = false;\r
+ break;\r
+ }\r
+ } // end for j\r
+ if ( calc.isPrime(i) != prime ) System.out.println(i + " oops");\r
+ } // end for i\r
+\r
+ } // end main\r
+} // end Primes\r