/* Taken from the javaxdelta project. */ /* Primes 1.1 calculates the primes 1..N, tells you if N is prime, computes the prime just below or above N. It is useful in computing optimal HashTable sizes. Java source included. Copyright 1998 by Roedy Green of Canadian Mind Products. May be freely distbributed for any purpose but military. */ // Primes.java package org.thdl.util.javaxdelta; /** Copyright 1998 * Roedy Green * Canadian Mind Products * #208 - 525 Ninth Street * New Westminster, BC Canada V3M 5T9 * tel: (604) 777-1804 * mailto:roedy@mindprod.com * http://mindprod.com */ // May be freely distributed for any purpose but military import java.util.BitSet; /** * @author Roedy Green * @version 1.10 1998 November 10 * Calculate primes using Eratostheses Sieve. * Tell if a given number is prime. * Find a prime just below a given number. * Find a prime just above a given number. */ /* * version 1.1 1998 November 10 - new address and phone. */ public class Primes { private static final String EmbeddedCopyright = "Copyright 1997-2000 Roedy Green, Canadian Mind Products, http://mindprod.com"; /** * constructors */ public Primes() { ensureCapacity(1000); } /** * @param capacity - largest number you will be asking if prime. * If give too small a number, it will automatically grow by * recomputing the sieve array. */ public Primes (int capacity) { ensureCapacity(capacity); } /** * @param candidate - is this a prime? */ public boolean isPrime(int candidate) { ensureCapacity(candidate); if (candidate < 3) return candidate != 0; if (candidate % 2 == 0 ) return false; return !b.get(candidate/2); } /** * @return first prime higher than candidate */ public int above(int candidate) { do { // see what we can find in the existing sieve for (int i=candidate+1; i<= sieveCapacity; i++) { if (isPrime(i)) return i; } // Keep building ever bigger sieves till we succeed. // The next prime P' is between P+2 and P^2 - 2. // However that is a rather pessimistic upper bound. // Ideally some theorem would tell us how big we need to build // to find one. ensureCapacity(Math.max(candidate*2, sieveCapacity*2)); } // end do while (true); } // end above /** * @return first prime less than candidate */ public int below (int candidate) { for (candidate--; candidate > 0; candidate--) { if (isPrime(candidate)) return candidate; } // candidate was 1 or 0 or -ve return 0; } /** * calc all primes in the range 1..n, * not the first n primes. * @param n highest candidate, not necessarily prime. * @return list of primes 1..n in an array */ public final int[] getPrimes(int n) { // calculate the primes ensureCapacity(n); // pass 1: count primes int countPrimes = 0; for (int i = 0; i <= n; i++) { if (isPrime(i)) countPrimes++; } // pass 2: construct array of primes int [] primes = new int[countPrimes]; countPrimes = 0; for (int i = 0; i <= n; i++) { if (isPrime(i)) primes[countPrimes++] = i; } return primes; } // end getPrimes /** * calculate the sieve, bit map of all primes 0..n * @param n highest number evalutated by the sieve, not necessarily prime. */ private final void sieve ( int n ) { // Presume BitSet b set is big enough for our purposes. // Presume all even numbers are already marked composite, effectively. // Presume all odd numbers are already marked prime (0 in bit map). int last = (int)(Math.sqrt(n))+1; for (int candidate = 3; candidate <= last; candidate += 2) { // only look at odd numbers if (!b.get(candidate/2) /* if candidate is prime */) { // Our candidate is prime. // Only bother to mark multiples of primes. Others already done. // no need to mark even multiples, already done int incr = candidate*2; for ( int multiple = candidate + incr; multiple < n; multiple += incr) { b.set(multiple/2); // mark multiple as composite } // end for multiple } // end if } // end for candidate // at this point our sieve b is correct, except for 0..2 } // end sieve /** * Ensure have a sieve to tackle primes as big as n. * If we don't allocate a sieve big enough and calculate it. * @param n - ensure sieve big enough to evaluate n for primality. */ private void ensureCapacity (int n) { if ( n > sieveCapacity ) { b = new BitSet((n+1)/2); // starts out all 0, presume all numbers prime sieveCapacity = n; sieve(n); } // otherwise existing sieve is fine } // end ensureCapacity private int sieveCapacity; // biggest number we have computed in our sieve. // our BitSet array is indexed 0..N (odd only) private BitSet b; /* true for each odd number if is composite */ /** * Demonstrate and test the methods */ public static void main (String[] args) { // print primes 1..101 Primes calc = new Primes(106); int[] primes = calc.getPrimes(101); for (int i=0; i