+++ /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