test/java/math/BigInteger/BigIntegerTest.java

Print this page
rev 12826 : 8032027: Add BigInteger square root methods
Summary: Add sqrt() and sqrtAndReminder() using Newton iteration
Reviewed-by: XXX

*** 24,34 **** /* * @test * @library /lib/testlibrary/ * @build jdk.testlibrary.* * @run main BigIntegerTest ! * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 * @summary tests methods in BigInteger (use -Dseed=X to set PRNG seed) * @run main/timeout=400 BigIntegerTest * @author madbot * @key randomness */ --- 24,34 ---- /* * @test * @library /lib/testlibrary/ * @build jdk.testlibrary.* * @run main BigIntegerTest ! * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 8032027 * @summary tests methods in BigInteger (use -Dseed=X to set PRNG seed) * @run main/timeout=400 BigIntegerTest * @author madbot * @key randomness */
*** 36,47 **** --- 36,51 ---- import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; + import java.math.BigDecimal; import java.math.BigInteger; import java.util.Random; + import java.util.stream.DoubleStream; + import java.util.stream.IntStream; + import java.util.stream.LongStream; import jdk.testlibrary.RandomFactory; /** * This is a simple test class created to ensure that the results * generated by BigInteger adhere to certain identities. Passing
*** 241,250 **** --- 245,421 ---- failCount1++; } report("square for " + order + " bits", failCount1); } + private static void fail(String msg) { + System.err.println(msg); + failure = true; + } + + private static void fail(String msg, Object expected, Object actual) { + System.err.println(msg + " - expected: " + expected + ", actual: " + actual); + failure = true; + } + + private static void squareRootSmall() { + // A negative value should cause an exception. + BigInteger n = BigInteger.ONE.negate(); + BigInteger s; + try { + s = n.sqrt(); + // If sqrt() does not throw an exception that is a failure. + fail("sqrt() of negative number did not throw an exception"); + } catch (ArithmeticException expected) { + // A negative value should cause an exception and is not a failure. + } + + // A zero value should return BigInteger.ZERO. + if (!BigInteger.valueOf(0).sqrt().equals(BigInteger.ZERO)) { + fail("sqrt(0) != BigInteger.ZERO"); + } + + // 1 <= value < 4 should return BigInteger.ONE. + long[] smalls = new long[] {1, 2, 3}; + for (long small : smalls) { + if (!BigInteger.valueOf(small).sqrt().equals(BigInteger.ONE)) { + fail("sqrt("+small+") != 1"); + } + } + } + + private static void squareRootInt() { + IntStream ints = random.ints(SIZE, 4, Integer.MAX_VALUE); + ints.forEach(i -> { + BigInteger n = BigInteger.valueOf(i); + BigInteger n2 = n.pow(2); + + // square root of n^2 -> n + BigInteger actual = n2.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(int)", n, actual); + } + + // square root of n^2 + 1 -> n + BigInteger n2up = n2.add(BigInteger.ONE); + actual = n2up.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(int)", n, actual); + } + + // square root of (n + 1)^2 - 1 -> n + BigInteger up = n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE); + actual = up.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(int)", n, actual); + } + }); + } + + private static void squareRootLong() { + LongStream longs = random.longs(SIZE, (long)Integer.MAX_VALUE + 1L, + Long.MAX_VALUE); + longs.forEach(i -> { + BigInteger n = BigInteger.valueOf(i); + BigInteger n2 = n.pow(2); + + // square root of n^2 -> n + BigInteger actual = n2.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(long)", n, actual); + } + + // square root of n^2 + 1 -> n + BigInteger n2up = n2.add(BigInteger.ONE); + actual = n2up.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(long)", n, actual); + } + + // square root of (n + 1)^2 - 1 -> n + BigInteger up = n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE); + actual = up.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(long)", n, actual); + } + }); + } + + private static void squareRootDouble() { + DoubleStream doubles = random.doubles(SIZE, + (double)Long.MAX_VALUE + 1.0, Math.sqrt(Double.MAX_VALUE)); + doubles.forEach(i -> { + BigInteger n = BigDecimal.valueOf(i).toBigInteger(); + BigInteger n2 = n.pow(2); + + // square root of n^2 -> n + BigInteger actual = n2.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(double)", n, actual); + } + + // square root of n^2 + 1 -> n + BigInteger n2up = n2.add(BigInteger.ONE); + actual = n2up.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(double)", n, actual); + } + + // square root of (n + 1)^2 - 1 -> n + BigInteger up = n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE); + actual = up.sqrt(); + if (actual.compareTo(n) != 0) { + fail("sqrt(double)", n, actual); + } + }); + } + + public static void squareRoot() { + squareRootSmall(); + squareRootInt(); + squareRootLong(); + squareRootDouble(); + } + + public static void squareRootAndRemainder() { + IntStream bits = random.ints(SIZE, 3, Short.MAX_VALUE); + bits.forEach(i -> { + BigInteger n = new BigInteger(i, random); + BigInteger n2 = n.pow(2); + + // square root of n^2 -> n + BigInteger[] actual = n2.sqrtAndRemainder(); + if (actual[0].compareTo(n) != 0) { + fail("sqrtAndRemainder()[0]", n, actual[0]); + } + if (actual[1].compareTo(BigInteger.ZERO) != 0) { + fail("sqrtAndRemainder()[1]", BigInteger.ZERO, actual[1]); + } + + // square root of n^2 + 1 -> n + BigInteger n2up = n2.add(BigInteger.ONE); + actual = n2up.sqrtAndRemainder(); + if (actual[0].compareTo(n) != 0) { + fail("sqrtAndRemainder()[0]", n, actual[0]); + } + if (actual[1].compareTo(BigInteger.ONE) != 0) { + fail("sqrtAndRemainder()[1]", BigInteger.ONE, actual[1]); + } + + // square root of (n + 1)^2 - 1 -> n + BigInteger up = n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE); + actual = up.sqrtAndRemainder(); + if (actual[0].compareTo(n) != 0) { + fail("sqrt(int)", n, actual[0]); + } + BigInteger r = up.subtract(n2); + if (actual[1].compareTo(r) != 0) { + fail("sqrtAndRemainder()[1]", r, actual[1]); + } + }); + } + public static void arithmetic(int order) { int failCount = 0; for (int i=0; i<SIZE; i++) { BigInteger x = fetchNumber(order);
*** 1099,1108 **** --- 1270,1282 ---- square(ORDER_MEDIUM); square(ORDER_KARATSUBA_SQUARE); square(ORDER_TOOM_COOK_SQUARE); + squareRoot(); + squareRootAndRemainder(); + bitCount(); bitLength(); bitOps(order1); bitwise(order1);