mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			214 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			214 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Java
		
	
	
	
| // Primes.java
 | |
| 
 | |
| /** Copyright 1998
 | |
|  * Roedy Green
 | |
|  * Canadian Mind Products
 | |
|  * 5317 Barker Avenue
 | |
|  * Burnaby, BC Canada V5H 2N6
 | |
|  * tel: (604) 435-3016
 | |
|  * 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.  
 | |
|  */
 | |
| class Primes
 | |
|     {
 | |
| 
 | |
|     /**
 | |
|       * constructors
 | |
|       */
 | |
|     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.
 | |
|       */
 | |
|     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
 | |
| 
 | |
|     /**
 | |
|       * @param 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<primes.length; i++)
 | |
|             {
 | |
|             System.out.println(primes[i]);
 | |
|             }
 | |
| 
 | |
|         // demonstrate isPrime, above, below
 | |
|         System.out.println(calc.isPrime(149));
 | |
|         System.out.println(calc.below(149));
 | |
|         System.out.println(calc.above(149));
 | |
| 
 | |
|         // print all the primes just greater than powers of 2
 | |
|         calc = new Primes(10000000);
 | |
|         for (int pow=8; pow < 10000000; pow*=2)
 | |
|             System.out.println(calc.above(pow));
 | |
| 
 | |
|         // Validate that isPrime works by comparing it with brute force
 | |
|         for (int i=3; i<=151; i++)
 | |
|             {
 | |
|             boolean prime = true;
 | |
|             for (int j=2; j<i; j++)
 | |
|                 {
 | |
|                 if (i % j == 0 )
 | |
|                     {
 | |
|                     prime = false;
 | |
|                     break;
 | |
|                     }
 | |
|                 } // end for j
 | |
|             if ( calc.isPrime(i) != prime ) System.out.println(i + " oops");
 | |
|             } // end for i
 | |
| 
 | |
|         } // end main
 | |
| } // end Primes
 |