/* * Copyright(c)2002 Forward Computing and Control Pty. Ltd. * ACN 003 669 994, NSW, Australia All rights Reserved * * Written by Dr. M.P. Ford */ import au.com.forward.threads.*; import java.io.IOException; import java.math.BigInteger; import java.util.Date; import java.text.SimpleDateFormat; /** * finds a prime using Java's BigInteger.isProbablePrime() * * @author matthew ford * @created 5 May 2002 */ class TestForPrime extends Thread { /** * Increment by 2 to skip even numbers */ private static BigInteger two = new BigInteger("2"); /** * The number to test */ private BigInteger number; /** * The certainty level = 2^-certainty */ private int certainty; /** * How many numbers to test starting from the first one */ private int numberToTest; /** * Constructor for TestForPrime * * @param name the name of this thread * @param rangeStart the starting number to test * @param numberToTest how many numbers this thread will test starting from the rangeStart * @param certainty the certainty parameter */ TestForPrime(String name, BigInteger rangeStart, int numberToTest, int certainty) { super(name); if (rangeStart.signum() != 1) { throw new IllegalArgumentException(rangeStart.toString() + " is not positive."); } if (rangeStart.mod(two).equals(BigInteger.ZERO)) { // make it odd rangeStart = rangeStart.add(BigInteger.ONE); } number = rangeStart; if (numberToTest < 1) { throw new IllegalArgumentException("Must test at least one number"); } this.numberToTest = numberToTest; if (certainty < 1) { throw new IllegalArgumentException("Certainty argument must be >= 1"); } this.certainty = certainty; } /** * The TestForPrime run() method * Loops testing each number in the range for primality. */ public void run() { try { System.out.println("TestForPrime:" + Thread.currentThread().getName() + " " + " starting from " + number.toString()); for (int i = 0; i < numberToTest; i++) { System.out.println("TestForPrime:" + Thread.currentThread().getName() + " " + new SimpleDateFormat("yy/MM/dd HH:mm:ss.SS").format(new Date()) + " loop number " + i); if (number.isProbablePrime(certainty)) { ThreadReturn.save(number); return; } ThreadReturn.ifInterruptedStop(); // have we been stopped number = number.add(two); // else try next one } } catch (Throwable t) { ThreadReturn.save(t); } } } /** * Find the prime * * @author matthew ford * @created October 21, 2001 */ public class Primes implements ThreadListener { /** * the newline string for this system */ private static String nl; /** * set up the nl string for this system */ static { nl = (String) java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("line.separator")); } /** * The main program * * @param args The command line arguments. * Could be used to pass in the number and the certainty, * but not implemented here. */ public static void main(String[] args) { int certainty = 100; String numberString = "1224343333333334549999999999999999999999999555555555555555555333333333333333333333333"; new Primes().findPrime(numberString, certainty); } /** * find the first probable prime greater than or equal to this number * If the first three threads don't find one, create another three threads and try again. * * @param numberString number to start looking from * @param certainty the probability that the number found is a prime is * 2^-certainty */ public void findPrime(String numberString, int certainty) { BigInteger prime = null; // the result TestForPrime t_1=null, t_2=null, t_3=null; // the three threads System.out.println( new SimpleDateFormat("yy/MM/dd HH:mm:ss.SS").format(new Date()) + " Finding Prime with accuracy of 2^-" + certainty + " starting at "); System.out.println(numberString); BigInteger number = new BigInteger(numberString); // have each thread test this many numbers, skipping even numbers int increment = 20; BigInteger numberIncrement = (new BigInteger("2")).multiply(new BigInteger("" + increment)); int counter = 1; // counter for thread names try { while (prime == null) { // loop here until possible prime found t_1 = new TestForPrime("Thread_"+counter++, number, increment, certainty); number = number.add(numberIncrement); t_2 = new TestForPrime("Thread_"+counter++, number, increment, certainty); number = number.add(numberIncrement); t_3 = new TestForPrime("Thread_"+counter++, number, increment, certainty); // update for next loop number = number.add(numberIncrement); // add listeners ThreadReturn.addListener(t_1, this); ThreadReturn.addListener(t_2, this); ThreadReturn.addListener(t_3, this); // start all the threads t_1.start(); t_2.start(); t_3.start(); // wait at most 2 seconds for the threads to finish TimeOut timeOut = new TimeOut(2000); if( (prime = (BigInteger)ThreadReturn.join(t_1, timeOut.timeRemaining())) != null) { break;}; if( (prime = (BigInteger)ThreadReturn.join(t_2, timeOut.timeRemaining())) != null) { break;}; if( (prime = (BigInteger)ThreadReturn.join(t_3, timeOut.timeRemaining())) != null) { break;}; } // while(prime == null) } catch (TimedOutException toe) { System.out.println(" Did not finish in time: " + StackTrace.toString(toe)); } catch (ThreadInterruptedException tiex) { System.out.println("Caught ThreadInterruptedException in findPrime() " +StackTrace.toString(tiex)); } catch (ThreadException tex) { System.out.println("Caught ThreadException in findPrime() "+StackTrace.toString(tex)); } catch (InterruptedException iex) { System.out.println("Caught InterruptedException in findPrime() "+StackTrace.toString(iex)); } finally { // stop all the threads if any one thread finds a probable prime // or throws an exception t_1.interrupt(); t_2.interrupt(); t_3.interrupt(); } if (prime != null) { System.out.println("findPrime() returns at " + new SimpleDateFormat("yy/MM/dd HH:mm:ss.SS").format(new Date()) + nl + " with prime:" + prime.toString() + nl); } } // ThreadListener methods /** * Result listener. * This method is called when the thread finishes normally. * * @param e ThreadEvent */ public synchronized void threadResult(ThreadEvent e) { Object obj = e.getObject(); if (obj == null) { // thread did not find a prime System.out.println(nl+ new SimpleDateFormat("yy/MM/dd HH:mm:ss.SS").format(new Date()) + " Thread:" + e.getThread().getName() + " did not find probable prime: " + nl); } else { System.out.println(nl+ new SimpleDateFormat("yy/MM/dd HH:mm:ss.SS").format(new Date()) + " Thread:" + e.getThread().getName() + " found prime: " + nl + " " + ((BigInteger) e.getObject()).toString() + nl); } } /** * Interrupted listener. * This method is called when the thread is stopped due to interrupt * * @param e ThreadEvent */ public synchronized void threadInterrupted(ThreadEvent e) { System.out.println( new SimpleDateFormat("yy/MM/dd HH:mm:ss.SS").format(new Date()) + " in threadInterrupted with ThreadEvent:" + nl + e.toString()); } /** * Error listener. * This method is called when the thread is stopped due to other exceptions * * @param e ThreadEvent */ public synchronized void threadError(ThreadEvent e) { System.out.println( new SimpleDateFormat("yy/MM/dd HH:mm:ss.SS").format(new Date()) + " in threadError with ThreadEvent:" + nl + e.toString()); } }