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);