Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/math/BigInteger/PrimeTest.java
38821 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* @test27* @bug 802623628* @summary test primality verification methods in BigInteger29* @author bpb30* @key randomness31*/32import java.math.BigInteger;33import java.util.BitSet;34import java.util.List;35import java.util.NavigableSet;36import java.util.SplittableRandom;37import java.util.TreeSet;38import static java.util.stream.Collectors.toCollection;39import static java.util.stream.Collectors.toList;40import java.util.stream.IntStream;41import java.util.stream.Stream;4243public class PrimeTest {4445private static final int DEFAULT_UPPER_BOUND = 1299709; // 100000th prime46private static final int DEFAULT_CERTAINTY = 100;47private static final int NUM_NON_PRIMES = 10000;4849/**50* Run the test.51*52* @param args The parameters.53* @throws Exception on failure54*/55public static void main(String[] args) throws Exception {56// Prepare arguments57int upperBound = args.length > 0 ? Integer.valueOf(args[0]) : DEFAULT_UPPER_BOUND;58int certainty = args.length > 1 ? Integer.valueOf(args[1]) : DEFAULT_CERTAINTY;59boolean parallel = args.length > 2 ? Boolean.valueOf(args[2]) : true;6061// Echo parameter settings62System.out.println("Upper bound = " + upperBound63+ "\nCertainty = " + certainty64+ "\nParallel = " + parallel);6566// Get primes through specified bound (inclusive) and Integer.MAX_VALUE67NavigableSet<BigInteger> primes = getPrimes(upperBound);6869// Check whether known primes are identified as such70boolean primeTest = checkPrime(primes, certainty, parallel);71System.out.println("Prime test result: " + (primeTest ? "SUCCESS" : "FAILURE"));72if (!primeTest) {73System.err.println("Prime test failed");74}7576// Check whether known non-primes are not identified as primes77boolean nonPrimeTest = checkNonPrime(primes, certainty);78System.out.println("Non-prime test result: " + (nonPrimeTest ? "SUCCESS" : "FAILURE"));7980if (!primeTest || !nonPrimeTest) {81throw new Exception("PrimeTest FAILED!");82}8384System.out.println("PrimeTest succeeded!");85}8687/**88* Create a {@code BitSet} wherein a set bit indicates the corresponding89* index plus 2 is prime. That is, if bit N is set, then the integer N + 290* is prime. The values 0 and 1 are intentionally excluded. See the91* <a92* href="http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithm_description">93* Sieve of Eratosthenes</a> algorithm description for more information.94*95* @param upperBound The maximum prime to allow96* @return bits indicating which indexes represent primes97*/98private static BitSet createPrimes(int upperBound) {99int nbits = upperBound - 1;100BitSet bs = new BitSet(nbits);101for (int p = 2; p * p < upperBound;) {102for (int i = p * p; i < nbits + 2; i += p) {103bs.set(i - 2, true);104}105do {106++p;107} while (p > 1 && bs.get(p - 2));108}109bs.flip(0, nbits);110return bs;111}112113/**114* Load the primes up to the specified bound (inclusive) into a115* {@code NavigableSet}, appending the prime {@code Integer.MAX_VALUE}.116*117* @param upperBound The maximum prime to allow118* @return a set of primes119*/120private static NavigableSet<BigInteger> getPrimes(int upperBound) {121BitSet bs = createPrimes(upperBound);122NavigableSet<BigInteger> primes = bs.stream()123.mapToObj(p -> BigInteger.valueOf(p + 2))124.collect(toCollection(TreeSet::new));125primes.add(BigInteger.valueOf(Integer.MAX_VALUE));126System.out.println(String.format("Created %d primes", primes.size()));127return primes;128}129130/**131* Verifies whether the fraction of probable primes detected is at least 1 -132* 1/2^certainty.133*134* @return true if and only if the test succeeds135*/136private static boolean checkPrime(NavigableSet<BigInteger> primes,137int certainty,138boolean parallel) {139long probablePrimes = (parallel ? primes.parallelStream() : primes.stream())140.filter(bi -> bi.isProbablePrime(certainty))141.count();142143// N = certainty / 2144// Success if p/t >= 1 - 1/4^N145// or (p/t)*4^N >= 4^N - 1146// or p*4^N >= t*(4^N - 1)147BigInteger p = BigInteger.valueOf(probablePrimes);148BigInteger t = BigInteger.valueOf(primes.size());149BigInteger fourToTheC = BigInteger.valueOf(4).pow(certainty / 2);150BigInteger fourToTheCMinusOne = fourToTheC.subtract(BigInteger.ONE);151BigInteger left = p.multiply(fourToTheC);152BigInteger right = t.multiply(fourToTheCMinusOne);153154if (left.compareTo(right) < 0) {155System.err.println("Probable prime certainty test failed.");156}157158return left.compareTo(right) >= 0;159}160161/**162* Verifies whether all {@code BigInteger}s in the tested range for which163* {@code isProbablePrime()} returns {@code false} are <i>not</i>164* prime numbers.165*166* @return true if and only if the test succeeds167*/168private static boolean checkNonPrime(NavigableSet<BigInteger> primes,169int certainty) {170int maxPrime = DEFAULT_UPPER_BOUND;171try {172maxPrime = primes.last().intValueExact();173} catch (ArithmeticException e) {174// ignore it175}176177// Create a list of non-prime BigIntegers.178List<BigInteger> nonPrimeBigInts = (new SplittableRandom())179.ints(NUM_NON_PRIMES, 2, maxPrime).mapToObj(BigInteger::valueOf)180.filter(b -> !b.isProbablePrime(certainty)).collect(toList());181182// If there are any non-probable primes also in the primes list then fail.183boolean failed = nonPrimeBigInts.stream().anyMatch(primes::contains);184185// In the event, print which purported non-primes were actually prime.186if (failed) {187for (BigInteger bigInt : nonPrimeBigInts) {188if (primes.contains(bigInt)) {189System.err.println("Prime value thought to be non-prime: " + bigInt);190}191}192}193194return !failed;195}196}197198199