/* * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 * @summary tests methods in BigInteger * @run main/timeout=400 BigIntegerTest * @author madbot */ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.math.BigInteger; import java.util.Random; /** * This is a simple test class created to ensure that the results * generated by BigInteger adhere to certain identities. Passing * this test is a strong assurance that the BigInteger operations * are working correctly. * * Four arguments may be specified which give the number of * decimal digits you desire in the four batches of test numbers. * * The tests are performed on arrays of random numbers which are * generated by a Random class as well as special cases which * throw in boundary numbers such as 0, 1, maximum sized, etc. * */ public class BigIntegerTest { // // Bit large number thresholds based on the int thresholds // defined in BigInteger itself: // // KARATSUBA_THRESHOLD = 80 ints = 2560 bits // TOOM_COOK_THRESHOLD = 240 ints = 7680 bits // KARATSUBA_SQUARE_THRESHOLD = 128 ints = 4096 bits // TOOM_COOK_SQUARE_THRESHOLD = 216 ints = 6912 bits // // SCHOENHAGE_BASE_CONVERSION_THRESHOLD = 20 ints = 640 bits // // BURNIKEL_ZIEGLER_THRESHOLD = 80 ints = 2560 bits // static final int BITS_KARATSUBA = 2560; static final int BITS_TOOM_COOK = 7680; static final int BITS_KARATSUBA_SQUARE = 4096; static final int BITS_TOOM_COOK_SQUARE = 6912; static final int BITS_SCHOENHAGE_BASE = 640; static final int BITS_BURNIKEL_ZIEGLER = 2560; static final int ORDER_SMALL = 60; static final int ORDER_MEDIUM = 100; // #bits for testing Karatsuba static final int ORDER_KARATSUBA = 2760; // #bits for testing Toom-Cook and Burnikel-Ziegler static final int ORDER_TOOM_COOK = 8000; // #bits for testing Karatsuba squaring static final int ORDER_KARATSUBA_SQUARE = 4200; // #bits for testing Toom-Cook squaring static final int ORDER_TOOM_COOK_SQUARE = 7000; static final int SIZE = 1000; // numbers per batch static Random rnd = new Random(); static boolean failure = false; public static void pow(int order) { int failCount1 = 0; for (int i=0; i * (u << a)*(v << b) = (u*v) << (a + b) * * For Karatsuba multiplication, the right hand expression will be evaluated * using the standard naive algorithm, and the left hand expression using * the Karatsuba algorithm. For 3-way Toom-Cook multiplication, the right * hand expression will be evaluated using Karatsuba multiplication, and the * left hand expression using 3-way Toom-Cook multiplication. */ public static void multiplyLarge() { int failCount = 0; BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA - 32 - 1); for (int i=0; ibigInteger.multiply(bigInteger) tests whether * the parameter is the same instance on which the method is being invoked * and calls square() accordingly. */ public static void squareLarge() { int failCount = 0; BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA_SQUARE - 32 - 1); for (int i=0; i abs(v)} and {@code a > b && b > 0}, then if * {@code w/z = q1*z + r1} and {@code u/v = q2*v + r2}, then * {@code q1 = q2*pow(2,a-b)} and {@code r1 = r2*pow(2,b)}. The test * ensures that {@code v} is just under the B-Z threshold and that {@code w} * and {@code z} are both over the threshold. This implies that {@code u/v} * uses the standard division algorithm and {@code w/z} uses the B-Z * algorithm. The results of the two algorithms are then compared using the * observation described in the foregoing and if they are not equal a * failure is logged. */ public static void divideLarge() { int failCount = 0; BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER - 33); for (int i=0; i>= 1; } if (bigX.bitCount() != bitCount) { //System.err.println(x+": "+bitCount+", "+bigX.bitCount()); failCount++; } } report("Bit Count", failCount); } public static void bitLength() { int failCount = 0; for (int i=0; i= lower; bits--) { for (int i = 0; i < 50; i++) { BigInteger x = BigInteger.ONE.shiftLeft(bits - 1).or(new BigInteger(bits - 2, rnd)); for (int radix = Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) { String result = x.toString(radix); BigInteger test = new BigInteger(result, radix); if (!test.equals(x)) { failCount++; System.err.println("BigInteger toString: " + x); System.err.println("Test: " + test); System.err.println(radix); } } } } } report("String Conversion", failCount); } public static void byteArrayConv(int order) { int failCount = 0; for (int i=0; i0) order1 = (int)((Integer.parseInt(args[0]))* 3.333); if (args.length >1) order2 = (int)((Integer.parseInt(args[1]))* 3.333); if (args.length >2) order3 = (int)((Integer.parseInt(args[2]))* 3.333); if (args.length >3) order4 = (int)((Integer.parseInt(args[3]))* 3.333); prime(); nextProbablePrime(); arithmetic(order1); // small numbers arithmetic(order3); // Karatsuba range arithmetic(order4); // Toom-Cook / Burnikel-Ziegler range divideAndRemainder(order1); // small numbers divideAndRemainder(order3); // Karatsuba range divideAndRemainder(order4); // Toom-Cook / Burnikel-Ziegler range pow(order1); pow(order3); pow(order4); square(ORDER_MEDIUM); square(ORDER_KARATSUBA_SQUARE); square(ORDER_TOOM_COOK_SQUARE); bitCount(); bitLength(); bitOps(order1); bitwise(order1); shift(order1); byteArrayConv(order1); modInv(order1); // small numbers modInv(order3); // Karatsuba range modInv(order4); // Toom-Cook / Burnikel-Ziegler range modExp(order1, order2); modExp2(order1); stringConv(); serialize(); multiplyLarge(); squareLarge(); divideLarge(); if (failure) throw new RuntimeException("Failure in BigIntegerTest."); } /* * Get a random or boundary-case number. This is designed to provide * a lot of numbers that will find failure points, such as max sized * numbers, empty BigIntegers, etc. * * If order is less than 2, order is changed to 2. */ private static BigInteger fetchNumber(int order) { boolean negative = rnd.nextBoolean(); int numType = rnd.nextInt(7); BigInteger result = null; if (order < 2) order = 2; switch (numType) { case 0: // Empty result = BigInteger.ZERO; break; case 1: // One result = BigInteger.ONE; break; case 2: // All bits set in number int numBytes = (order+7)/8; byte[] fullBits = new byte[numBytes]; for(int i=0; i 0) { int runLength = Math.min(remaining, rnd.nextInt(order)); result = result.shiftLeft(runLength); if (bit > 0) result = result.add(ONE.shiftLeft(runLength).subtract(ONE)); remaining -= runLength; bit = 1 - bit; } break; default: // random bits result = new BigInteger(order, rnd); } if (negative) result = result.negate(); return result; } static void report(String testName, int failCount) { System.err.println(testName+": " + (failCount==0 ? "Passed":"Failed("+failCount+")")); if (failCount > 0) failure = true; } }