import jdbm.RecordManager;
import jdbm.RecordManagerFactory;
import jdbm.RecordManagerOptions;
import jdbm.btree.BTree;
import jdbm.helper.LongComparator;
import jdbm.helper.Tuple;
import jdbm.helper.TupleBrowser;
import java.util.Properties;
import java.util.Random;
import java.io.IOException;
/**
* Example program dealing with B+Trees and Prime numbers.
*/
public class Primes
{
/**
* Default number of prime number to populate in the database (if not specified on command-line)
*/
public static int DEFAULT_POPULATE = 100;
/**
* Default number of random lookups (if not specified on command-line)
*/
public static int DEFAULT_LOOKUPS = 100;
/**
* Record Manager used for persistence.
*/
private RecordManager _recman;
/**
* B+Tree holding prime numbers.
*/
private BTree _primes;
/**
* Random number generator.
*/
private static Random _random = new Random();
/**
* Main constructor
*/
public Primes( String[] args )
throws IOException
{
long recid;
Properties props;
// open database and setup an object cache
props = new Properties();
props.put( RecordManagerOptions.CACHE_SIZE, "10000" );
_recman = RecordManagerFactory.createRecordManager( "primes", props );
recid = _recman.getNamedObject( "primes" );
if ( recid == 0 ) {
System.out.println( "Creating a new primes B+Tree." );
_primes = BTree.createInstance( _recman, new LongComparator() );
_recman.setNamedObject( "primes", _primes.getRecid() );
} else {
_primes = BTree.load( _recman, recid );
System.out.println( "B+Tree already contains " + _primes.size() + " primes." );
}
_recman.commit();
}
/**
* Get the largest prime number in the database.
*/
public Long getLargestPrime()
throws IOException
{
Tuple tuple;
TupleBrowser browser;
Long largest = null;
tuple = new Tuple();
browser = _primes.browse( null );
if ( browser.getPrevious( tuple ) ) {
largest = (Long) tuple.getValue();
System.out.println( "Largest prime: " + largest );
} else {
System.out.println( "No prime number in the database." );
}
return largest;
}
/**
* Populate the database with more prime numbers.
*
* @param count Number of primes to add to database.
*/
void populate( int count )
throws IOException
{
Long current;
Long largest;
System.out.println( "Populating prime B+Tree..." );
// start after the largest known prime
largest = getLargestPrime();
if ( largest == null ) {
largest = new Long( 0 );
}
current = new Long( largest.longValue() + 1L );
while ( count > 0 ) {
if ( isPrime( current ) ) {
_primes.insert( current, current, false );
System.out.println( "Found prime #" + _primes.size() + ": " + current );
count--;
}
current = new Long( current.longValue() + 1 );
}
_recman.commit();
}
/**
* Returns true if a number is prime.
*/
boolean isPrime( Long number )
throws IOException
{
Tuple tuple;
TupleBrowser browser;
Long largest;
Long current;
if ( number.longValue() <= 0L ) {
throw new IllegalArgumentException( "Number must be greater than zero" );
}
if ( number.longValue() == 1 ) {
return true;
}
tuple = new Tuple();
browser = _primes.browse();
while ( browser.getNext( tuple ) ) {
current = (Long) tuple.getValue();
if ( current.longValue() != 1 && ( number.longValue() % current.longValue() ) == 0 ) {
// not a prime because it is divisibe by a prime
return false;
}
}
// this is a prime
return true;
}
/**
* Display a number of random prime numbers.
*/
void random( int count )
throws IOException
{
Tuple tuple;
TupleBrowser browser;
Long largest;
Long number;
tuple = new Tuple();
largest = getLargestPrime();
System.out.println( "Looking up " + count + " random primes...." );
long start = System.currentTimeMillis();
for ( int i=0; i<count; i++ ) {
number = new Long( random( 0, largest.longValue() ) );
browser = _primes.browse( number );
if ( browser.getNext( tuple ) ) {
number = (Long) tuple.getValue();
System.out.print( number );
System.out.print( ", " );
}
}
long stop = System.currentTimeMillis();
System.out.println();
System.out.println( "Time: " + (stop-start)/count + " millis/lookup " );
}
/**
* Return true if number is a prime.
*/
public static boolean isPrimeCompute( long number )
{
for ( int i=2; i<number/2; i++ ) {
if ( ( number % i ) == 0 ) {
return false;
}
}
return true;
}
/**
* Get random number between "low" and "high" (inclusively)
*/
public static long random( long low, long high )
{
return ( (long) ( _random.nextDouble() * (high-low) ) + low );
}
/**
* Static program entrypoint.
*/
public static void main( String[] args )
{
Primes primes;
int count;
Long number;
Long largest;
try {
primes = new Primes( args );
for ( int i=0; i<args.length; i++ ) {
if ( args[i].equalsIgnoreCase( "-populate" ) ) {
if ( ++i < args.length ) {
count = Integer.parseInt( args[i] );
} else {
count = DEFAULT_POPULATE;
}
primes.populate( count );
} else if ( args[i].equalsIgnoreCase( "-check" ) ) {
if ( ++i < args.length ) {
number = new Long( Long.parseLong( args[i] ) );
} else {
number = new Long( _random.nextLong() );
}
largest = primes.getLargestPrime();
if ( number.longValue() > primes.getLargestPrime().longValue() ) {
throw new IllegalArgumentException( "Number is larger than largest known prime in database." );
}
if ( primes.isPrime( number ) ) {
System.out.println( "The number " + number + " is a prime." );
} else {
System.out.println( "The number " + number + " is not a prime." );
}
} else if ( args[i].equalsIgnoreCase( "-random" ) ) {
if ( ++i < args.length ) {
count = Integer.parseInt( args[i] );
} else {
count = DEFAULT_LOOKUPS;
}
primes.random( count );
}
}
if ( args.length == 0 ) {
System.out.println( "Usage: java Prime [action] [args]" );
System.out.println( "" );
System.out.println( "Actions:" );
System.out.println( " -populate [number] Populate database with prime numbers" );
System.out.println( " -check [number] Check if a number is a prime" );
System.out.println( " -random [number] Display random prime numbers" );
System.out.println( "" );
}
} catch ( IOException except ) {
except.printStackTrace();
}
}
}