jaroslav@1258: /* jaroslav@1258: * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. jaroslav@1258: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@1258: * jaroslav@1258: * This code is free software; you can redistribute it and/or modify it jaroslav@1258: * under the terms of the GNU General Public License version 2 only, as jaroslav@1258: * published by the Free Software Foundation. Oracle designates this jaroslav@1258: * particular file as subject to the "Classpath" exception as provided jaroslav@1258: * by Oracle in the LICENSE file that accompanied this code. jaroslav@1258: * jaroslav@1258: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@1258: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@1258: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@1258: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@1258: * accompanied this code). jaroslav@1258: * jaroslav@1258: * You should have received a copy of the GNU General Public License version jaroslav@1258: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@1258: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@1258: * jaroslav@1258: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@1258: * or visit www.oracle.com if you need additional information or have any jaroslav@1258: * questions. jaroslav@1258: */ jaroslav@1258: jaroslav@1258: package java.math; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * A simple bit sieve used for finding prime number candidates. Allows setting jaroslav@1258: * and clearing of bits in a storage array. The size of the sieve is assumed to jaroslav@1258: * be constant to reduce overhead. All the bits of a new bitSieve are zero, and jaroslav@1258: * bits are removed from it by setting them. jaroslav@1258: * jaroslav@1258: * To reduce storage space and increase efficiency, no even numbers are jaroslav@1258: * represented in the sieve (each bit in the sieve represents an odd number). jaroslav@1258: * The relationship between the index of a bit and the number it represents is jaroslav@1258: * given by jaroslav@1258: * N = offset + (2*index + 1); jaroslav@1258: * Where N is the integer represented by a bit in the sieve, offset is some jaroslav@1258: * even integer offset indicating where the sieve begins, and index is the jaroslav@1258: * index of a bit in the sieve array. jaroslav@1258: * jaroslav@1258: * @see BigInteger jaroslav@1258: * @author Michael McCloskey jaroslav@1258: * @since 1.3 jaroslav@1258: */ jaroslav@1258: class BitSieve { jaroslav@1258: /** jaroslav@1258: * Stores the bits in this bitSieve. jaroslav@1258: */ jaroslav@1258: private long bits[]; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Length is how many bits this sieve holds. jaroslav@1258: */ jaroslav@1258: private int length; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * A small sieve used to filter out multiples of small primes in a search jaroslav@1258: * sieve. jaroslav@1258: */ jaroslav@1258: private static BitSieve smallSieve = new BitSieve(); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Construct a "small sieve" with a base of 0. This constructor is jaroslav@1258: * used internally to generate the set of "small primes" whose multiples jaroslav@1258: * are excluded from sieves generated by the main (package private) jaroslav@1258: * constructor, BitSieve(BigInteger base, int searchLen). The length jaroslav@1258: * of the sieve generated by this constructor was chosen for performance; jaroslav@1258: * it controls a tradeoff between how much time is spent constructing jaroslav@1258: * other sieves, and how much time is wasted testing composite candidates jaroslav@1258: * for primality. The length was chosen experimentally to yield good jaroslav@1258: * performance. jaroslav@1258: */ jaroslav@1258: private BitSieve() { jaroslav@1258: length = 150 * 64; jaroslav@1258: bits = new long[(unitIndex(length - 1) + 1)]; jaroslav@1258: jaroslav@1258: // Mark 1 as composite jaroslav@1258: set(0); jaroslav@1258: int nextIndex = 1; jaroslav@1258: int nextPrime = 3; jaroslav@1258: jaroslav@1258: // Find primes and remove their multiples from sieve jaroslav@1258: do { jaroslav@1258: sieveSingle(length, nextIndex + nextPrime, nextPrime); jaroslav@1258: nextIndex = sieveSearch(length, nextIndex + 1); jaroslav@1258: nextPrime = 2*nextIndex + 1; jaroslav@1258: } while((nextIndex > 0) && (nextPrime < length)); jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Construct a bit sieve of searchLen bits used for finding prime number jaroslav@1258: * candidates. The new sieve begins at the specified base, which must jaroslav@1258: * be even. jaroslav@1258: */ jaroslav@1258: BitSieve(BigInteger base, int searchLen) { jaroslav@1258: /* jaroslav@1258: * Candidates are indicated by clear bits in the sieve. As a candidates jaroslav@1258: * nonprimality is calculated, a bit is set in the sieve to eliminate jaroslav@1258: * it. To reduce storage space and increase efficiency, no even numbers jaroslav@1258: * are represented in the sieve (each bit in the sieve represents an jaroslav@1258: * odd number). jaroslav@1258: */ jaroslav@1258: bits = new long[(unitIndex(searchLen-1) + 1)]; jaroslav@1258: length = searchLen; jaroslav@1258: int start = 0; jaroslav@1258: jaroslav@1258: int step = smallSieve.sieveSearch(smallSieve.length, start); jaroslav@1258: int convertedStep = (step *2) + 1; jaroslav@1258: jaroslav@1258: // Construct the large sieve at an even offset specified by base jaroslav@1258: MutableBigInteger b = new MutableBigInteger(base); jaroslav@1258: MutableBigInteger q = new MutableBigInteger(); jaroslav@1258: do { jaroslav@1258: // Calculate base mod convertedStep jaroslav@1258: start = b.divideOneWord(convertedStep, q); jaroslav@1258: jaroslav@1258: // Take each multiple of step out of sieve jaroslav@1258: start = convertedStep - start; jaroslav@1258: if (start%2 == 0) jaroslav@1258: start += convertedStep; jaroslav@1258: sieveSingle(searchLen, (start-1)/2, convertedStep); jaroslav@1258: jaroslav@1258: // Find next prime from small sieve jaroslav@1258: step = smallSieve.sieveSearch(smallSieve.length, step+1); jaroslav@1258: convertedStep = (step *2) + 1; jaroslav@1258: } while (step > 0); jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Given a bit index return unit index containing it. jaroslav@1258: */ jaroslav@1258: private static int unitIndex(int bitIndex) { jaroslav@1258: return bitIndex >>> 6; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Return a unit that masks the specified bit in its unit. jaroslav@1258: */ jaroslav@1258: private static long bit(int bitIndex) { jaroslav@1258: return 1L << (bitIndex & ((1<<6) - 1)); jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Get the value of the bit at the specified index. jaroslav@1258: */ jaroslav@1258: private boolean get(int bitIndex) { jaroslav@1258: int unitIndex = unitIndex(bitIndex); jaroslav@1258: return ((bits[unitIndex] & bit(bitIndex)) != 0); jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Set the bit at the specified index. jaroslav@1258: */ jaroslav@1258: private void set(int bitIndex) { jaroslav@1258: int unitIndex = unitIndex(bitIndex); jaroslav@1258: bits[unitIndex] |= bit(bitIndex); jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * This method returns the index of the first clear bit in the search jaroslav@1258: * array that occurs at or after start. It will not search past the jaroslav@1258: * specified limit. It returns -1 if there is no such clear bit. jaroslav@1258: */ jaroslav@1258: private int sieveSearch(int limit, int start) { jaroslav@1258: if (start >= limit) jaroslav@1258: return -1; jaroslav@1258: jaroslav@1258: int index = start; jaroslav@1258: do { jaroslav@1258: if (!get(index)) jaroslav@1258: return index; jaroslav@1258: index++; jaroslav@1258: } while(index < limit-1); jaroslav@1258: return -1; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Sieve a single set of multiples out of the sieve. Begin to remove jaroslav@1258: * multiples of the specified step starting at the specified start index, jaroslav@1258: * up to the specified limit. jaroslav@1258: */ jaroslav@1258: private void sieveSingle(int limit, int start, int step) { jaroslav@1258: while(start < limit) { jaroslav@1258: set(start); jaroslav@1258: start += step; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Test probable primes in the sieve and return successful candidates. jaroslav@1258: */ jaroslav@1258: BigInteger retrieve(BigInteger initValue, int certainty, java.util.Random random) { jaroslav@1258: // Examine the sieve one long at a time to find possible primes jaroslav@1258: int offset = 1; jaroslav@1258: for (int i=0; i>>= 1; jaroslav@1258: offset+=2; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: return null; jaroslav@1258: } jaroslav@1258: }