undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,327 @@
/*
* Copyright (c) 2006, 2025, 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 6362557 8200698
* @summary Some tests of add(BigDecimal, mc)
*/
import java.math.*;
import static java.math.BigDecimal.*;
import java.util.Set;
import java.util.EnumSet;
public class AddTests {
private static Set<RoundingMode> nonExactRoundingModes =
EnumSet.complementOf(EnumSet.of(RoundingMode.UNNECESSARY));
/**
* Test for some simple additions, particularly, it will test
* the overflow case.
*/
private static int simpleTests() {
int failures = 0;
BigDecimal[] bd1 = {
new BigDecimal(new BigInteger("7812404666936930160"), 11),
new BigDecimal(new BigInteger("7812404666936930160"), 12),
new BigDecimal(new BigInteger("7812404666936930160"), 13),
};
BigDecimal bd2 = new BigDecimal(new BigInteger("2790000"), 1);
BigDecimal[] expectedResult = {
new BigDecimal("78403046.66936930160"),
new BigDecimal("8091404.666936930160"),
new BigDecimal("1060240.4666936930160"),
};
for (int i = 0; i < bd1.length; i++) {
if (!bd1[i].add(bd2).equals(expectedResult[i]))
failures++;
}
return failures;
}
/**
* Test for extreme value of scale and rounding precision that
* could cause integer overflow in right-shift-into-sticky-bit
* computations.
*/
private static int extremaTests() {
int failures = 0;
failures += addWithoutException(valueOf(1, -Integer.MAX_VALUE),
valueOf(2, Integer.MAX_VALUE), null);
failures += addWithoutException(valueOf(1, -Integer.MAX_VALUE),
valueOf(-2, Integer.MAX_VALUE), null);
return failures;
}
/**
* Print sum of b1 and b2; correct result will not throw an
* exception.
*/
private static int addWithoutException(BigDecimal b1, BigDecimal b2, MathContext mc) {
if (mc == null)
mc = new MathContext(2, RoundingMode.DOWN);
try {
BigDecimal sum = b1.add(b2, mc);
printAddition(b1, b2, sum.toString());
return 0;
} catch(ArithmeticException ae) {
printAddition(b1, b2, "Exception!");
return 1;
}
}
/**
* Test combinations of operands that may meet the condensation
* criteria when rounded to different precisions.
*/
private static int roundingGradationTests() {
int failures = 0;
failures += roundAway(new BigDecimal("1234e100"),
new BigDecimal( "1234e97"));
failures += roundAway(new BigDecimal("1234e100"),
new BigDecimal( "1234e96"));
failures += roundAway(new BigDecimal("1234e100"),
new BigDecimal( "1234e95"));
failures += roundAway(new BigDecimal("1234e100"),
new BigDecimal( "1234e94"));
failures += roundAway(new BigDecimal("1234e100"),
new BigDecimal( "1234e93"));
failures += roundAway(new BigDecimal("1234e100"),
new BigDecimal( "1234e92"));
failures += roundAway(new BigDecimal("1234e100"),
new BigDecimal("1234e50"));
failures += roundAway(new BigDecimal("1000e100"),
new BigDecimal( "1234e97"));
failures += roundAway(new BigDecimal("1000e100"),
new BigDecimal( "1234e96"));
failures += roundAway(new BigDecimal("1000e100"),
new BigDecimal( "1234e95"));
failures += roundAway(new BigDecimal("1000e100"),
new BigDecimal( "1234e94"));
failures += roundAway(new BigDecimal("1000e100"),
new BigDecimal( "1234e93"));
failures += roundAway(new BigDecimal("1000e100"),
new BigDecimal( "1234e92"));
failures += roundAway(new BigDecimal("1000e100"),
new BigDecimal("1234e50"));
failures += roundAway(new BigDecimal("1999e100"),
new BigDecimal( "1234e97"));
failures += roundAway(new BigDecimal("1999e100"),
new BigDecimal( "1234e96"));
failures += roundAway(new BigDecimal("1999e100"),
new BigDecimal( "1234e95"));
failures += roundAway(new BigDecimal("1999e100"),
new BigDecimal( "1234e94"));
failures += roundAway(new BigDecimal("1999e100"),
new BigDecimal( "1234e93"));
failures += roundAway(new BigDecimal("1999e100"),
new BigDecimal( "1234e92"));
failures += roundAway(new BigDecimal("1999e100"),
new BigDecimal("1234e50"));
failures += roundAway(new BigDecimal("9999e100"),
new BigDecimal( "1234e97"));
failures += roundAway(new BigDecimal("9999e100"),
new BigDecimal( "1234e96"));
failures += roundAway(new BigDecimal("9999e100"),
new BigDecimal( "1234e95"));
failures += roundAway(new BigDecimal("9999e100"),
new BigDecimal( "1234e94"));
failures += roundAway(new BigDecimal("9999e100"),
new BigDecimal( "1234e93"));
failures += roundAway(new BigDecimal("9999e100"),
new BigDecimal( "1234e92"));
failures += roundAway(new BigDecimal("9999e100"),
new BigDecimal("1234e50"));
return failures;
}
private static void printAddition(BigDecimal b1, BigDecimal b2, String s) {
System.out.println("" + b1+ "\t+\t" + b2 + "\t=\t" + s);
}
private static int roundAway(BigDecimal b1, BigDecimal b2) {
int failures = 0;
b1.precision();
b2.precision();
BigDecimal b1_negate = b1.negate();
BigDecimal b2_negate = b2.negate();
b1_negate.precision();
b2_negate.precision();
failures += roundAway1(b1, b2);
failures += roundAway1(b1, b2_negate);
failures += roundAway1(b1_negate, b2);
failures += roundAway1(b1_negate, b2_negate);
return failures;
}
private static int roundAway1(BigDecimal b1, BigDecimal b2) {
int failures = 0;
failures += roundAway0(b1, b2);
failures += roundAway0(b2, b1);
return failures;
}
/**
* Compare b1.add(b2, mc) with b1.add(b2).round(mc) for a variety
* of MathContexts.
*/
private static int roundAway0(BigDecimal b1, BigDecimal b2) {
int failures = 0;
BigDecimal exactSum = b1.add(b2);
for(int precision = 1 ; precision < exactSum.precision()+2; precision++) {
for(RoundingMode rm : nonExactRoundingModes) {
MathContext mc = new MathContext(precision, rm);
BigDecimal roundedExactSum = exactSum.round(mc);
try {
BigDecimal sum = b1.add(b2, mc);
if (!roundedExactSum.equals(sum) ) {
failures++;
System.out.println("Exact sum " + exactSum +
"\trounded by " + mc +
"\texpected: " + roundedExactSum + " got: ");
printAddition(b1, b2, sum.toString());
}
// else {
// System.out.print(mc + "\t");
// printAddition(b1, b2, sum.toString());
// }
} catch (ArithmeticException ae) {
printAddition(b1, b2, "Exception!");
failures++;
}
}
}
return failures;
}
/**
* Verify calling the precision method should not change the
* computed result.
*/
private static int precisionConsistencyTest() {
int failures = 0;
MathContext mc = new MathContext(1,RoundingMode.DOWN);
BigDecimal a = BigDecimal.valueOf(1999, -1); //value is equivalent to 19990
BigDecimal sum1 = a.add(BigDecimal.ONE, mc);
a.precision();
BigDecimal sum2 = a.add(BigDecimal.ONE, mc);
if (!sum1.equals(sum2)) {
failures ++;
System.out.println("Unequal sums after calling precision!");
System.out.print("Before:\t");
printAddition(a, BigDecimal.ONE, sum1.toString());
System.out.print("After:\t");
printAddition(a, BigDecimal.ONE, sum2.toString());
}
return failures;
}
private static int arithmeticExceptionTest() {
int failures = 0;
BigDecimal x;
try {
//
// The string representation "1e2147483647", which is equivalent
// to 10^Integer.MAX_VALUE, is used to create an augend with an
// unscaled value of 1 and a scale of -Integer.MAX_VALUE. The
// addend "1" has an unscaled value of 1 with a scale of 0. The
// addition is performed exactly and is specified to have a
// preferred scale of max(-Integer.MAX_VALUE, 0). As the scale
// of the result is 0, a value with Integer.MAX_VALUE + 1 digits
// would need to be created. Therefore the next statement is
// expected to overflow with an ArithmeticException.
//
x = new BigDecimal("1e2147483647").add(new BigDecimal(1));
failures++;
} catch (ArithmeticException ae) {
}
return failures;
}
public static void main(String argv[]) {
int failures = 0;
failures += extremaTests();
failures += roundingGradationTests();
failures += precisionConsistencyTest();
failures += arithmeticExceptionTest();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing rounding add.");
}
}
}

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2006, 2025, 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 6473768
* @summary Tests of BigDecimal.compareTo
*/
import java.math.*;
import static java.math.BigDecimal.*;
public class CompareToTests {
private static int compareToTests() {
int failures = 0;
final BigDecimal MINUS_ONE = BigDecimal.ONE.negate();
// First operand, second operand, expected compareTo result
BigDecimal [][] testCases = {
// Basics
{valueOf(0), valueOf(0), ZERO},
{valueOf(0), valueOf(1), MINUS_ONE},
{valueOf(1), valueOf(2), MINUS_ONE},
{valueOf(2), valueOf(1), ONE},
{valueOf(10), valueOf(10), ZERO},
// Significands would compare differently than scaled value
{valueOf(2,1), valueOf(2), MINUS_ONE},
{valueOf(2,-1), valueOf(2), ONE},
{valueOf(1,1), valueOf(2), MINUS_ONE},
{valueOf(1,-1), valueOf(2), ONE},
{valueOf(5,-1), valueOf(2), ONE},
// Boundary and near boundary values
{valueOf(Long.MAX_VALUE), valueOf(Long.MAX_VALUE), ZERO},
{valueOf(Long.MAX_VALUE).negate(), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MAX_VALUE-1), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MAX_VALUE-1).negate(), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MIN_VALUE), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MIN_VALUE).negate(), valueOf(Long.MAX_VALUE), ONE},
{valueOf(Long.MIN_VALUE+1), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MIN_VALUE+1).negate(), valueOf(Long.MAX_VALUE), ZERO},
{valueOf(Long.MAX_VALUE), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MAX_VALUE).negate(), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MAX_VALUE-1), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MAX_VALUE-1).negate(), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MIN_VALUE), valueOf(Long.MIN_VALUE), ZERO},
{valueOf(Long.MIN_VALUE).negate(), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MIN_VALUE+1), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MIN_VALUE+1).negate(), valueOf(Long.MIN_VALUE), ONE},
};
for (BigDecimal[] testCase : testCases) {
BigDecimal a = testCase[0];
BigDecimal a_negate = a.negate();
BigDecimal b = testCase[1];
BigDecimal b_negate = b.negate();
int expected = testCase[2].intValue();
failures += compareToTest(a, b, expected);
failures += compareToTest(a_negate, b_negate, -expected);
}
return failures;
}
private static int compareToTest(BigDecimal a, BigDecimal b, int expected) {
int result = a.compareTo(b);
int failed = (result==expected) ? 0 : 1;
if (failed == 1) {
System.err.println("(" + a + ").compareTo(" + b + ") => " + result +
"\n\tExpected " + expected);
}
return failed;
}
public static void main(String argv[]) {
int failures = 0;
failures += compareToTests();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing exact compareTo.");
}
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 1999, 2025, 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 4259453 8200698
* @summary Test constructors of BigDecimal
* @library ..
* @run junit Constructor
*/
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
public class Constructor {
@Test
public void stringConstructor() {
Assertions.assertThrows(NumberFormatException.class, () -> {
BigDecimal bd = new BigDecimal("1.2e");
});
}
@Test
public void charArrayConstructorNegativeOffset() {
Assertions.assertThrows(NumberFormatException.class, () -> {
BigDecimal bd = new BigDecimal(new char[5], -1, 4, null);
});
}
@Test
public void charArrayConstructorNegativeLength() {
Assertions.assertThrows(NumberFormatException.class, () -> {
BigDecimal bd = new BigDecimal(new char[5], 0, -1, null);
});
}
@Test
public void charArrayConstructorIntegerOverflow() {
Assertions.assertThrows(NumberFormatException.class, () -> {
try {
BigDecimal bd = new BigDecimal(new char[5], Integer.MAX_VALUE - 5,
6, null);
} catch (NumberFormatException nfe) {
if (nfe.getCause() instanceof IndexOutOfBoundsException) {
throw new RuntimeException
("NumberFormatException should not have a cause");
} else {
throw nfe;
}
}
});
}
@Test
public void charArrayConstructorIndexOutOfBounds() {
Assertions.assertThrows(NumberFormatException.class, () -> {
BigDecimal bd = new BigDecimal(new char[5], 1, 5, null);
});
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2022, 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 8282252
* @summary Test constructors of BigDecimal to replace BigInteger subclasses
*/
import java.math.*;
public class ConstructorUnscaledValue {
public static void main(String... args) {
TestBigInteger tbi = new TestBigInteger(BigInteger.ONE);
// Create BigDecimal's using each of the three constructors
// with guards on the class of unscaledValue
BigDecimal[] values = {
new BigDecimal(tbi),
new BigDecimal(tbi, 2),
new BigDecimal(tbi, 3, MathContext.DECIMAL32),
};
for (var bd : values) {
BigInteger unscaledValue = bd.unscaledValue();
if (unscaledValue.getClass() != BigInteger.class) {
throw new RuntimeException("Bad class for unscaledValue");
}
if (!unscaledValue.equals(BigInteger.ONE)) {
throw new RuntimeException("Bad value for unscaledValue");
}
}
}
private static class TestBigInteger extends BigInteger {
public TestBigInteger(BigInteger bi) {
super(bi.toByteArray());
}
@Override
public String toString() {
return java.util.Arrays.toString(toByteArray());
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,426 @@
/*
* Copyright (c) 2003, 2025, 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 4851776 4907265 6177836 6876282 8066842
* @summary Some tests for the divide methods.
*/
import java.math.*;
import static java.math.BigDecimal.*;
public class DivideTests {
// Preliminary exact divide method; could be used for comparison
// purposes.
BigDecimal anotherDivide(BigDecimal dividend, BigDecimal divisor) {
/*
* Handle zero cases first.
*/
if (divisor.signum() == 0) { // x/0
if (dividend.signum() == 0) // 0/0
throw new ArithmeticException("Division undefined"); // NaN
throw new ArithmeticException("Division by zero");
}
if (dividend.signum() == 0) // 0/y
return BigDecimal.ZERO;
else {
/*
* Determine if there is a result with a terminating
* decimal expansion. Putting aside overflow and
* underflow considerations, the existance of an exact
* result only depends on the ratio of the intVal's of the
* dividend (i.e. this) and divisor since the scales
* of the argument just affect where the decimal point
* lies.
*
* For the ratio of (a = this.intVal) and (b =
* divisor.intVal) to have a finite decimal expansion,
* once a/b is put in lowest terms, b must be equal to
* (2^i)*(5^j) for some integer i,j >= 0. Therefore, we
* first compute to see if b_prime =(b/gcd(a,b)) is equal
* to (2^i)*(5^j).
*/
BigInteger TWO = BigInteger.valueOf(2);
BigInteger FIVE = BigInteger.valueOf(5);
BigInteger TEN = BigInteger.valueOf(10);
BigInteger divisorIntvalue = divisor.scaleByPowerOfTen(divisor.scale()).toBigInteger().abs();
BigInteger dividendIntvalue = dividend.scaleByPowerOfTen(dividend.scale()).toBigInteger().abs();
BigInteger b_prime = divisorIntvalue.divide(dividendIntvalue.gcd(divisorIntvalue));
boolean goodDivisor = false;
int i=0, j=0;
badDivisor: {
while(! b_prime.equals(BigInteger.ONE) ) {
int b_primeModTen = b_prime.mod(TEN).intValue() ;
switch(b_primeModTen) {
case 0:
// b_prime divisible by 10=2*5, increment i and j
i++;
j++;
b_prime = b_prime.divide(TEN);
break;
case 5:
// b_prime divisible by 5, increment j
j++;
b_prime = b_prime.divide(FIVE);
break;
case 2:
case 4:
case 6:
case 8:
// b_prime divisible by 2, increment i
i++;
b_prime = b_prime.divide(TWO);
break;
default: // hit something we shouldn't have
b_prime = BigInteger.ONE; // terminate loop
break badDivisor;
}
}
goodDivisor = true;
}
if( ! goodDivisor ) {
throw new ArithmeticException("Non terminating decimal expansion");
}
else {
// What is a rule for determining how many digits are
// needed? Once that is determined, cons up a new
// MathContext object and pass it on to the divide(bd,
// mc) method; precision == ?, roundingMode is unnecessary.
// Are we sure this is the right scale to use? Should
// also determine a precision-based method.
MathContext mc = new MathContext(dividend.precision() +
(int)Math.ceil(
10.0*divisor.precision()/3.0),
RoundingMode.UNNECESSARY);
// Should do some more work here to rescale, etc.
return dividend.divide(divisor, mc);
}
}
}
public static int powersOf2and5() {
int failures = 0;
for(int i = 0; i < 6; i++) {
int powerOf2 = (int)StrictMath.pow(2.0, i);
for(int j = 0; j < 6; j++) {
int powerOf5 = (int)StrictMath.pow(5.0, j);
int product;
BigDecimal bd;
try {
bd = BigDecimal.ONE.divide(new BigDecimal(product=powerOf2*powerOf5));
} catch (ArithmeticException e) {
failures++;
System.err.println((new BigDecimal(powerOf2)).toString() + " / " +
(new BigDecimal(powerOf5)).toString() + " threw an exception.");
e.printStackTrace();
}
try {
bd = new BigDecimal(powerOf2).divide(new BigDecimal(powerOf5));
} catch (ArithmeticException e) {
failures++;
System.err.println((new BigDecimal(powerOf2)).toString() + " / " +
(new BigDecimal(powerOf5)).toString() + " threw an exception.");
e.printStackTrace();
}
try {
bd = new BigDecimal(powerOf5).divide(new BigDecimal(powerOf2));
} catch (ArithmeticException e) {
failures++;
System.err.println((new BigDecimal(powerOf5)).toString() + " / " +
(new BigDecimal(powerOf2)).toString() + " threw an exception.");
e.printStackTrace();
}
}
}
return failures;
}
public static int nonTerminating() {
int failures = 0;
int[] primes = {1, 3, 7, 13, 17};
// For each pair of prime products, verify the ratio of
// non-equal products has a non-terminating expansion.
for(int i = 0; i < primes.length; i++) {
for(int j = i+1; j < primes.length; j++) {
for(int m = 0; m < primes.length; m++) {
for(int n = m+1; n < primes.length; n++) {
int dividend = primes[i] * primes[j];
int divisor = primes[m] * primes[n];
if ( ((dividend/divisor) * divisor) != dividend ) {
try {
BigDecimal quotient = (new BigDecimal(dividend).
divide(new BigDecimal(divisor)));
failures++;
System.err.println("Exact quotient " + quotient.toString() +
" returned for non-terminating fraction " +
dividend + " / " + divisor + ".");
}
catch (ArithmeticException e) {
; // Correct result
}
}
}
}
}
}
return failures;
}
public static int properScaleTests(){
int failures = 0;
BigDecimal[][] testCases = {
{new BigDecimal("1"), new BigDecimal("5"), new BigDecimal("2e-1")},
{new BigDecimal("1"), new BigDecimal("50e-1"), new BigDecimal("2e-1")},
{new BigDecimal("10e-1"), new BigDecimal("5"), new BigDecimal("2e-1")},
{new BigDecimal("1"), new BigDecimal("500e-2"), new BigDecimal("2e-1")},
{new BigDecimal("100e-2"), new BigDecimal("5"), new BigDecimal("20e-2")},
{new BigDecimal("1"), new BigDecimal("32"), new BigDecimal("3125e-5")},
{new BigDecimal("1"), new BigDecimal("64"), new BigDecimal("15625e-6")},
{new BigDecimal("1.0000000"), new BigDecimal("64"), new BigDecimal("156250e-7")},
};
for(BigDecimal[] tc : testCases) {
BigDecimal quotient;
if (! (quotient = tc[0].divide(tc[1])).equals(tc[2]) ) {
failures++;
System.err.println("Unexpected quotient from " + tc[0] + " / " + tc[1] +
"; expected " + tc[2] + " got " + quotient);
}
}
return failures;
}
public static int trailingZeroTests() {
int failures = 0;
MathContext mc = new MathContext(3, RoundingMode.FLOOR);
BigDecimal[][] testCases = {
{new BigDecimal("19"), new BigDecimal("100"), new BigDecimal("0.19")},
{new BigDecimal("21"), new BigDecimal("110"), new BigDecimal("0.190")},
};
for(BigDecimal[] tc : testCases) {
BigDecimal quotient;
if (! (quotient = tc[0].divide(tc[1], mc)).equals(tc[2]) ) {
failures++;
System.err.println("Unexpected quotient from " + tc[0] + " / " + tc[1] +
"; expected " + tc[2] + " got " + quotient);
}
}
return failures;
}
public static int scaledRoundedDivideTests() {
int failures = 0;
// Tests of the traditional scaled divide under different
// rounding modes.
// Encode rounding mode and scale for the divide in a
// BigDecimal with the significand equal to the rounding mode
// and the scale equal to the number's scale.
// {dividend, dividisor, rounding, quotient}
BigDecimal a = new BigDecimal("31415");
BigDecimal a_minus = a.negate();
BigDecimal b = new BigDecimal("10000");
BigDecimal c = new BigDecimal("31425");
BigDecimal c_minus = c.negate();
// Ad hoc tests
BigDecimal d = new BigDecimal(new BigInteger("-37361671119238118911893939591735"), 10);
BigDecimal e = new BigDecimal(new BigInteger("74723342238476237823787879183470"), 15);
BigDecimal[][] testCases = {
{a, b, BigDecimal.valueOf(ROUND_UP, 3), new BigDecimal("3.142")},
{a_minus, b, BigDecimal.valueOf(ROUND_UP, 3), new BigDecimal("-3.142")},
{a, b, BigDecimal.valueOf(ROUND_DOWN, 3), new BigDecimal("3.141")},
{a_minus, b, BigDecimal.valueOf(ROUND_DOWN, 3), new BigDecimal("-3.141")},
{a, b, BigDecimal.valueOf(ROUND_CEILING, 3), new BigDecimal("3.142")},
{a_minus, b, BigDecimal.valueOf(ROUND_CEILING, 3), new BigDecimal("-3.141")},
{a, b, BigDecimal.valueOf(ROUND_FLOOR, 3), new BigDecimal("3.141")},
{a_minus, b, BigDecimal.valueOf(ROUND_FLOOR, 3), new BigDecimal("-3.142")},
{a, b, BigDecimal.valueOf(ROUND_HALF_UP, 3), new BigDecimal("3.142")},
{a_minus, b, BigDecimal.valueOf(ROUND_HALF_UP, 3), new BigDecimal("-3.142")},
{a, b, BigDecimal.valueOf(ROUND_DOWN, 3), new BigDecimal("3.141")},
{a_minus, b, BigDecimal.valueOf(ROUND_DOWN, 3), new BigDecimal("-3.141")},
{a, b, BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("3.142")},
{a_minus, b, BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("-3.142")},
{c, b, BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("3.142")},
{c_minus, b, BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("-3.142")},
{d, e, BigDecimal.valueOf(ROUND_HALF_UP, -5), BigDecimal.valueOf(-1, -5)},
{d, e, BigDecimal.valueOf(ROUND_HALF_DOWN, -5), BigDecimal.valueOf(0, -5)},
{d, e, BigDecimal.valueOf(ROUND_HALF_EVEN, -5), BigDecimal.valueOf(0, -5)},
};
for(BigDecimal tc[] : testCases) {
int scale = tc[2].scale();
int rm = tc[2].unscaledValue().intValue();
BigDecimal quotient = tc[0].divide(tc[1], scale, rm);
if (!quotient.equals(tc[3])) {
failures++;
System.err.println("Unexpected quotient from " + tc[0] + " / " + tc[1] +
" scale " + scale + " rounding mode " + RoundingMode.valueOf(rm) +
"; expected " + tc[3] + " got " + quotient);
}
}
// 6876282
BigDecimal[][] testCases2 = {
// { dividend, divisor, expected quotient }
{ new BigDecimal(3090), new BigDecimal(7), new BigDecimal(441) },
{ new BigDecimal("309000000000000000000000"), new BigDecimal("700000000000000000000"),
new BigDecimal(441) },
{ new BigDecimal("962.430000000000"), new BigDecimal("8346463.460000000000"),
new BigDecimal("0.000115309916") },
{ new BigDecimal("18446744073709551631"), new BigDecimal("4611686018427387909"),
new BigDecimal(4) },
{ new BigDecimal("18446744073709551630"), new BigDecimal("4611686018427387909"),
new BigDecimal(4) },
{ new BigDecimal("23058430092136939523"), new BigDecimal("4611686018427387905"),
new BigDecimal(5) },
{ new BigDecimal("-18446744073709551661"), new BigDecimal("-4611686018427387919"),
new BigDecimal(4) },
{ new BigDecimal("-18446744073709551660"), new BigDecimal("-4611686018427387919"),
new BigDecimal(4) },
};
for (BigDecimal test[] : testCases2) {
BigDecimal quo = test[0].divide(test[1], RoundingMode.HALF_UP);
if (!quo.equals(test[2])) {
failures++;
System.err.println("Unexpected quotient from " + test[0] + " / " + test[1] +
" rounding mode HALF_UP" +
"; expected " + test[2] + " got " + quo);
}
}
return failures;
}
private static int divideByOneTests() {
int failures = 0;
//problematic divisor: one with scale 17
BigDecimal one = BigDecimal.ONE.setScale(17);
RoundingMode rounding = RoundingMode.UNNECESSARY;
long[][] unscaledAndScale = new long[][] {
{ Long.MAX_VALUE, 17},
{-Long.MAX_VALUE, 17},
{ Long.MAX_VALUE, 0},
{-Long.MAX_VALUE, 0},
{ Long.MAX_VALUE, 100},
{-Long.MAX_VALUE, 100}
};
for (long[] uas : unscaledAndScale) {
long unscaled = uas[0];
int scale = (int)uas[1];
BigDecimal noRound = null;
try {
noRound = BigDecimal.valueOf(unscaled, scale).
divide(one, RoundingMode.UNNECESSARY);
} catch (ArithmeticException e) {
failures++;
System.err.println("ArithmeticException for value " + unscaled
+ " and scale " + scale + " without rounding");
}
BigDecimal roundDown = null;
try {
roundDown = BigDecimal.valueOf(unscaled, scale).
divide(one, RoundingMode.DOWN);
} catch (ArithmeticException e) {
failures++;
System.err.println("ArithmeticException for value " + unscaled
+ " and scale " + scale + " with rounding down");
}
if (noRound != null && roundDown != null
&& noRound.compareTo(roundDown) != 0) {
failures++;
System.err.println("Equality failure for value " + unscaled
+ " and scale " + scale);
}
}
return failures;
}
public static void main(String argv[]) {
int failures = 0;
failures += powersOf2and5();
failures += nonTerminating();
failures += properScaleTests();
failures += trailingZeroTests();
failures += scaledRoundedDivideTests();
failures += divideByOneTests();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing division.");
}
}
}

View file

@ -0,0 +1,366 @@
/*
* Copyright (c) 2022, 2024, 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 8205592 8339252 8341260
* @summary Verify {double, float, float16}Value methods work
* @modules jdk.incubator.vector
* @library /test/lib
* @key randomness
* @build jdk.test.lib.RandomFactory
* @run main DoubleFloatValueTests
*/
import jdk.test.lib.RandomFactory;
import java.math.BigDecimal;
import java.util.Random;
import jdk.incubator.vector.Float16;
public class DoubleFloatValueTests {
private static final BigDecimal HALF = BigDecimal.valueOf(5, 1);
private static final BigDecimal EPS = BigDecimal.valueOf(1, 10_000);
private static BigDecimal nextHalfUp(double v) {
BigDecimal bv = new BigDecimal(v);
BigDecimal ulp = new BigDecimal(Math.ulp(v));
return bv.add(ulp.multiply(HALF));
}
private static BigDecimal nextHalfDown(double v) {
BigDecimal bv = new BigDecimal(v);
BigDecimal ulp = new BigDecimal(v - Math.nextDown(v));
return bv.subtract(ulp.multiply(HALF));
}
private static BigDecimal nextHalfUp(float v) {
BigDecimal bv = new BigDecimal(v);
BigDecimal ulp = new BigDecimal(Math.ulp(v));
return bv.add(ulp.multiply(HALF));
}
private static BigDecimal nextHalfDown(float v) {
BigDecimal bv = new BigDecimal(v);
BigDecimal ulp = new BigDecimal(v - Math.nextDown(v));
return bv.subtract(ulp.multiply(HALF));
}
private static BigDecimal nextHalfUp(Float16 v) {
BigDecimal bv = new BigDecimal(v.doubleValue());
BigDecimal ulp = new BigDecimal(Float16.ulp(v).doubleValue());
return bv.add(ulp.multiply(HALF));
}
private static BigDecimal nextHalfDown(Float16 v) {
BigDecimal bv = new BigDecimal(v.doubleValue());
BigDecimal ulp = new BigDecimal(v.doubleValue() - Float16.nextDown(v).doubleValue());
return bv.subtract(ulp.multiply(HALF));
}
private static String toDecHexString(double v) {
return v + " (" + Double.toHexString(v) + ")";
}
private static String toDecHexString(float v) {
return v + " (" + Float.toHexString(v) + ")";
}
private static String toDecHexString(Float16 v) {
return v + " (" + Float16.toHexString(v) + ")";
}
private static void checkDouble(BigDecimal bd, double exp) {
double res = bd.doubleValue();
if (exp != res ) {
String message = "Bad conversion: got " + toDecHexString(res) +
", expected " + toDecHexString(exp);
throw new RuntimeException(message);
}
}
private static void checkFloat(BigDecimal bv, float exp) {
float res = bv.floatValue();
if (exp != res ) {
String message = "Bad conversion: got " + toDecHexString(res) +
", expected " + toDecHexString(exp);
throw new RuntimeException(message);
}
}
private static void checkFloat16(BigDecimal bv, Float16 exp) {
Float16 res = Float16.valueOf(bv); // bv.float16Value();
if (exp.floatValue() != res.floatValue()) {
String message = "Bad conversion: got " + toDecHexString(res) +
", expected " + toDecHexString(exp);
throw new RuntimeException(message);
}
}
private static boolean isOdd(int n) {
return (n & 0x1) != 0;
}
private static void testDoubleValueNearMinValue() {
for (int n = 0; n < 100; ++n) {
BigDecimal b = nextHalfUp(n * Double.MIN_VALUE);
checkDouble(b, ((n + 1) / 2 * 2) * Double.MIN_VALUE);
checkDouble(b.subtract(EPS), n * Double.MIN_VALUE);
checkDouble(b.add(EPS), (n + 1) * Double.MIN_VALUE);
}
}
private static void testFloatValueNearMinValue() {
for (int n = 0; n < 100; ++n) {
BigDecimal b = nextHalfUp(n * Float.MIN_VALUE);
checkFloat(b, ((n + 1) / 2 * 2) * Float.MIN_VALUE);
checkFloat(b.subtract(EPS), n * Float.MIN_VALUE);
checkFloat(b.add(EPS), (n + 1) * Float.MIN_VALUE);
}
}
private static void testFloat16ValueNearMinValue() {
for (int n = 0; n < 100; ++n) {
BigDecimal b = nextHalfUp(Float16.multiply(Float16.valueOf(n), Float16.MIN_VALUE));
checkFloat16(b, Float16.multiply(Float16.valueOf((n + 1) / 2 * 2), Float16.MIN_VALUE));
checkFloat16(b.subtract(EPS), Float16.multiply(Float16.valueOf(n), Float16.MIN_VALUE));
checkFloat16(b.add(EPS), Float16.multiply(Float16.valueOf(n + 1), Float16.MIN_VALUE));
}
}
private static void testDoubleValueNearMinNormal() {
double v = Double.MIN_NORMAL;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfDown(v);
checkDouble(bv, isOdd(n) ? Math.nextDown(v) : v);
checkDouble(bv.subtract(EPS), Math.nextDown(v));
checkDouble(bv.add(EPS), v);
v = Math.nextDown(v);
}
v = Double.MIN_NORMAL;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfUp(v);
checkDouble(bv, isOdd(n) ? Math.nextUp(v) : v);
checkDouble(bv.subtract(EPS), v);
checkDouble(bv.add(EPS), Math.nextUp(v));
v = Math.nextUp(v);
}
}
private static void testFloatValueNearMinNormal() {
float v = Float.MIN_NORMAL;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfDown(v);
checkFloat(bv, isOdd(n) ? Math.nextDown(v) : v);
checkFloat(bv.subtract(EPS), Math.nextDown(v));
checkFloat(bv.add(EPS), v);
v = Math.nextDown(v);
}
v = Float.MIN_NORMAL;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfUp(v);
checkFloat(bv, isOdd(n) ? Math.nextUp(v) : v);
checkFloat(bv.subtract(EPS), v);
checkFloat(bv.add(EPS), Math.nextUp(v));
v = Math.nextUp(v);
}
}
private static void testFloat16ValueNearMinNormal() {
Float16 v = Float16.MIN_NORMAL;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfDown(v);
checkFloat16(bv, isOdd(n) ? Float16.nextDown(v) : v);
checkFloat16(bv.subtract(EPS), Float16.nextDown(v));
checkFloat16(bv.add(EPS), v);
v = Float16.nextDown(v);
}
v = Float16.MIN_NORMAL;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfUp(v);
checkFloat16(bv, isOdd(n) ? Float16.nextUp(v) : v);
checkFloat16(bv.subtract(EPS), v);
checkFloat16(bv.add(EPS), Float16.nextUp(v));
v = Float16.nextUp(v);
}
}
private static void testDoubleValueNearMaxValue() {
double v = Double.MAX_VALUE;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfDown(v);
checkDouble(bv, isOdd(n) ? v : Math.nextDown(v));
checkDouble(bv.subtract(EPS), Math.nextDown(v));
checkDouble(bv.add(EPS), v);
v = Math.nextDown(v);
}
BigDecimal bv = nextHalfUp(Double.MAX_VALUE);
checkDouble(bv, Double.POSITIVE_INFINITY);
checkDouble(bv.subtract(EPS), Double.MAX_VALUE);
checkDouble(bv.add(EPS), Double.POSITIVE_INFINITY);
}
private static void testFloatValueNearMaxValue() {
float v = Float.MAX_VALUE;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfDown(v);
checkFloat(bv, isOdd(n) ? v : Math.nextDown(v));
checkFloat(bv.subtract(EPS), Math.nextDown(v));
checkFloat(bv.add(EPS), v);
v = Math.nextDown(v);
}
BigDecimal bv = nextHalfUp(Float.MAX_VALUE);
checkFloat(bv, Float.POSITIVE_INFINITY);
checkFloat(bv.subtract(EPS), Float.MAX_VALUE);
checkFloat(bv.add(EPS), Float.POSITIVE_INFINITY);
}
private static void testFloat16ValueNearMaxValue() {
Float16 v = Float16.MAX_VALUE;
for (int n = 0; n < 100; ++n) {
BigDecimal bv = nextHalfDown(v);
checkFloat16(bv, isOdd(n) ? v : Float16.nextDown(v));
checkFloat16(bv.subtract(EPS), Float16.nextDown(v));
checkFloat16(bv.add(EPS), v);
v = Float16.nextDown(v);
}
BigDecimal bv = nextHalfUp(Float16.MAX_VALUE);
checkFloat16(bv, Float16.POSITIVE_INFINITY);
checkFloat16(bv.subtract(EPS), Float16.MAX_VALUE);
checkFloat16(bv.add(EPS), Float16.POSITIVE_INFINITY);
}
private static void testDoubleValueRandom() {
Random r = RandomFactory.getRandom();
for (int i = 0; i < 10_000; ++i) {
double v = r.nextDouble(-Double.MAX_VALUE, Double.MAX_VALUE);
checkDouble(new BigDecimal(v), v);
}
for (int i = 0; i < 10_000; ++i) {
double v = r.nextDouble(-1e9, 1e9);
checkDouble(new BigDecimal(v), v);
}
for (int i = 0; i < 10_000; ++i) {
double v = r.nextDouble(-1e6, 1e6);
checkDouble(new BigDecimal(v), v);
}
for (int i = 0; i < 10_000; ++i) {
double v = r.nextDouble(-1e-6, 1e-6);
checkDouble(new BigDecimal(v), v);
}
for (int i = 0; i < 10_000; ++i) {
double v = r.nextDouble(-1e-9, 1e-9);
checkDouble(new BigDecimal(v), v);
}
}
private static void testFloatValueRandom() {
Random r = RandomFactory.getRandom();
for (int i = 0; i < 10_000; ++i) {
float v = r.nextFloat(-Float.MAX_VALUE, Float.MAX_VALUE);
checkFloat(new BigDecimal(v), v);
}
for (int i = 0; i < 10_000; ++i) {
float v = r.nextFloat(-1e9f, 1e9f);
checkFloat(new BigDecimal(v), v);
}
for (int i = 0; i < 10_000; ++i) {
float v = r.nextFloat(-1e6f, 1e6f);
checkFloat(new BigDecimal(v), v);
}
for (int i = 0; i < 10_000; ++i) {
float v = r.nextFloat(-1e-6f, 1e-6f);
checkFloat(new BigDecimal(v), v);
}
for (int i = 0; i < 10_000; ++i) {
float v = r.nextFloat(-1e-9f, 1e-9f);
checkFloat(new BigDecimal(v), v);
}
}
private static void testFloat16ValueRandom() {
Random r = RandomFactory.getRandom();
for (int i = 0; i < 10_000; ++i) {
Float16 v = Float16.valueOf(r.nextFloat(-Float16.MAX_VALUE.floatValue(), Float16.MAX_VALUE.floatValue()));
checkFloat16(new BigDecimal(v.floatValue()), v);
}
for (int i = 0; i < 10_000; ++i) {
Float16 v = Float16.valueOf(r.nextFloat(-1e4f, 1e4f));
checkFloat16(new BigDecimal(v.floatValue()), v);
}
for (int i = 0; i < 10_000; ++i) {
Float16 v = Float16.valueOf(r.nextFloat(-1e3f, 1e3f));
checkFloat16(new BigDecimal(v.floatValue()), v);
}
for (int i = 0; i < 10_000; ++i) {
Float16 v = Float16.valueOf(r.nextFloat(-1e-3f, 1e-3f));
checkFloat16(new BigDecimal(v.floatValue()), v);
}
for (int i = 0; i < 10_000; ++i) {
Float16 v = Float16.valueOf(r.nextFloat(-1e-4f, 1e-4f));
checkFloat16(new BigDecimal(v.floatValue()), v);
}
}
private static void testDoubleValueExtremes() {
checkDouble(BigDecimal.valueOf(1, 1000), 0.0);
checkDouble(BigDecimal.valueOf(-1, 1000), -0.0);
checkDouble(BigDecimal.valueOf(1, -1000), Double.POSITIVE_INFINITY);
checkDouble(BigDecimal.valueOf(-1, -1000), Double.NEGATIVE_INFINITY);
}
private static void testFloatValueExtremes() {
checkFloat(BigDecimal.valueOf(1, 1000), 0.0f);
checkFloat(BigDecimal.valueOf(-1, 1000), -0.0f);
checkFloat(BigDecimal.valueOf(1, -1000), Float.POSITIVE_INFINITY);
checkFloat(BigDecimal.valueOf(-1, -1000), Float.NEGATIVE_INFINITY);
}
private static void testFloat16ValueExtremes() {
checkFloat16(BigDecimal.valueOf(1, 1000), Float16.valueOf(0.0f));
checkFloat16(BigDecimal.valueOf(-1, 1000), Float16.valueOf(-0.0f));
checkFloat16(BigDecimal.valueOf(1, -1000), Float16.POSITIVE_INFINITY);
checkFloat16(BigDecimal.valueOf(-1, -1000), Float16.NEGATIVE_INFINITY);
}
public static void main(String[] args) {
testDoubleValueNearMinValue();
testDoubleValueNearMinNormal();
testDoubleValueNearMaxValue();
testDoubleValueRandom();
testDoubleValueExtremes();
testFloatValueNearMinValue();
testFloatValueNearMinNormal();
testFloatValueNearMaxValue();
testFloatValueRandom();
testFloatValueExtremes();
testFloat16ValueNearMinValue();
testFloat16ValueNearMinNormal();
testFloat16ValueNearMaxValue();
testFloat16ValueRandom();
testFloat16ValueExtremes();
}
}

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2009, 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 1234567
* @summary Test BigDecimal.equals() method.
* @author xlu
*/
import java.math.*;
import static java.math.BigDecimal.*;
public class EqualsTests {
public static void main(String argv[]) {
int failures = 0;
BigDecimal[][] testValues = {
// The even index is supposed to return true for equals call and
// the odd index is supposed to return false, i.e. not equal.
{ZERO, ZERO},
{ONE, TEN},
{valueOf(Integer.MAX_VALUE), valueOf(Integer.MAX_VALUE)},
{valueOf(Long.MAX_VALUE), valueOf(-Long.MAX_VALUE)},
{valueOf(12345678), valueOf(12345678)},
{valueOf(123456789), valueOf(123456788)},
{new BigDecimal("123456789123456789123"),
new BigDecimal(new BigInteger("123456789123456789123"))},
{new BigDecimal("123456789123456789123"),
new BigDecimal(new BigInteger("123456789123456789124"))},
{valueOf(Long.MIN_VALUE), new BigDecimal("-9223372036854775808")},
{new BigDecimal("9223372036854775808"), valueOf(Long.MAX_VALUE)},
{valueOf(Math.round(Math.pow(2, 10))), new BigDecimal("1024")},
{new BigDecimal("1020"), valueOf(Math.pow(2, 11))},
{new BigDecimal(BigInteger.valueOf(2).pow(65)),
new BigDecimal("36893488147419103232")},
{new BigDecimal("36893488147419103231.81"),
new BigDecimal("36893488147419103231.811"),
}
};
boolean expected = Boolean.TRUE;
for (BigDecimal[] testValuePair : testValues) {
failures += equalsTest(testValuePair[0], testValuePair[1], expected);
expected = !expected;
}
if (failures > 0) {
throw new RuntimeException("Inccured " + failures +
" failures while testing equals.");
}
}
private static int equalsTest(BigDecimal l, BigDecimal r, boolean expected) {
boolean result = l.equals(r);
int failed = (result == expected) ? 0 : 1;
if (failed == 1) {
System.err.println(l + " .equals(" + r + ") => " + result +
"\n\tExpected " + expected);
}
return failed;
}
}

View file

@ -0,0 +1,188 @@
/*
* Copyright (c) 2005, 2018, 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 6274390 7082971
* @summary Verify {float, double}Value methods work with condensed representation
* @run main FloatDoubleValueTests
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 FloatDoubleValueTests
*/
import java.math.*;
public class FloatDoubleValueTests {
private static final long two2the24 = 1L<<23;
private static final long two2the53 = 1L<<52;
// Largest long that fits exactly in a float
private static final long maxFltLong = (long)(Integer.MAX_VALUE & ~(0xff));
// Largest long that fits exactly in a double
private static final long maxDblLong = Long.MAX_VALUE & ~(0x7ffL);
static void testDoubleValue0(long i, BigDecimal bd) {
if (bd.doubleValue() != i ||
bd.longValue() != i)
throw new RuntimeException("Unexpected equality failure for " +
i + "\t" + bd);
}
static void testFloatValue0(long i, BigDecimal bd) {
if (bd.floatValue() != i ||
bd.longValue() != i)
throw new RuntimeException("Unexpected equality failure for " +
i + "\t" + bd);
}
static void checkFloat(BigDecimal bd, float f) {
float fbd = bd.floatValue();
if (f != fbd ) {
String message = String.format("Bad conversion:"+
"got %g (%a)\texpected %g (%a)",
f, f, fbd, fbd);
throw new RuntimeException(message);
}
}
static void checkDouble(BigDecimal bd, double d) {
double dbd = bd.doubleValue();
if (d != dbd ) {
String message = String.format("Bad conversion:"+
"got %g (%a)\texpected %g (%a)",
d, d, dbd, dbd);
throw new RuntimeException(message);
}
}
// Test integral values that will convert exactly to both float
// and double.
static void testFloatDoubleValue() {
long longValues[] = {
Long.MIN_VALUE, // -2^63
0,
1,
2,
two2the24-1,
two2the24,
two2the24+1,
maxFltLong-1,
maxFltLong,
maxFltLong+1,
};
for(long i : longValues) {
BigDecimal bd1 = new BigDecimal(i);
BigDecimal bd2 = new BigDecimal(-i);
testDoubleValue0( i, bd1);
testDoubleValue0(-i, bd2);
testFloatValue0( i, bd1);
testFloatValue0(-i, bd2);
}
}
static void testDoubleValue() {
long longValues[] = {
Integer.MAX_VALUE-1,
Integer.MAX_VALUE,
(long)Integer.MAX_VALUE+1,
two2the53-1,
two2the53,
two2the53+1,
maxDblLong,
};
// Test integral values that will convert exactly to double
// but not float.
for(long i : longValues) {
BigDecimal bd1 = new BigDecimal(i);
BigDecimal bd2 = new BigDecimal(-i);
testDoubleValue0( i, bd1);
testDoubleValue0(-i, bd2);
checkFloat(bd1, (float)i);
checkFloat(bd2, -(float)i);
}
// Now check values that should not convert the same in double
for(long i = maxDblLong; i < Long.MAX_VALUE; i++) {
BigDecimal bd1 = new BigDecimal(i);
BigDecimal bd2 = new BigDecimal(-i);
checkDouble(bd1, (double)i);
checkDouble(bd2, -(double)i);
checkFloat(bd1, (float)i);
checkFloat(bd2, -(float)i);
}
checkDouble(new BigDecimal(Long.MIN_VALUE), (double)Long.MIN_VALUE);
checkDouble(new BigDecimal(Long.MAX_VALUE), (double)Long.MAX_VALUE);
}
static void testFloatValue() {
// Now check values that should not convert the same in float
for(long i = maxFltLong; i <= Integer.MAX_VALUE; i++) {
BigDecimal bd1 = new BigDecimal(i);
BigDecimal bd2 = new BigDecimal(-i);
checkFloat(bd1, (float)i);
checkFloat(bd2, -(float)i);
testDoubleValue0( i, bd1);
testDoubleValue0(-i, bd2);
}
}
static void testFloatValue1() {
checkFloat(new BigDecimal("85070591730234615847396907784232501249"), 8.507059e+37f);
checkFloat(new BigDecimal("7784232501249e12"), 7.7842326e24f);
checkFloat(new BigDecimal("907784232501249e-12"),907.78424f);
checkFloat(new BigDecimal("7784e8"),7.7839997e11f);
checkFloat(new BigDecimal("9077e-8"),9.077e-5f);
}
static void testDoubleValue1() {
checkDouble(new BigDecimal("85070591730234615847396907784232501249"), 8.507059173023462e37);
checkDouble(new BigDecimal("7784232501249e12"), 7.784232501249e24);
checkDouble(new BigDecimal("907784232501249e-12"), 907.784232501249);
checkDouble(new BigDecimal("7784e8"), 7.784e11);
checkDouble(new BigDecimal("9077e-8"), 9.077e-5);
}
public static void main(String[] args) throws Exception {
testFloatDoubleValue();
testDoubleValue();
testFloatValue();
testFloatValue1();
testDoubleValue1();
}
}

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2019, 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 8211936
* @summary Tests of BigDecimal.intValueExact
*/
import java.math.*;
import java.util.List;
import java.util.Map;
import static java.util.Map.entry;
public class IntValueExactTests {
public static void main(String... args) {
int failures = 0;
failures += intValueExactSuccessful();
failures += intValueExactExceptional();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing intValueExact.");
}
}
private static int simpleIntValueExact(BigDecimal bd) {
return bd.toBigIntegerExact().intValue();
}
private static int intValueExactSuccessful() {
int failures = 0;
// Strings used to create BigDecimal instances on which invoking
// intValueExact() will succeed.
Map<BigDecimal, Integer> successCases =
Map.ofEntries(entry(new BigDecimal("2147483647"), Integer.MAX_VALUE), // 2^31 -1
entry(new BigDecimal("2147483647.0"), Integer.MAX_VALUE),
entry(new BigDecimal("2147483647.00"), Integer.MAX_VALUE),
entry(new BigDecimal("-2147483648"), Integer.MIN_VALUE), // -2^31
entry(new BigDecimal("-2147483648.0"), Integer.MIN_VALUE),
entry(new BigDecimal("-2147483648.00"),Integer.MIN_VALUE),
entry(new BigDecimal("1e0"), 1),
entry(new BigDecimal(BigInteger.ONE, -9), 1_000_000_000),
entry(new BigDecimal("0e13"), 0), // Fast path zero
entry(new BigDecimal("0e32"), 0),
entry(new BigDecimal("0e512"), 0),
entry(new BigDecimal("10.000000000000000000000000000000000"), 10));
for (var testCase : successCases.entrySet()) {
BigDecimal bd = testCase.getKey();
int expected = testCase.getValue();
try {
int intValueExact = bd.intValueExact();
if (expected != intValueExact ||
intValueExact != simpleIntValueExact(bd)) {
failures++;
System.err.println("Unexpected intValueExact result " + intValueExact +
" on " + bd);
}
} catch (Exception e) {
failures++;
System.err.println("Error on " + bd + "\tException message:" + e.getMessage());
}
}
return failures;
}
private static int intValueExactExceptional() {
int failures = 0;
List<BigDecimal> exceptionalCases =
List.of(new BigDecimal("2147483648"), // Integer.MAX_VALUE + 1
new BigDecimal("2147483648.0"),
new BigDecimal("2147483648.00"),
new BigDecimal("-2147483649"), // Integer.MIN_VALUE - 1
new BigDecimal("-2147483649.1"),
new BigDecimal("-2147483649.01"),
new BigDecimal("9999999999999999999999999999999"),
new BigDecimal("10000000000000000000000000000000"),
new BigDecimal("0.99"),
new BigDecimal("0.999999999999999999999"));
for (BigDecimal bd : exceptionalCases) {
try {
int intValueExact = bd.intValueExact();
failures++;
System.err.println("Unexpected non-exceptional intValueExact on " + bd);
} catch (ArithmeticException e) {
// Success;
}
}
return failures;
}
}

View file

@ -0,0 +1,352 @@
/*
* Copyright (c) 2003, 2025, 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 4904082 4917089 6337226 6378503
* @summary Tests that integral division and related methods return the proper result and scale.
*/
import java.math.*;
public class IntegralDivisionTests {
static int dividetoIntegralValueTests() {
int failures = 0;
// Exact integer quotient should have the same results from
// the exact divide and dividetoIntegralValue
// Rounded results
BigDecimal [][] moreTestCases = {
{new BigDecimal("11003"), new BigDecimal("10"), new BigDecimal("1100")},
{new BigDecimal("11003"), new BigDecimal("1e1"), new BigDecimal("1100.0")},
{new BigDecimal("1e9"), new BigDecimal("1"), new BigDecimal("1e9")},
{new BigDecimal("1e9"), new BigDecimal("1.00"), new BigDecimal("1e9")},
{new BigDecimal("1e9"), new BigDecimal("0.1"), new BigDecimal("1e10")},
{new BigDecimal("10e8"), new BigDecimal("0.1"), new BigDecimal("10e9")},
{new BigDecimal("400e1"), new BigDecimal("5"), new BigDecimal("80e1")},
{new BigDecimal("400e1"), new BigDecimal("4.999999999"), new BigDecimal("8e2")},
{new BigDecimal("40e2"), new BigDecimal("5"), new BigDecimal("8e2")},
{BigDecimal.valueOf(1, Integer.MIN_VALUE),
BigDecimal.valueOf(1, -(Integer.MAX_VALUE & 0x7fffff00)),
BigDecimal.valueOf(1, -256)},
};
for(BigDecimal [] testCase: moreTestCases) {
BigDecimal quotient;
if (! (quotient=testCase[0].divideToIntegralValue(testCase[1])).equals(testCase[2]) ){
failures++;
// BigDecimal exact = testCase[0].divide(testCase[1]);
System.err.println();
System.err.println("dividend = " + testCase[0] + " scale = " + testCase[0].scale());
System.err.println("divisor = " + testCase[1] + " scale = " + testCase[1].scale());
System.err.println("quotient = " + quotient + " scale = " + quotient.scale());
System.err.println("expected = " + testCase[2] + " scale = " + testCase[2].scale());
// System.err.println("exact = " + exact + " scale = " + exact.scale());
}
}
return failures;
}
static int dividetoIntegralValueRoundedTests() {
int failures = 0;
BigDecimal dividend = new BigDecimal("11003");
BigDecimal divisor = new BigDecimal("10");
BigDecimal [] quotients = { // Expected results with precision =
new BigDecimal("1100"), // 0
null, // 1
new BigDecimal("11e2"), // 2
new BigDecimal("110e1"), // 3
new BigDecimal("1100"), // 4
};
failures += divideContextTestPrecs(dividend, divisor, quotients);
dividend = new BigDecimal("11003");
divisor = new BigDecimal("1e1");
BigDecimal [] quotients2 = { // Expected results with precision =
new BigDecimal("1100.0"), // 0
null, // 1
new BigDecimal("11e2"), // 2
new BigDecimal("110e1"), // 3
new BigDecimal("1100"), // 4
new BigDecimal("1100.0"), // 5
};
failures += divideContextTestPrecs(dividend, divisor, quotients2);
dividend = new BigDecimal("1230000");
divisor = new BigDecimal("100");
BigDecimal [] quotients3 = { // Expected results with precision =
new BigDecimal("12300"), // 0
null, // 1
null, // 2
new BigDecimal("123e2"), // 3
new BigDecimal("1230e1"), // 4
new BigDecimal("12300"), // 5
};
failures += divideContextTestPrecs(dividend, divisor, quotients3);
dividend = new BigDecimal("33");
divisor = new BigDecimal("3");
BigDecimal [] quotients4 = { // Expected results with precision =
new BigDecimal("11"), // 0
null, // 1
new BigDecimal("11"), // 2
new BigDecimal("11"), // 3
};
failures += divideContextTestPrecs(dividend, divisor, quotients4);
dividend = new BigDecimal("34");
divisor = new BigDecimal("3");
BigDecimal [] quotients5 = { // Expected results with precision =
new BigDecimal("11"), // 0
null, // 1
new BigDecimal("11"), // 2
new BigDecimal("11"), // 3
};
failures += divideContextTestPrecs(dividend, divisor, quotients5);
return failures;
}
static int divideContextTestPrecs(BigDecimal dividend,
BigDecimal divisor,
BigDecimal[] quotients)
{
int failures = 0;
for(int i = 0; i < quotients.length; i++) {
BigDecimal result = null;
BigDecimal quotient = quotients[i];
try {
result = dividend.divideToIntegralValue(divisor,
new MathContext(i, RoundingMode.DOWN));
} catch (ArithmeticException e) {
if (quotient != null) {
failures++;
System.err.println();
System.err.println("Unexpected exception:");
System.err.println("dividend = " + dividend + " scale = " + dividend.scale());
System.err.println("divisor = " + divisor + " scale = " + divisor.scale());
System.err.println("expected = " + quotient + " scale = " + quotient.scale());
}
}
if (quotient != null) {
if (! result.equals(quotient)) {
failures++;
System.err.println();
System.err.println("Unexpected result:");
System.err.println("dividend = " + dividend + " scale = " + dividend.scale());
System.err.println("divisor = " + divisor + " scale = " + divisor.scale());
System.err.println("quotient = " + result + " scale = " + result.scale());
System.err.println("expected = " + quotient + " scale = " + quotient.scale());
System.err.println("precision = " + i);
}
} else {
if (result != null) {
failures++;
System.err.println();
System.err.println("Unexpected unexceptional result:");
System.err.println("dividend = " + dividend + " scale = " + dividend.scale());
System.err.println("divisor = " + divisor + " scale = " + divisor.scale());
System.err.println("quotient = " + result + " scale = " + result.scale());
System.err.println("precision = " + i);
}
}
}
return failures;
}
static int divideContextTests(BigDecimal dividend,
BigDecimal divisor,
BigDecimal expected,
MathContext mc) {
int failures = 0;
failures += divideContextTest(dividend, divisor, expected, mc);
failures += divideContextTest(dividend.negate(), divisor.negate(), expected, mc);
if (expected != null) {
failures += divideContextTest(dividend.negate(), divisor, expected.negate(), mc);
failures += divideContextTest(dividend, divisor.negate(), expected.negate(), mc);
}
return failures;
}
static int divideContextTest(BigDecimal dividend,
BigDecimal divisor,
BigDecimal expected,
MathContext mc)
{
int failures = 0;
BigDecimal result = null;
try {
result = dividend.divideToIntegralValue(divisor, mc);
} catch (ArithmeticException e) {
if (expected != null) {
failures++;
System.err.println();
System.err.println("Unexpected exception:");
System.err.println("dividend = " + dividend + " scale = " + dividend.scale());
System.err.println("divisor = " + divisor + " scale = " + divisor.scale());
System.err.println("expected = " + expected + " scale = " + expected.scale());
System.err.println("MathContext = " + mc);
}
}
if (expected != null) {
if (! result.equals(expected)) {
failures++;
System.err.println();
System.err.println("Unexpected result:");
System.err.println("dividend = " + dividend + " scale = " + dividend.scale());
System.err.println("divisor = " + divisor + " scale = " + divisor.scale());
System.err.println("expected = " + expected + " scale = " + expected.scale());
System.err.println("result = " + result + " scale = " + result.scale());
System.err.println("MathContext = " + mc);
}
} else {
if (result != null) {
failures++;
System.err.println();
System.err.println("Unexpected unexceptional result:");
System.err.println("dividend = " + dividend + " scale = " + dividend.scale());
System.err.println("divisor = " + divisor + " scale = " + divisor.scale());
System.err.println("quotient = " + result + " scale = " + result.scale());
System.err.println("MathConext = " + mc);
}
}
return failures;
}
static int dividetoIntegralValueScalingTests() {
int failures = 0;
BigDecimal dividend = new BigDecimal("123456789000");
BigDecimal divisor = BigDecimal.ONE;
BigDecimal expected = new BigDecimal("123456789e3");
MathContext mc = new MathContext(9,RoundingMode.DOWN);
failures += divideContextTests(dividend, divisor, expected, mc);
// 100/3 = 33 remainder 1
int [] precisions = {0, 2, 3, 4};
dividend = new BigDecimal(100);
divisor = new BigDecimal(3);
expected = new BigDecimal(33);
for(RoundingMode rm: RoundingMode.values())
for(int precision: precisions) {
failures += divideContextTests(dividend, divisor, expected,
new MathContext(precision, rm));
}
// 123000/10 = 12300 remainder 0
dividend = new BigDecimal(123000);
divisor = new BigDecimal(10);
int[] precisions1 = {0, 1, 2, 3, 4, 5};
BigDecimal[] expected1 = {
new BigDecimal("12300"),
null,
null,
new BigDecimal("123e2"),
new BigDecimal("1230e1"),
new BigDecimal("12300"),
};
for(RoundingMode rm: RoundingMode.values())
for(int i = 0; i < precisions1.length; i++) {
failures += divideContextTests(dividend, divisor,
expected1[i],
new MathContext(precisions1[i], rm));
}
// 123e3/10 = 123e2 remainder 0
dividend = new BigDecimal("123e3");
divisor = new BigDecimal(10);
int[] precisions2 = {0, 1, 2, 3, 4, 5};
BigDecimal[] expected2 = {
new BigDecimal("123e2"),
null,
null,
new BigDecimal("123e2"),
new BigDecimal("123e2"),
new BigDecimal("123e2"),
};
for(RoundingMode rm: RoundingMode.values())
for(int i = 0; i < precisions2.length; i++) {
failures += divideContextTests(dividend, divisor,
expected2[i],
new MathContext(precisions2[i], rm));
}
// 123000/1e1 = 12300.0 remainder 0
dividend = new BigDecimal("123000");
divisor = new BigDecimal("1e1");
int[] precisions3 = {0, 1, 2, 3, 4, 5, 6};
BigDecimal[] expected3 = {
new BigDecimal("12300.0"),
null,
null,
new BigDecimal("123e2"),
new BigDecimal("1230e1"),
new BigDecimal("12300"),
new BigDecimal("12300.0"),
};
for(RoundingMode rm: RoundingMode.values())
for(int i = 0; i < precisions3.length; i++) {
failures += divideContextTests(dividend, divisor,
expected3[i],
new MathContext(precisions3[i], rm));
}
return failures;
}
public static void main(String argv[]) {
int failures = 0;
failures += dividetoIntegralValueTests();
failures += dividetoIntegralValueRoundedTests();
failures += dividetoIntegralValueScalingTests();
if (failures > 0) {
System.err.println("Encountered " + failures +
" failures while testing integral division.");
throw new RuntimeException();
}
}
}

View file

@ -0,0 +1,241 @@
/*
* Copyright (c) 2019, 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 8211936
* @summary Tests of BigDecimal.intValue() and BigDecimal.longValue()
*/
import java.math.BigDecimal;
import java.util.Map;
public class IntegralValueTests {
public static void main(String... args) {
int failures =
integralValuesTest(INT_VALUES, true) +
integralValuesTest(LONG_VALUES, false);
if (failures != 0) {
throw new RuntimeException
("Incurred " + failures + " failures for {int,long}Value().");
}
}
private static final Map<BigDecimal, Number> INT_VALUES =
Map.ofEntries(
// 2**31 - 1
Map.entry(new BigDecimal("2147483647"), Integer.MAX_VALUE),
Map.entry(new BigDecimal("2147483647.0"), Integer.MAX_VALUE),
Map.entry(new BigDecimal("2147483647.00"), Integer.MAX_VALUE),
Map.entry(new BigDecimal("-2147483647"), -Integer.MAX_VALUE),
Map.entry(new BigDecimal("-2147483647.0"), -Integer.MAX_VALUE),
// -2**31
Map.entry(new BigDecimal("-2147483648"), Integer.MIN_VALUE),
Map.entry(new BigDecimal("-2147483648.1"), Integer.MIN_VALUE),
Map.entry(new BigDecimal("-2147483648.01"), Integer.MIN_VALUE),
// -2**31 + 1 truncation to 2**31 - 1
Map.entry(new BigDecimal("-2147483649"), Integer.MAX_VALUE),
// 2**64 - 1 truncation to 1
Map.entry(new BigDecimal("4294967295"), -1),
// 2**64 truncation to 0
Map.entry(new BigDecimal("4294967296"), 0),
// Fast path truncation to 0
Map.entry(new BigDecimal("1e32"), 0),
// Slow path truncation to -2**31
Map.entry(new BigDecimal("1e31"), Integer.MIN_VALUE),
// Slow path
Map.entry(new BigDecimal("1e0"), 1),
// Fast path round to 0
Map.entry(new BigDecimal("9e-1"), 0),
// Some random values
Map.entry(new BigDecimal("900e-1"), 90), // Increasing negative exponents
Map.entry(new BigDecimal("900e-2"), 9),
Map.entry(new BigDecimal("900e-3"), 0),
// Fast path round to 0
Map.entry(new BigDecimal("123456789e-9"), 0),
// Slow path round to 1
Map.entry(new BigDecimal("123456789e-8"), 1),
// Increasing positive exponents
Map.entry(new BigDecimal("10000001e1"), 100000010),
Map.entry(new BigDecimal("10000001e10"), -1315576832),
Map.entry(new BigDecimal("10000001e100"), 0),
Map.entry(new BigDecimal("10000001e1000"), 0),
Map.entry(new BigDecimal("10000001e10000"), 0),
Map.entry(new BigDecimal("10000001e100000"), 0),
Map.entry(new BigDecimal("10000001e1000000"), 0),
Map.entry(new BigDecimal("10000001e10000000"), 0),
Map.entry(new BigDecimal("10000001e100000000"), 0),
Map.entry(new BigDecimal("10000001e1000000000"), 0),
// Increasing negative exponents
Map.entry(new BigDecimal("10000001e-1"), 1000000),
Map.entry(new BigDecimal("10000001e-10"), 0),
Map.entry(new BigDecimal("10000001e-100"), 0),
Map.entry(new BigDecimal("10000001e-1000"), 0),
Map.entry(new BigDecimal("10000001e-10000"), 0),
Map.entry(new BigDecimal("10000001e-100000"), 0),
Map.entry(new BigDecimal("10000001e-1000000"), 0),
Map.entry(new BigDecimal("10000001e-10000000"), 0),
Map.entry(new BigDecimal("10000001e-100000000"), 0),
Map.entry(new BigDecimal("10000001e-1000000000"), 0),
// Currency calculation to 4 places
Map.entry(new BigDecimal("12345.0001"), 12345),
Map.entry(new BigDecimal("12345.9999"), 12345),
Map.entry(new BigDecimal("-12345.0001"), -12345),
Map.entry(new BigDecimal("-12345.9999"), -12345));
private static final Map<BigDecimal, Number> LONG_VALUES =
Map.ofEntries(
// 2**63 - 1
Map.entry(new BigDecimal("9223372036854775807"), Long.MAX_VALUE),
Map.entry(new BigDecimal("9223372036854775807.0"), Long.MAX_VALUE),
Map.entry(new BigDecimal("9223372036854775807.00"), Long.MAX_VALUE),
// 2**63 truncation to -2**63
Map.entry(new BigDecimal("-9223372036854775808"), Long.MIN_VALUE),
Map.entry(new BigDecimal("-9223372036854775808.1"), Long.MIN_VALUE),
Map.entry(new BigDecimal("-9223372036854775808.01"), Long.MIN_VALUE),
// -2**63 + 1 truncation to 2**63 - 1
Map.entry(new BigDecimal("-9223372036854775809"), 9223372036854775807L),
// 2**64 - 1 truncation to -1
Map.entry(new BigDecimal("18446744073709551615"), -1L),
// 2**64 truncation to 0
Map.entry(new BigDecimal("18446744073709551616"), 0L),
// Slow path truncation to -2**63
Map.entry(new BigDecimal("1e63"), -9223372036854775808L),
Map.entry(new BigDecimal("-1e63"), -9223372036854775808L),
// Fast path with larger magnitude scale
Map.entry(new BigDecimal("1e64"), 0L),
Map.entry(new BigDecimal("-1e64"), 0L),
Map.entry(new BigDecimal("1e65"), 0L),
Map.entry(new BigDecimal("-1e65"), 0L),
// Slow path
Map.entry(new BigDecimal("1e0"), 1L),
// Fast path round to 0
Map.entry(new BigDecimal("9e-1"), 0L),
// Some random values
Map.entry(new BigDecimal("900e-1"), 90L), // Increasing negative exponents
Map.entry(new BigDecimal("900e-2"), 9L),
Map.entry(new BigDecimal("900e-3"), 0L),
// Fast path round to 0
Map.entry(new BigDecimal("123456789e-9"), 0L),
// Slow path round to 1
Map.entry(new BigDecimal("123456789e-8"), 1L),
// Increasing positive exponents
Map.entry(new BigDecimal("10000001e1"), 100000010L),
Map.entry(new BigDecimal("10000001e10"), 100000010000000000L),
Map.entry(new BigDecimal("10000001e100"), 0L),
Map.entry(new BigDecimal("10000001e1000"), 0L),
Map.entry(new BigDecimal("10000001e10000"), 0L),
Map.entry(new BigDecimal("10000001e100000"), 0L),
Map.entry(new BigDecimal("10000001e1000000"), 0L),
Map.entry(new BigDecimal("10000001e10000000"), 0L),
Map.entry(new BigDecimal("10000001e100000000"), 0L),
Map.entry(new BigDecimal("10000001e1000000000"), 0L),
// Increasing negative exponents
Map.entry(new BigDecimal("10000001e-1"), 1000000L),
Map.entry(new BigDecimal("10000001e-10"), 0L),
Map.entry(new BigDecimal("10000001e-100"), 0L),
Map.entry(new BigDecimal("10000001e-1000"), 0L),
Map.entry(new BigDecimal("10000001e-10000"), 0L),
Map.entry(new BigDecimal("10000001e-100000"), 0L),
Map.entry(new BigDecimal("10000001e-1000000"), 0L),
Map.entry(new BigDecimal("10000001e-10000000"), 0L),
Map.entry(new BigDecimal("10000001e-100000000"), 0L),
Map.entry(new BigDecimal("10000001e-1000000000"), 0L),
// Currency calculation to 4 places
Map.entry(new BigDecimal("12345.0001"), 12345L),
Map.entry(new BigDecimal("12345.9999"), 12345L),
Map.entry(new BigDecimal("-12345.0001"), -12345L),
Map.entry(new BigDecimal("-12345.9999"), -12345L));
private static int integralValuesTest(Map<BigDecimal, Number> v, boolean isInt) {
System.err.format("Testing %s%n", isInt ? "Integer" : "Long");
int failures = 0;
for (var testCase : v.entrySet()) {
BigDecimal bd = testCase.getKey();
Number expected = testCase.getValue();
try {
if (isInt) {
int intValue = bd.intValue();
if (intValue != (int)expected) {
failures += reportError(bd, expected, intValue, isInt);
}
} else {
long longValue = bd.longValue();
if (longValue != (long)expected) {
failures += reportError(bd, expected, longValue, isInt);
}
}
} catch (Exception e) {
failures++;
System.err.format("Unexpected exception %s for %s%n",
e, bd.toString());
}
}
return failures;
}
private static int reportError(BigDecimal bd, Number expected, long longValue, boolean isInt) {
System.err.format("For %s, scale=%d, expected %d, actual %d, simple %d%n",
bd.toString(), bd.scale(),
(isInt ? (Integer) expected : (Long) expected ),
longValue,
(isInt ? simpleIntValue(bd): simpleLongValue(bd) ));
return 1;
}
private static long simpleLongValue(BigDecimal bd) {
return bd.toBigInteger().longValue();
}
private static int simpleIntValue(BigDecimal bd) {
return bd.toBigInteger().intValue();
}
}

View file

@ -0,0 +1,144 @@
/*
* Copyright (c) 2005, 2023, 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 6806261 8211936 8305343
* @summary Tests of BigDecimal.longValueExact
*/
import java.math.*;
import java.util.List;
import java.util.Map;
import static java.util.Map.entry;
public class LongValueExactTests {
public static void main(String... args) {
int failures = 0;
failures += longValueExactSuccessful();
failures += longValueExactExceptional();
failures += longValueExactExceptional8305343();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing longValueExact.");
}
}
private static long simpleLongValueExact(BigDecimal bd) {
return bd.toBigIntegerExact().longValue();
}
private static int longValueExactSuccessful() {
int failures = 0;
// Strings used to create BigDecimal instances on which invoking
// longValueExact() will succeed.
Map<BigDecimal, Long> successCases =
Map.ofEntries(entry(new BigDecimal("9223372036854775807"), Long.MAX_VALUE), // 2^63 -1
entry(new BigDecimal("9223372036854775807.0"), Long.MAX_VALUE),
entry(new BigDecimal("9223372036854775807.00"), Long.MAX_VALUE),
entry(new BigDecimal("-9223372036854775808"), Long.MIN_VALUE), // -2^63
entry(new BigDecimal("-9223372036854775808.0"), Long.MIN_VALUE),
entry(new BigDecimal("-9223372036854775808.00"),Long.MIN_VALUE),
entry(new BigDecimal("1e0"), 1L),
entry(new BigDecimal(BigInteger.ONE, -18), 1_000_000_000_000_000_000L),
entry(new BigDecimal("0e13"), 0L), // Fast path zero
entry(new BigDecimal("0e64"), 0L),
entry(new BigDecimal("0e1024"), 0L),
entry(new BigDecimal("10.000000000000000000000000000000000"), 10L));
for (var testCase : successCases.entrySet()) {
BigDecimal bd = testCase.getKey();
long expected = testCase.getValue();
try {
long longValueExact = bd.longValueExact();
if (expected != longValueExact ||
longValueExact != simpleLongValueExact(bd)) {
failures++;
System.err.println("Unexpected longValueExact result " + longValueExact +
" on " + bd);
}
} catch (Exception e) {
failures++;
System.err.println("Error on " + bd + "\tException message:" + e.getMessage());
}
}
return failures;
}
private static int longValueExactExceptional() {
int failures = 0;
List<BigDecimal> exceptionalCases =
List.of(new BigDecimal("9223372036854775808"), // Long.MAX_VALUE + 1
new BigDecimal("9223372036854775808.0"),
new BigDecimal("9223372036854775808.00"),
new BigDecimal("-9223372036854775809"), // Long.MIN_VALUE - 1
new BigDecimal("-9223372036854775808.1"),
new BigDecimal("-9223372036854775808.01"),
new BigDecimal("9999999999999999999"),
new BigDecimal("10000000000000000000"),
new BigDecimal("0.99"),
new BigDecimal("0.999999999999999999999"));
for (BigDecimal bd : exceptionalCases) {
try {
long longValueExact = bd.longValueExact();
failures++;
System.err.println("Unexpected non-exceptional longValueExact on " + bd);
} catch (ArithmeticException e) {
// Success;
}
}
return failures;
}
private static int longValueExactExceptional8305343() {
int failures = 0;
List<BigDecimal> exceptionalCases =
List.of(new BigDecimal("1e" + (Integer.MAX_VALUE - 1)),
new BigDecimal("1e" + (Integer.MAX_VALUE))
);
for (BigDecimal bd : exceptionalCases) {
try {
bd.longValueExact();
failures++;
System.err.println("Unexpected non-exceptional longValueExact on " + bd);
} catch (ArithmeticException e) {
if (!e.getMessage().toLowerCase().contains("overflow")) {
failures++;
System.err.println("Unexpected non-exceptional longValueExact on " + bd);
}
}
}
return failures;
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright (c) 2022, 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 8289260
*/
import java.math.BigDecimal;
public class MovePointTests {
public static void main(String argv[]) {
BigDecimal bd;
bd = BigDecimal.valueOf(1, -3);
checkNotIdentical(bd, bd.movePointLeft(0));
checkNotIdentical(bd, bd.movePointRight(0));
bd = BigDecimal.valueOf(1, 0);
checkIdentical(bd, bd.movePointLeft(0));
checkIdentical(bd, bd.movePointRight(0));
bd = BigDecimal.valueOf(1, 3);
checkIdentical(bd, bd.movePointLeft(0));
checkIdentical(bd, bd.movePointRight(0));
bd = BigDecimal.valueOf(1, -3);
checkNotEquals(bd, bd.movePointLeft(1));
checkNotEquals(bd, bd.movePointLeft(-1));
checkNotEquals(bd, bd.movePointRight(1));
checkNotEquals(bd, bd.movePointRight(-1));
bd = BigDecimal.valueOf(1, 0);
checkNotEquals(bd, bd.movePointLeft(1));
checkNotEquals(bd, bd.movePointLeft(-1));
checkNotEquals(bd, bd.movePointRight(1));
checkNotEquals(bd, bd.movePointRight(-1));
bd = BigDecimal.valueOf(1, 3);
checkNotEquals(bd, bd.movePointLeft(1));
checkNotEquals(bd, bd.movePointLeft(-1));
checkNotEquals(bd, bd.movePointRight(1));
checkNotEquals(bd, bd.movePointRight(-1));
bd = BigDecimal.valueOf(1, -3);
checkNotEquals(bd, bd.movePointLeft(10));
checkNotEquals(bd, bd.movePointLeft(-10));
checkNotEquals(bd, bd.movePointRight(10));
checkNotEquals(bd, bd.movePointRight(-10));
bd = BigDecimal.valueOf(1, 0);
checkNotEquals(bd, bd.movePointLeft(10));
checkNotEquals(bd, bd.movePointLeft(-10));
checkNotEquals(bd, bd.movePointRight(10));
checkNotEquals(bd, bd.movePointRight(-10));
bd = BigDecimal.valueOf(1, 3);
checkNotEquals(bd, bd.movePointLeft(10));
checkNotEquals(bd, bd.movePointLeft(-10));
checkNotEquals(bd, bd.movePointRight(10));
checkNotEquals(bd, bd.movePointRight(-10));
}
private static void checkIdentical(BigDecimal bd, BigDecimal res) {
if (res != bd) { // intentionally !=
throw new RuntimeException("Unexpected result " +
bd + " != " + res);
}
}
private static void checkNotIdentical(BigDecimal bd, BigDecimal res) {
if (res == bd) { // intentionally ==
throw new RuntimeException("Unexpected result " +
bd + " == " + res);
}
}
private static void checkNotEquals(BigDecimal bd, BigDecimal res) {
if (res.equals(bd)) {
throw new RuntimeException("Unexpected result " +
bd + ".equals(" + res + ")");
}
}
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2006, 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 6850606
* @summary Test BigDecimal.multiply(BigDecimal)
* @author xlu
*/
import java.math.*;
import static java.math.BigDecimal.*;
public class MultiplyTests {
private static int multiplyTests() {
int failures = 0;
BigDecimal[] bd1 = {
new BigDecimal("123456789"),
new BigDecimal("1234567898"),
new BigDecimal("12345678987")
};
BigDecimal[] bd2 = {
new BigDecimal("987654321"),
new BigDecimal("8987654321"),
new BigDecimal("78987654321")
};
// Two dimensonal array recording bd1[i] * bd2[j] &
// 0 <= i <= 2 && 0 <= j <= 2;
BigDecimal[][] expectedResults = {
{new BigDecimal("121932631112635269"),
new BigDecimal("1109586943112635269"),
new BigDecimal("9751562173112635269")
},
{ new BigDecimal("1219326319027587258"),
new BigDecimal("11095869503027587258"),
new BigDecimal("97515622363027587258")
},
{ new BigDecimal("12193263197189452827"),
new BigDecimal("110958695093189452827"),
new BigDecimal("975156224183189452827")
}
};
for (int i = 0; i < bd1.length; i++) {
for (int j = 0; j < bd2.length; j++) {
if (!bd1[i].multiply(bd2[j]).equals(expectedResults[i][j])) {
failures++;
}
}
}
BigDecimal x = BigDecimal.valueOf(8L, 1);
BigDecimal xPower = BigDecimal.valueOf(-1L);
try {
for (int i = 0; i < 100; i++) {
xPower = xPower.multiply(x);
}
} catch (Exception ex) {
failures++;
}
return failures;
}
public static void main(String[] args) {
int failures = 0;
failures += multiplyTests();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing multiply.");
}
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2005, 2025, 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 6325535
* @summary Test for the rounding behavior of negate(MathContext)
*/
import java.math.*;
public class NegateTests {
static BigDecimal negateThenRound(BigDecimal bd, MathContext mc) {
return bd.negate().plus(mc);
}
static BigDecimal absThenRound(BigDecimal bd, MathContext mc) {
return bd.abs().plus(mc);
}
static int negateTest(BigDecimal[][] testCases, MathContext mc) {
int failures = 0;
for (BigDecimal [] testCase : testCases) {
BigDecimal bd = testCase[0];
BigDecimal neg1 = bd.negate(mc);
BigDecimal neg2 = negateThenRound(bd, mc);
BigDecimal expected = testCase[1];
if (! neg1.equals(expected) ) {
failures++;
System.err.println("(" + bd + ").negate(" + mc + ") => " +
neg1 + " != expected " + expected);
}
if (! neg1.equals(neg2) ) {
failures++;
System.err.println("(" + bd + ").negate(" + mc + ") => " +
neg1 + " != ntr " + neg2);
}
// Test abs consistency
BigDecimal abs = bd.abs(mc);
BigDecimal expectedAbs = absThenRound(bd,mc);
if (! abs.equals(expectedAbs) ) {
failures++;
System.err.println("(" + bd + ").abs(" + mc + ") => " +
abs + " != atr " + expectedAbs);
}
}
return failures;
}
static int negateTests() {
int failures = 0;
BigDecimal [][] testCasesCeiling = {
{new BigDecimal("1.3"), new BigDecimal("-1")},
{new BigDecimal("-1.3"), new BigDecimal("2")},
};
failures += negateTest(testCasesCeiling,
new MathContext(1, RoundingMode.CEILING));
BigDecimal [][] testCasesFloor = {
{new BigDecimal("1.3"), new BigDecimal("-2")},
{new BigDecimal("-1.3"), new BigDecimal("1")},
};
failures += negateTest(testCasesFloor,
new MathContext(1, RoundingMode.FLOOR));
return failures;
}
public static void main(String argv[]) {
int failures = 0;
failures += negateTests();
if (failures > 0 )
throw new RuntimeException("Incurred " + failures + " failures" +
" testing the negate and/or abs.");
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2003, 2025, 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 4916097
* @summary Some exponent over/undeflow tests for the pow method
*/
import java.math.*;
public class PowTests {
static int zeroAndOneTests() {
int failures = 0;
BigDecimal[][] testCases = {
{BigDecimal.valueOf(0, Integer.MAX_VALUE), new BigDecimal(0), BigDecimal.valueOf(1, 0)},
{BigDecimal.valueOf(0, Integer.MAX_VALUE), new BigDecimal(1), BigDecimal.valueOf(0, Integer.MAX_VALUE)},
{BigDecimal.valueOf(0, Integer.MAX_VALUE), new BigDecimal(2), BigDecimal.valueOf(0, Integer.MAX_VALUE)},
{BigDecimal.valueOf(0, Integer.MAX_VALUE), new BigDecimal(999999999), BigDecimal.valueOf(0, Integer.MAX_VALUE)},
{BigDecimal.valueOf(0, Integer.MIN_VALUE), new BigDecimal(0), BigDecimal.valueOf(1, 0)},
{BigDecimal.valueOf(0, Integer.MIN_VALUE), new BigDecimal(1), BigDecimal.valueOf(0, Integer.MIN_VALUE)},
{BigDecimal.valueOf(0, Integer.MIN_VALUE), new BigDecimal(2), BigDecimal.valueOf(0, Integer.MIN_VALUE)},
{BigDecimal.valueOf(0, Integer.MIN_VALUE), new BigDecimal(999999999), BigDecimal.valueOf(0, Integer.MIN_VALUE)},
{BigDecimal.valueOf(1, Integer.MAX_VALUE), new BigDecimal(0), BigDecimal.valueOf(1, 0)},
{BigDecimal.valueOf(1, Integer.MAX_VALUE), new BigDecimal(1), BigDecimal.valueOf(1, Integer.MAX_VALUE)},
{BigDecimal.valueOf(1, Integer.MAX_VALUE), new BigDecimal(2), null}, // overflow
{BigDecimal.valueOf(1, Integer.MAX_VALUE), new BigDecimal(999999999), null}, // overflow
{BigDecimal.valueOf(1, Integer.MIN_VALUE), new BigDecimal(0), BigDecimal.valueOf(1, 0)},
{BigDecimal.valueOf(1, Integer.MIN_VALUE), new BigDecimal(1), BigDecimal.valueOf(1, Integer.MIN_VALUE)},
{BigDecimal.valueOf(1, Integer.MIN_VALUE), new BigDecimal(2), null}, // underflow
{BigDecimal.valueOf(1, Integer.MIN_VALUE), new BigDecimal(999999999), null}, // underflow
};
for(BigDecimal[] testCase: testCases) {
int exponent = testCase[1].intValueExact();
BigDecimal result;
try{
result = testCase[0].pow(exponent);
if (!result.equals(testCase[2]) ) {
failures++;
System.err.println("Unexpected result while raising " +
testCase[0] +
" to the " + exponent + " power; expected " +
testCase[2] + ", got " + result + ".");
}
} catch (ArithmeticException e) {
if (testCase[2] != null) {
failures++;
System.err.println("Unexpected exception while raising " + testCase[0] +
" to the " + exponent + " power.");
}
}
}
return failures;
}
public static void main(String argv[]) {
int failures = 0;
failures += zeroAndOneTests();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing pow methods.");
}
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2009, 2025, 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 1234567
* @summary Test that precision() is computed properly.
*/
import java.math.*;
import static java.math.BigDecimal.*;
public class PrecisionTests {
private static BigDecimal NINE = valueOf(9);
public static void main(String argv[]) {
int failures = 0;
// Smallest and largest values of a given length
BigDecimal[] testValues = {
valueOf(1), valueOf(9),
};
failures += testPrecision(new BigDecimal(0), 1);
for(int i = 1; i < 100; i++) {
for(BigDecimal bd : testValues) {
failures += testPrecision(bd, i);
failures += testPrecision(bd.negate(), i);
}
testValues[0] = testValues[0].multiply(TEN);
testValues[1] = testValues[1].multiply(TEN).add(NINE);
}
// The following test tries to cover testings for precision of long values
BigDecimal[] randomTestValues = {
valueOf(2147483648L), // 2^31: 10 digits
valueOf(-2147483648L), // -2^31: 10 digits
valueOf(98893745455L), // random: 11 digits
valueOf(3455436789887L), // random: 13 digits
valueOf(140737488355328L), // 2^47: 15 digits
valueOf(-140737488355328L), // -2^47: 15 digits
valueOf(7564232235739573L), // random: 16 digits
valueOf(25335434990002322L), // random: 17 digits
valueOf(9223372036854775807L), // 2^63 - 1: 19 digits
valueOf(-9223372036854775807L) // -2^63 + 1: 19 digits
};
// The array below contains the expected precision of the above numbers
int[] expectedPrecision = {10, 10, 11, 13, 15, 15, 16, 17, 19, 19};
for (int i = 0; i < randomTestValues.length; i++) {
failures += testPrecision(randomTestValues[i], expectedPrecision[i]);
}
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing precision.");
}
}
private static int testPrecision(BigDecimal bd, int expected) {
int precision = bd.precision();
// System.out.printf("Testing %s, expected %d%n", bd, expected);
if (precision != expected) {
System.err.printf("For (%s).precision expected %d, got %d%n",
bd, expected, precision);
return 1;
}
return 0;
}
}

View file

@ -0,0 +1,245 @@
/*
* Copyright (c) 2003, 2018, 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 7036582
* @summary Some new tests for the add method and constructor with MathContext.
* @run main RangeTests
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 RangeTests
* @author Sergey V. Kuksenko
*/
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
public class RangeTests {
private static int addTest(BigDecimal arg1, BigDecimal arg2, BigDecimal expectedResult) {
int failures = 0;
BigDecimal result = arg1.add(arg2);
if (!result.equals(expectedResult)) {
System.out.println("Sum:" +
arg1 + " + " +
arg2 + " == " +
result + "; expected " +
expectedResult
);
failures++;
}
result = arg2.add(arg1);
if (!result.equals(expectedResult)) {
System.out.println("Sum:" +
arg2 + " + " +
arg1 + " == " +
result + "; expected " +
expectedResult
);
failures++;
}
return failures;
}
/*
* Test BigDecimal.add(BigDecimal) when values are withing different ranges:
* 1. within 32 bits
* 2. within 64 bits
* 3. outside 64 bits.
*/
private static int addBoundaryTest() {
int failures = 0;
failures += addTest(
new BigDecimal("85070591730234615847396907784232501249"),
BigDecimal.valueOf(0),
new BigDecimal("85070591730234615847396907784232501249") );
failures += addTest(
new BigDecimal("-85070591730234615847396907784232501249"),
BigDecimal.valueOf(0),
new BigDecimal("-85070591730234615847396907784232501249") );
failures += addTest(
new BigDecimal("85070591730234615847396907784232501249"),
BigDecimal.valueOf(1),
new BigDecimal("85070591730234615847396907784232501250") );
failures += addTest(
new BigDecimal("85070591730234615847396907784232501249"),
BigDecimal.valueOf(-1),
new BigDecimal("85070591730234615847396907784232501248") );
failures += addTest(
new BigDecimal("-85070591730234615847396907784232501250"),
BigDecimal.valueOf(-1),
new BigDecimal("-85070591730234615847396907784232501251") );
failures += addTest(
new BigDecimal("-85070591730234615847396907784232501249"),
BigDecimal.valueOf(1),
new BigDecimal("-85070591730234615847396907784232501248") );
failures += addTest(
new BigDecimal("147573952589676412927"),
BigDecimal.valueOf(Integer.MAX_VALUE),
new BigDecimal("147573952591823896574") );
failures += addTest(
new BigDecimal("-147573952589676412927"),
BigDecimal.valueOf(Integer.MAX_VALUE),
new BigDecimal("-147573952587528929280") );
failures += addTest(
new BigDecimal("79228162514264337593543950335"),
BigDecimal.valueOf(999),
new BigDecimal("79228162514264337593543951334") );
failures += addTest(
new BigDecimal("79228162514264337593543950335"),
BigDecimal.valueOf(Integer.MAX_VALUE/2),
new BigDecimal("79228162514264337594617692158") );
failures += addTest(
new BigDecimal("79228162514264337593543950335"),
BigDecimal.valueOf(Integer.MIN_VALUE/2),
new BigDecimal("79228162514264337592470208511") );
failures += addTest(
new BigDecimal("-79228162514264337593543950335"),
BigDecimal.valueOf(Integer.MAX_VALUE/2),
new BigDecimal("-79228162514264337592470208512") );
failures += addTest(
new BigDecimal("79228162514264337593543950335"),
BigDecimal.valueOf(-(Integer.MIN_VALUE/2)),
new BigDecimal("79228162514264337594617692159") );
failures += addTest(
new BigDecimal("79228162514264337593543950335"),
BigDecimal.valueOf(Long.MAX_VALUE/2),
new BigDecimal("79228162518876023611971338238") );
failures += addTest(
new BigDecimal("79228162514264337593543950335"),
BigDecimal.valueOf(Long.MIN_VALUE/2),
new BigDecimal("79228162509652651575116562431") );
failures += addTest(
new BigDecimal("-79228162514264337593543950335"),
BigDecimal.valueOf(Long.MAX_VALUE/2),
new BigDecimal("-79228162509652651575116562432") );
failures += addTest(
new BigDecimal("79228162514264337593543950335"),
BigDecimal.valueOf(-(Long.MIN_VALUE/2)),
new BigDecimal("79228162518876023611971338239") );
failures += addTest(
new BigDecimal("-9223372036854775808"),
BigDecimal.valueOf(1),
new BigDecimal("-9223372036854775807") );
failures += addTest(
new BigDecimal("-9223372036854775808"),
BigDecimal.valueOf(Long.MAX_VALUE/2),
new BigDecimal("-4611686018427387905") );
failures += addTest(
new BigDecimal("9223372036854775808"),
BigDecimal.valueOf(-1),
new BigDecimal("9223372036854775807") );
failures += addTest(
new BigDecimal("9223372036854775808"),
BigDecimal.valueOf(-Long.MAX_VALUE/2),
new BigDecimal("4611686018427387905") );
return failures;
}
private static int testRoundingFromBigInteger(BigInteger bi, int scale, MathContext mc) {
int failures = 0;
BigDecimal bd1 = new BigDecimal(bi,scale, mc);
BigDecimal bd2 = (new BigDecimal(bi,scale)).round(mc);
if (!bd1.equals(bd2)) {
System.out.println("new BigDecimal(BigInteger,int,MathContext):" +
"BigInteger == " +
bi + "; scale == " + scale + "; result == " +
bd1 + "; expected == " +
bd2
);
failures++;
}
return failures;
}
private static int roundingConstructorTest() {
int failures = 0;
failures += testRoundingFromBigInteger(
new BigInteger("85070591730234615847396907784232501249"),
7, MathContext.DECIMAL64);
failures += testRoundingFromBigInteger(
new BigInteger("85070591730234615847396907784232501249"),
0, MathContext.DECIMAL64);
failures += testRoundingFromBigInteger(
new BigInteger("85070591730234615847396907784232501249"),
-7, MathContext.DECIMAL64);
failures += testRoundingFromBigInteger(
new BigInteger("85070591730234615847396907784232501249"),
7, MathContext.DECIMAL128);
failures += testRoundingFromBigInteger(
new BigInteger("85070591730234615847396907784232501249"),
177, MathContext.DECIMAL128);
failures += testRoundingFromBigInteger(
new BigInteger("85070591730234615847396907784232501249"),
177, MathContext.DECIMAL32);
failures += testRoundingFromBigInteger(
new BigInteger("85070591730234615847396907784232501249"),
177, MathContext.UNLIMITED);
failures += testRoundingFromBigInteger(
new BigInteger("85070591730234615847396907784232501249"),
0, MathContext.UNLIMITED);
return failures;
}
private static int minLongConstructorTest(MathContext mc) {
int failures = 0;
BigDecimal bd1 = new BigDecimal(Long.MIN_VALUE,mc);
BigDecimal bd2 = new BigDecimal(Long.MIN_VALUE).round(mc);
if (!bd1.equals(bd2)) {
System.out.println("new BigDecimal(long,MathContext):" +
"long == " +
Long.MIN_VALUE + "; result == " +
bd1 + "; expected == " +
bd2
);
failures++;
}
return failures;
}
private static int minLongConstructorTest() {
int failures = 0;
failures+=minLongConstructorTest(MathContext.UNLIMITED);
failures+=minLongConstructorTest(MathContext.DECIMAL32);
failures+=minLongConstructorTest(MathContext.DECIMAL64);
failures+=minLongConstructorTest(MathContext.DECIMAL128);
return failures;
}
public static void main(String argv[]) {
int failures = 0;
failures += addBoundaryTest();
failures += roundingConstructorTest();
failures += minLongConstructorTest();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing.");
}
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2005, 2025, 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 6334849
* @summary Tests of dropping digits near the scale threshold
*/
import java.math.*;
public class RoundingTests {
private static int roundingTests() {
int failures = 0;
BigDecimal bd1 = BigDecimal.valueOf(11, Integer.MIN_VALUE);
BigDecimal bd2 = null;
MathContext mc = new MathContext(1);
try {
bd2 = bd1.round(mc); // should overflow here
failures++;
System.err.printf("Did not get expected overflow rounding %s to %d digits, got %s%n",
bd1, mc.getPrecision(), bd2);
} catch(ArithmeticException e) {
; // expected
}
return failures;
}
public static void main(String argv[]) {
int failures = 0;
failures += roundingTests();
if (failures > 0) {
System.err.println("Encountered " + failures +
" failures while testing rounding.");
throw new RuntimeException();
}
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2003, 2025, 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 4899722
* @summary Basic tests of scaleByPowerOfTen
*/
import java.math.*;
public class ScaleByPowerOfTenTests {
public static void main(String argv[]) {
for (int i = -10; i < 10; i++) {
BigDecimal bd = BigDecimal.ONE.scaleByPowerOfTen(i);
BigDecimal expected;
if (!bd.equals(expected = new BigDecimal(BigInteger.ONE, -i))) {
throw new RuntimeException("Unexpected result " +
bd.toString() +
"; expected " +
expected.toString());
}
bd = BigDecimal.ONE.negate().scaleByPowerOfTen(i);
if (!bd.equals(expected = new BigDecimal(BigInteger.ONE.negate(), -i))) {
throw new RuntimeException("Unexpected result " +
bd.toString() +
"; expected " +
expected.toString());
}
}
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright (c) 2005, 2022, 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 6177836 8282252
* @summary Verify BigDecimal objects with collapsed values are serialized properly.
*/
import java.math.*;
import java.io.*;
import java.util.List;
public class SerializationTests {
public static void main(String... args) throws Exception {
checkBigDecimalSerialRoundTrip();
checkBigDecimalSubSerialRoundTrip();
}
private static void checkSerialForm(BigDecimal bd) throws Exception {
checkSerialForm0(bd);
checkSerialForm0(bd.negate());
}
private static void checkSerialForm0(BigDecimal bd) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try(ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(bd);
oos.flush();
}
ObjectInputStream ois = new
ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
BigDecimal tmp = (BigDecimal)ois.readObject();
if (!bd.equals(tmp) ||
bd.hashCode() != tmp.hashCode() ||
bd.getClass() != tmp.getClass() ||
// Directly test equality of components
bd.scale() != tmp.scale() ||
!bd.unscaledValue().equals(tmp.unscaledValue())) {
System.err.print(" original : " + bd);
System.err.println(" (hash: 0x" + Integer.toHexString(bd.hashCode()) + ")");
System.err.print("serialized : " + tmp);
System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")");
throw new RuntimeException("Bad serial roundtrip");
}
// If the class of the deserialized number is BigDecimal,
// verify the implementation constraint on the unscaled value
// having BigInteger class
if (tmp.getClass() == BigDecimal.class) {
if (tmp.unscaledValue().getClass() != BigInteger.class) {
throw new RuntimeException("Not using genuine BigInteger as an unscaled value");
}
}
}
private static class BigIntegerSub extends BigInteger {
public BigIntegerSub(BigInteger bi) {
super(bi.toByteArray());
}
@Override
public String toString() {
return java.util.Arrays.toString(toByteArray());
}
}
private static void checkBigDecimalSerialRoundTrip() throws Exception {
var values =
List.of(BigDecimal.ZERO,
BigDecimal.ONE,
BigDecimal.TEN,
new BigDecimal(0),
new BigDecimal(1),
new BigDecimal(10),
new BigDecimal(Integer.MAX_VALUE),
new BigDecimal(Long.MAX_VALUE-1),
new BigDecimal(BigInteger.valueOf(1), 1),
new BigDecimal(BigInteger.valueOf(100), 50),
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
Integer.MAX_VALUE),
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
Integer.MIN_VALUE),
new BigDecimal(new BigIntegerSub(BigInteger.ONE), 2));
for(BigDecimal value : values) {
checkSerialForm(value);
}
}
private static class BigDecimalSub extends BigDecimal {
public BigDecimalSub(BigDecimal bd) {
super(bd.unscaledValue(), bd.scale());
}
@Override
public String toString() {
return unscaledValue() + "x10^" + (-scale());
}
}
// Subclass defining a serialVersionUID
private static class BigDecimalSubSVUID extends BigDecimal {
@java.io.Serial
private static long serialVesionUID = 0x0123_4567_89ab_cdefL;
public BigDecimalSubSVUID(BigDecimal bd) {
super(bd.unscaledValue(), bd.scale());
}
}
private static void checkBigDecimalSubSerialRoundTrip() throws Exception {
var values =
List.of(BigDecimal.ZERO,
BigDecimal.ONE,
BigDecimal.TEN,
new BigDecimal(BigInteger.TEN, 1234),
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
Integer.MAX_VALUE),
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
Integer.MIN_VALUE));
for(var value : values) {
checkSerialForm(new BigDecimalSub(value));
checkSerialForm(new BigDecimalSubSVUID(value));
}
}
}

View file

@ -0,0 +1,834 @@
/*
* Copyright (c) 2016, 2025, 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 4851777 8233452 8341402
* @summary Tests of BigDecimal.sqrt().
*/
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.List;
import static java.math.BigDecimal.ONE;
import static java.math.BigDecimal.TWO;
import static java.math.BigDecimal.TEN;
import static java.math.BigDecimal.ZERO;
import static java.math.BigDecimal.valueOf;
public class SquareRootTests {
/**
* The value 0.1, with a scale of 1.
*/
private static final BigDecimal ONE_TENTH = valueOf(1L, 1);
public static void main(String... args) {
int failures = 0;
failures += negativeTests();
failures += zeroTests();
failures += oneDigitTests();
failures += twoDigitTests();
failures += evenPowersOfTenTests();
failures += squareRootTwoTests();
failures += lowPrecisionPerfectSquares();
failures += almostFourRoundingDown();
failures += almostFourRoundingUp();
failures += nearTen();
failures += nearOne();
failures += halfWay();
failures += exactResultTests();
failures += scaleOverflowTest();
if (failures > 0 ) {
throw new RuntimeException("Incurred " + failures + " failures" +
" testing BigDecimal.sqrt().");
}
}
private static int negativeTests() {
int failures = 0;
for (long i = -10; i < 0; i++) {
for (int j = -5; j < 5; j++) {
try {
BigDecimal input = BigDecimal.valueOf(i, j);
BigDecimal result = input.sqrt(MathContext.DECIMAL64);
System.err.println("Unexpected sqrt of negative: (" +
input + ").sqrt() = " + result );
failures += 1;
} catch (ArithmeticException e) {
; // Expected
}
}
}
return failures;
}
private static int zeroTests() {
int failures = 0;
for (int i = -100; i < 100; i++) {
BigDecimal expected = BigDecimal.valueOf(0L, i/2);
// These results are independent of rounding mode
failures += compare(BigDecimal.valueOf(0L, i).sqrt(MathContext.UNLIMITED),
expected, true, "zeros");
failures += compare(BigDecimal.valueOf(0L, i).sqrt(MathContext.DECIMAL64),
expected, true, "zeros");
}
return failures;
}
/**
* Probe inputs with one digit of precision, 1 ... 9 and those
* values scaled by 10^-1, 0.1, ... 0.9.
*/
private static int oneDigitTests() {
int failures = 0;
List<BigDecimal> oneToNine =
List.of(ONE, TWO, valueOf(3),
valueOf(4), valueOf(5), valueOf(6),
valueOf(7), valueOf(8), valueOf(9));
List<RoundingMode> modes =
List.of(RoundingMode.UP, RoundingMode.DOWN,
RoundingMode.CEILING, RoundingMode.FLOOR,
RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN);
for (int i = 1; i < 20; i++) {
for (RoundingMode rm : modes) {
for (BigDecimal bd : oneToNine) {
MathContext mc = new MathContext(i, rm);
failures += compareSqrtImplementations(bd, mc);
bd = bd.multiply(ONE_TENTH);
failures += compareSqrtImplementations(bd, mc);
}
}
}
return failures;
}
/**
* Probe inputs with two digits of precision, (10 ... 99) and
* those values scaled by 10^-1 (1, ... 9.9) and scaled by 10^-2
* (0.1 ... 0.99).
*/
private static int twoDigitTests() {
int failures = 0;
List<RoundingMode> modes =
List.of(RoundingMode.UP, RoundingMode.DOWN,
RoundingMode.CEILING, RoundingMode.FLOOR,
RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN);
for (int i = 10; i < 100; i++) {
BigDecimal bd0 = BigDecimal.valueOf(i);
BigDecimal bd1 = bd0.multiply(ONE_TENTH);
BigDecimal bd2 = bd1.multiply(ONE_TENTH);
for (BigDecimal bd : List.of(bd0, bd1, bd2)) {
for (int precision = 1; i < 20; i++) {
for (RoundingMode rm : modes) {
MathContext mc = new MathContext(precision, rm);
failures += compareSqrtImplementations(bd, mc);
}
}
}
}
return failures;
}
private static int compareSqrtImplementations(BigDecimal bd, MathContext mc) {
return equalNumerically(BigSquareRoot.sqrt(bd, mc),
bd.sqrt(mc), "sqrt(" + bd + ") under " + mc);
}
private static int exactResultTests() {
int failures = 0;
MathContext unnecessary = new MathContext(1, RoundingMode.UNNECESSARY);
MathContext arbitrary = new MathContext(0, RoundingMode.CEILING);
BigDecimal[] errCases = {
// (strippedScale & 1) != 0
BigDecimal.TEN,
// (strippedScale & 1) == 0 && !stripped.isPowerOfTen() && sqrtRem[1].signum != 0
BigDecimal.TWO,
};
for (BigDecimal input : errCases) {
BigDecimal result;
// mc.roundingMode == RoundingMode.UNNECESSARY
try {
result = input.sqrt(unnecessary);
System.err.println("Unexpected sqrt with UNNECESSARY RoundingMode: (" + input + ").sqrt() = " + result);
failures += 1;
} catch (ArithmeticException e) {
// Expected
}
// mc.roundingMode != RoundingMode.UNNECESSARY && mc.precision == 0
try {
result = input.sqrt(arbitrary);
System.err.println("Unexpected sqrt with mc.precision == 0: (" + input + ").sqrt() = " + result);
failures += 1;
} catch (ArithmeticException e) {
// Expected
}
}
// (strippedScale & 1) == 0
// !stripped.isPowerOfTen() && sqrtRem[1].signum == 0 && (mc.precision != 0 && result.precision() > mc.precision)
try {
BigDecimal input = BigDecimal.valueOf(121);
BigDecimal result = input.sqrt(unnecessary);
System.err.println("Unexpected sqrt with result.precision() > mc.precision: ("
+ input + ").sqrt() = " + result);
failures += 1;
} catch (ArithmeticException e) {
// Expected
}
BigDecimal four = BigDecimal.valueOf(4);
Object[][] cases = {
// stripped.isPowerOfTen() && mc.roundingMode == RoundingMode.UNNECESSARY
{ BigDecimal.ONE, unnecessary, BigDecimal.ONE },
// stripped.isPowerOfTen() && mc.roundingMode != RoundingMode.UNNECESSARY && mc.precision == 0
{ BigDecimal.ONE, arbitrary, BigDecimal.ONE },
// !stripped.isPowerOfTen() && mc.roundingMode == RoundingMode.UNNECESSARY
// && sqrtRem[1].signum == 0 && mc.precision == 0
{ four, new MathContext(0, RoundingMode.UNNECESSARY), BigDecimal.TWO },
// !stripped.isPowerOfTen() && mc.roundingMode != RoundingMode.UNNECESSARY
// && sqrtRem[1].signum == 0 && mc.precision == 0
{ four, arbitrary, BigDecimal.TWO },
// !stripped.isPowerOfTen() && sqrtRem[1].signum == 0
// && (mc.precision != 0 && result.precision() <= mc.precision)
{ four, unnecessary, BigDecimal.TWO },
};
for (Object[] testCase : cases) {
BigDecimal expected = (BigDecimal) testCase[2];
BigDecimal result = ((BigDecimal) testCase[0]).sqrt((MathContext) testCase[1]);
failures += compare(expected, result, true, "Exact results");
}
return failures;
}
private static int scaleOverflowTest() {
int failures = 0;
try {
BigDecimal.valueOf(1, -1).sqrt(new MathContext((1 << 30) + 1, RoundingMode.UP));
System.err.println("ArithmeticException expected: possible overflow undetected "
+ "or the range of supported values for the algorithm has extended.");
failures += 1;
} catch (ArithmeticException e) {
// Expected
}
return failures;
}
/**
* sqrt(10^2N) is 10^N
* Both numerical value and representation should be verified
*/
private static int evenPowersOfTenTests() {
int failures = 0;
MathContext oneDigitExactly = new MathContext(1, RoundingMode.UNNECESSARY);
for (int scale = -100; scale <= 100; scale++) {
BigDecimal testValue = BigDecimal.valueOf(1, 2*scale);
BigDecimal expectedNumericalResult = BigDecimal.valueOf(1, scale);
BigDecimal result;
failures += equalNumerically(expectedNumericalResult,
result = testValue.sqrt(MathContext.DECIMAL64),
"Even powers of 10, DECIMAL64");
// Can round to one digit of precision exactly
failures += equalNumerically(expectedNumericalResult,
result = testValue.sqrt(oneDigitExactly),
"even powers of 10, 1 digit");
if (result.precision() > 1) {
failures += 1;
System.err.println("Excess precision for " + result);
}
// If rounding to more than one digit, do precision / scale checking...
}
return failures;
}
private static int squareRootTwoTests() {
int failures = 0;
// Square root of 2 truncated to 65 digits
BigDecimal highPrecisionRoot2 =
new BigDecimal("1.41421356237309504880168872420969807856967187537694807317667973799");
RoundingMode[] modes = {
RoundingMode.UP, RoundingMode.DOWN,
RoundingMode.CEILING, RoundingMode.FLOOR,
RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN
};
// For each interesting rounding mode, for precisions 1 to, say,
// 63 numerically compare TWO.sqrt(mc) to
// highPrecisionRoot2.round(mc) and the alternative internal high-precision
// implementation of square root.
for (RoundingMode mode : modes) {
for (int precision = 1; precision < 63; precision++) {
MathContext mc = new MathContext(precision, mode);
BigDecimal expected = highPrecisionRoot2.round(mc);
BigDecimal computed = TWO.sqrt(mc);
BigDecimal altComputed = BigSquareRoot.sqrt(TWO, mc);
failures += equalNumerically(expected, computed, "sqrt(2)");
failures += equalNumerically(computed, altComputed, "computed & altComputed");
}
}
return failures;
}
private static int lowPrecisionPerfectSquares() {
int failures = 0;
// For 5^2 through 9^2, if the input is rounded to one digit
// first before the root is computed, the wrong answer will
// result. Verify results and scale for different rounding
// modes and precisions.
long[][] squaresWithOneDigitRoot = {{ 4, 2},
{ 9, 3},
{25, 5},
{36, 6},
{49, 7},
{64, 8},
{81, 9}};
for (long[] squareAndRoot : squaresWithOneDigitRoot) {
BigDecimal square = new BigDecimal(squareAndRoot[0]);
BigDecimal expected = new BigDecimal(squareAndRoot[1]);
for (int scale = 0; scale <= 4; scale++) {
BigDecimal scaledSquare = square.setScale(scale, RoundingMode.UNNECESSARY);
int expectedScale = Math.ceilDiv(scale, 2);
for (int precision = 0; precision <= 5; precision++) {
for (RoundingMode rm : RoundingMode.values()) {
MathContext mc = new MathContext(precision, rm);
BigDecimal computedRoot = scaledSquare.sqrt(mc);
failures += equalNumerically(expected, computedRoot, "simple squares");
int computedScale = computedRoot.scale();
if (precision >= expectedScale + 1 &&
computedScale != expectedScale) {
System.err.printf("%s\tprecision=%d\trm=%s%n",
computedRoot.toString(), precision, rm);
failures++;
System.err.printf("\t%s does not have expected scale of %d%n.",
computedRoot, expectedScale);
}
}
}
}
}
return failures;
}
/**
* Test around 3.9999 that the sqrt doesn't improperly round-up to
* a numerical value of 2.
*/
private static int almostFourRoundingDown() {
int failures = 0;
BigDecimal nearFour = new BigDecimal("3.999999999999999999999999999999");
// Sqrt is 1.9999...
for (int i = 1; i < 64; i++) {
MathContext mc = new MathContext(i, RoundingMode.FLOOR);
BigDecimal result = nearFour.sqrt(mc);
BigDecimal expected = BigSquareRoot.sqrt(nearFour, mc);
failures += equalNumerically(expected, result, "near four rounding down");
failures += (result.compareTo(TWO) < 0) ? 0 : 1 ;
}
return failures;
}
/**
* Test around 4.000...1 that the sqrt doesn't improperly
* round-down to a numerical value of 2.
*/
private static int almostFourRoundingUp() {
int failures = 0;
BigDecimal nearFour = new BigDecimal("4.000000000000000000000000000001");
// Sqrt is 2.0000....<non-zero digits>
for (int i = 1; i < 64; i++) {
MathContext mc = new MathContext(i, RoundingMode.CEILING);
BigDecimal result = nearFour.sqrt(mc);
BigDecimal expected = BigSquareRoot.sqrt(nearFour, mc);
failures += equalNumerically(expected, result, "near four rounding up");
failures += (result.compareTo(TWO) > 0) ? 0 : 1 ;
}
return failures;
}
private static int nearTen() {
int failures = 0;
BigDecimal near10 = new BigDecimal("9.99999999999999999999");
BigDecimal near10sq = near10.multiply(near10);
BigDecimal near10sq_ulp = near10sq.add(near10sq.ulp());
for (int i = 10; i < 23; i++) {
MathContext mc = new MathContext(i, RoundingMode.HALF_EVEN);
failures += equalNumerically(BigSquareRoot.sqrt(near10sq_ulp, mc),
near10sq_ulp.sqrt(mc),
"near 10 rounding half even");
}
return failures;
}
/*
* Probe for rounding failures near a power of ten, 1 = 10^0,
* where an ulp has a different size above and below the value.
*/
private static int nearOne() {
int failures = 0;
BigDecimal near1 = new BigDecimal(".999999999999999999999");
BigDecimal near1sq = near1.multiply(near1);
BigDecimal near1sq_ulp = near1sq.add(near1sq.ulp());
for (int i = 10; i < 23; i++) {
for (RoundingMode rm : List.of(RoundingMode.HALF_EVEN,
RoundingMode.UP,
RoundingMode.DOWN )) {
MathContext mc = new MathContext(i, rm);
failures += equalNumerically(BigSquareRoot.sqrt(near1sq_ulp, mc),
near1sq_ulp.sqrt(mc),
mc.toString());
}
}
return failures;
}
private static int halfWay() {
int failures = 0;
/*
* Use enough digits that the exact result cannot be computed
* from the sqrt of a double.
*/
BigDecimal[] halfWayCases = {
// Odd next digit, truncate on HALF_EVEN
new BigDecimal("123456789123456789.5"),
// Even next digit, round up on HALF_EVEN
new BigDecimal("123456789123456788.5"),
};
for (BigDecimal halfWayCase : halfWayCases) {
// Round result to next-to-last place
int precision = halfWayCase.precision() - 1;
BigDecimal square = halfWayCase.multiply(halfWayCase);
for (RoundingMode rm : List.of(RoundingMode.HALF_EVEN,
RoundingMode.HALF_UP,
RoundingMode.HALF_DOWN)) {
MathContext mc = new MathContext(precision, rm);
System.out.println("\nRounding mode " + rm);
System.out.println("\t" + halfWayCase.round(mc) + "\t" + halfWayCase);
System.out.println("\t" + BigSquareRoot.sqrt(square, mc));
failures += equalNumerically(/*square.sqrt(mc),*/
BigSquareRoot.sqrt(square, mc),
halfWayCase.round(mc),
"Rounding halway " + rm);
}
}
return failures;
}
private static int compare(BigDecimal a, BigDecimal b, boolean expected, String prefix) {
boolean result = a.equals(b);
int failed = (result==expected) ? 0 : 1;
if (failed == 1) {
System.err.println("Testing " + prefix +
"(" + a + ").compareTo(" + b + ") => " + result +
"\n\tExpected " + expected);
}
return failed;
}
private static int equalNumerically(BigDecimal a, BigDecimal b,
String prefix) {
return compareNumerically(a, b, 0, prefix);
}
private static int compareNumerically(BigDecimal a, BigDecimal b,
int expected, String prefix) {
int result = a.compareTo(b);
int failed = (result==expected) ? 0 : 1;
if (failed == 1) {
System.err.println("Testing " + prefix +
"(" + a + ").compareTo(" + b + ") => " + result +
"\n\tExpected " + expected);
}
return failed;
}
/**
* Alternative implementation of BigDecimal square root which uses
* higher-precision for a simpler set of termination conditions
* for the Newton iteration.
*/
private static class BigSquareRoot {
/**
* The value 0.5, with a scale of 1.
*/
private static final BigDecimal ONE_HALF = valueOf(5L, 1);
public static boolean isPowerOfTen(BigDecimal bd) {
return BigInteger.ONE.equals(bd.unscaledValue());
}
public static BigDecimal square(BigDecimal bd) {
return bd.multiply(bd);
}
public static BigDecimal sqrt(BigDecimal bd, MathContext mc) {
int signum = bd.signum();
if (signum == 1) {
/*
* The following code draws on the algorithm presented in
* "Properly Rounded Variable Precision Square Root," Hull and
* Abrham, ACM Transactions on Mathematical Software, Vol 11,
* No. 3, September 1985, Pages 229-237.
*
* The BigDecimal computational model differs from the one
* presented in the paper in several ways: first BigDecimal
* numbers aren't necessarily normalized, second many more
* rounding modes are supported, including UNNECESSARY, and
* exact results can be requested.
*
* The main steps of the algorithm below are as follows,
* first argument reduce the value to the numerical range
* [1, 10) using the following relations:
*
* x = y * 10 ^ exp
* sqrt(x) = sqrt(y) * 10^(exp / 2) if exp is even
* sqrt(x) = sqrt(y/10) * 10 ^((exp+1)/2) is exp is odd
*
* Then use Newton's iteration on the reduced value to compute
* the numerical digits of the desired result.
*
* Finally, scale back to the desired exponent range and
* perform any adjustment to get the preferred scale in the
* representation.
*/
// The code below favors relative simplicity over checking
// for special cases that could run faster.
int preferredScale = Math.ceilDiv(bd.scale(), 2);
BigDecimal zeroWithFinalPreferredScale =
BigDecimal.valueOf(0L, preferredScale);
// First phase of numerical normalization, strip trailing
// zeros and check for even powers of 10.
BigDecimal stripped = bd.stripTrailingZeros();
int strippedScale = stripped.scale();
// Numerically sqrt(10^2N) = 10^N
if (isPowerOfTen(stripped) &&
strippedScale % 2 == 0) {
BigDecimal result = BigDecimal.valueOf(1L, strippedScale/2);
if (result.scale() != preferredScale) {
// Adjust to requested precision and preferred
// scale as appropriate.
result = result.add(zeroWithFinalPreferredScale, mc);
}
return result;
}
// After stripTrailingZeros, the representation is normalized as
//
// unscaledValue * 10^(-scale)
//
// where unscaledValue is an integer with the mimimum
// precision for the cohort of the numerical value. To
// allow binary floating-point hardware to be used to get
// approximately a 15 digit approximation to the square
// root, it is helpful to instead normalize this so that
// the significand portion is to right of the decimal
// point by roughly (scale() - precision() + 1).
// Now the precision / scale adjustment
int scaleAdjust = 0;
int scale = stripped.scale() - stripped.precision() + 1;
if (scale % 2 == 0) {
scaleAdjust = scale;
} else {
scaleAdjust = scale - 1;
}
BigDecimal working = stripped.scaleByPowerOfTen(scaleAdjust);
assert // Verify 0.1 <= working < 10
ONE_TENTH.compareTo(working) <= 0 && working.compareTo(TEN) < 0;
// Use good ole' Math.sqrt to get the initial guess for
// the Newton iteration, good to at least 15 decimal
// digits. This approach does incur the cost of a
//
// BigDecimal -> double -> BigDecimal
//
// conversion cycle, but it avoids the need for several
// Newton iterations in BigDecimal arithmetic to get the
// working answer to 15 digits of precision. If many fewer
// than 15 digits were needed, it might be faster to do
// the loop entirely in BigDecimal arithmetic.
//
// (A double value might have as much many as 17 decimal
// digits of precision; it depends on the relative density
// of binary and decimal numbers at different regions of
// the number line.)
//
// (It would be possible to check for certain special
// cases to avoid doing any Newton iterations. For
// example, if the BigDecimal -> double conversion was
// known to be exact and the rounding mode had a
// low-enough precision, the post-Newton rounding logic
// could be applied directly.)
BigDecimal guess = new BigDecimal(Math.sqrt(working.doubleValue()));
int guessPrecision = 15;
int originalPrecision = mc.getPrecision();
int targetPrecision;
// If an exact value is requested, it must only need
// about half of the input digits to represent since
// multiplying an N digit number by itself yield a (2N
// - 1) digit or 2N digit result.
if (originalPrecision == 0) {
targetPrecision = stripped.precision()/2 + 1;
} else {
targetPrecision = originalPrecision;
}
// When setting the precision to use inside the Newton
// iteration loop, take care to avoid the case where the
// precision of the input exceeds the requested precision
// and rounding the input value too soon.
BigDecimal approx = guess;
int workingPrecision = working.precision();
// Use "2p + 2" property to guarantee enough
// intermediate precision so that a double-rounding
// error does not occur when rounded to the final
// destination precision.
int loopPrecision =
Math.max(2 * Math.max(targetPrecision, workingPrecision) + 2,
34); // Force at least two Netwon
// iterations on the Math.sqrt
// result.
do {
MathContext mcTmp = new MathContext(loopPrecision, RoundingMode.HALF_EVEN);
// approx = 0.5 * (approx + fraction / approx)
approx = ONE_HALF.multiply(approx.add(working.divide(approx, mcTmp), mcTmp));
guessPrecision *= 2;
} while (guessPrecision < loopPrecision);
BigDecimal result;
RoundingMode targetRm = mc.getRoundingMode();
if (targetRm == RoundingMode.UNNECESSARY || originalPrecision == 0) {
RoundingMode tmpRm =
(targetRm == RoundingMode.UNNECESSARY) ? RoundingMode.DOWN : targetRm;
MathContext mcTmp = new MathContext(targetPrecision, tmpRm);
result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mcTmp);
// If result*result != this numerically, the square
// root isn't exact
if (bd.subtract(square(result)).compareTo(ZERO) != 0) {
throw new ArithmeticException("Computed square root not exact.");
}
} else {
result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mc);
}
assert squareRootResultAssertions(bd, result, mc);
if (result.scale() != preferredScale) {
// The preferred scale of an add is
// max(addend.scale(), augend.scale()). Therefore, if
// the scale of the result is first minimized using
// stripTrailingZeros(), adding a zero of the
// preferred scale rounding the correct precision will
// perform the proper scale vs precision tradeoffs.
result = result.stripTrailingZeros().
add(zeroWithFinalPreferredScale,
new MathContext(originalPrecision, RoundingMode.UNNECESSARY));
}
return result;
} else {
switch (signum) {
case -1:
throw new ArithmeticException("Attempted square root " +
"of negative BigDecimal");
case 0:
return valueOf(0L, bd.scale()/2);
default:
throw new AssertionError("Bad value from signum");
}
}
}
/**
* For nonzero values, check numerical correctness properties of
* the computed result for the chosen rounding mode.
*
* For the directed roundings, for DOWN and FLOOR, result^2 must
* be {@code <=} the input and (result+ulp)^2 must be {@code >} the
* input. Conversely, for UP and CEIL, result^2 must be {@code >=} the
* input and (result-ulp)^2 must be {@code <} the input.
*/
private static boolean squareRootResultAssertions(BigDecimal input, BigDecimal result, MathContext mc) {
if (result.signum() == 0) {
return squareRootZeroResultAssertions(input, result, mc);
} else {
RoundingMode rm = mc.getRoundingMode();
BigDecimal ulp = result.ulp();
BigDecimal neighborUp = result.add(ulp);
// Make neighbor down accurate even for powers of ten
if (isPowerOfTen(result)) {
ulp = ulp.divide(TEN);
}
BigDecimal neighborDown = result.subtract(ulp);
// Both the starting value and result should be nonzero and positive.
if (result.signum() != 1 ||
input.signum() != 1) {
return false;
}
switch (rm) {
case DOWN:
case FLOOR:
assert
square(result).compareTo(input) <= 0 &&
square(neighborUp).compareTo(input) > 0:
"Square of result out for bounds rounding " + rm;
return true;
case UP:
case CEILING:
assert
square(result).compareTo(input) >= 0 :
"Square of result too small rounding " + rm;
assert
square(neighborDown).compareTo(input) < 0 :
"Square of down neighbor too large rounding " + rm + "\n" +
"\t input: " + input + "\t neighborDown: " + neighborDown +"\t sqrt: " + result +
"\t" + mc;
return true;
case HALF_DOWN:
case HALF_EVEN:
case HALF_UP:
BigDecimal err = square(result).subtract(input).abs();
BigDecimal errUp = square(neighborUp).subtract(input);
BigDecimal errDown = input.subtract(square(neighborDown));
// All error values should be positive so don't need to
// compare absolute values.
int err_comp_errUp = err.compareTo(errUp);
int err_comp_errDown = err.compareTo(errDown);
assert
errUp.signum() == 1 &&
errDown.signum() == 1 :
"Errors of neighbors squared don't have correct signs";
// At least one of these must be true, but not both
// assert
// err_comp_errUp <= 0 : "Upper neighbor is closer than result: " + rm +
// "\t" + input + "\t result" + result;
// assert
// err_comp_errDown <= 0 : "Lower neighbor is closer than result: " + rm +
// "\t" + input + "\t result " + result + "\t lower neighbor: " + neighborDown;
assert
((err_comp_errUp == 0 ) ? err_comp_errDown < 0 : true) &&
((err_comp_errDown == 0 ) ? err_comp_errUp < 0 : true) :
"Incorrect error relationships";
// && could check for digit conditions for ties too
return true;
default: // Definition of UNNECESSARY already verified.
return true;
}
}
}
private static boolean squareRootZeroResultAssertions(BigDecimal input,
BigDecimal result,
MathContext mc) {
return input.compareTo(ZERO) == 0;
}
}
}

View file

@ -0,0 +1,185 @@
/*
* Copyright (c) 1999, 2022, 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
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @run main StringConstructor
* @bug 4103117 4331084 4488017 4490929 6255285 6268365 8074460 8078672 8233760
* @summary Tests the BigDecimal string constructor (use -Dseed=X to set PRNG seed).
* @key randomness
*/
import java.math.*;
import java.util.Random;
import jdk.test.lib.RandomFactory;
public class StringConstructor {
public static void main(String[] args) throws Exception {
constructWithError("");
constructWithError("+");
constructWithError("-");
constructWithError("+e");
constructWithError("-e");
constructWithError("e+");
constructWithError("1.-0");
constructWithError(".-123");
constructWithError("-");
constructWithError("--1.1");
constructWithError("-+1.1");
constructWithError("+-1.1");
constructWithError("1-.1");
constructWithError("1+.1");
constructWithError("1.111+1");
constructWithError("1.111-1");
constructWithError("11.e+");
constructWithError("11.e-");
constructWithError("11.e+-");
constructWithError("11.e-+");
constructWithError("11.e-+1");
constructWithError("11.e+-1");
// Range checks
constructWithError("1e"+Integer.MIN_VALUE);
constructWithError("10e"+Integer.MIN_VALUE);
constructWithError("0.01e"+Integer.MIN_VALUE);
constructWithError("1e"+((long)Integer.MIN_VALUE-1));
leadingExponentZeroTest();
nonAsciiZeroTest();
/* These BigDecimals produce a string with an exponent > Integer.MAX_VALUE */
roundtripWithAbnormalExponent(BigDecimal.valueOf(10, Integer.MIN_VALUE));
roundtripWithAbnormalExponent(BigDecimal.valueOf(Long.MIN_VALUE, Integer.MIN_VALUE));
roundtripWithAbnormalExponent(new BigDecimal(new BigInteger("1" + "0".repeat(100)), Integer.MIN_VALUE));
/* These Strings have an exponent > Integer.MAX_VALUE */
roundtripWithAbnormalExponent("1.0E+2147483649");
roundtripWithAbnormalExponent("-9.223372036854775808E+2147483666");
roundtripWithAbnormalExponent("1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E+2147483748");
// Roundtrip tests
Random random = RandomFactory.getRandom();
for (int i=0; i<100; i++) {
int size = random.nextInt(100) + 1;
BigInteger bi = new BigInteger(size, random);
if (random.nextBoolean())
bi = bi.negate();
int decimalLength = bi.toString().length();
int scale = random.nextInt(decimalLength);
BigDecimal bd = new BigDecimal(bi, scale);
String bdString = bd.toString();
// System.err.println("bi" + bi.toString() + "\tscale " + scale);
// System.err.println("bd string: " + bdString);
BigDecimal bdDoppel = new BigDecimal(bdString);
if (!bd.equals(bdDoppel)) {
System.err.println("bd string: scale: " + bd.scale() +
"\t" + bdString);
System.err.println("bd doppel: scale: " + bdDoppel.scale() +
"\t" + bdDoppel.toString());
throw new RuntimeException("String constructor failure.");
}
}
}
private static void roundtripWithAbnormalExponent(BigDecimal bd) {
if (!bd.equals(new BigDecimal(bd.toString()))) {
throw new RuntimeException("Abnormal exponent roundtrip failure");
}
}
private static void roundtripWithAbnormalExponent(String s) {
if (!s.equals(new BigDecimal(s).toString())) {
throw new RuntimeException("Abnormal exponent roundtrip failure");
}
}
/*
* Verify precision is set properly if the significand has
* non-ASCII leading zeros.
*/
private static void nonAsciiZeroTest() {
String values[] = {
"00004e5",
"\u0660\u0660\u0660\u06604e5",
};
BigDecimal expected = new BigDecimal("4e5");
for(String s : values) {
BigDecimal tmp = new BigDecimal(s);
// System.err.println("Testing " + s);
if (! expected.equals(tmp) || tmp.precision() != 1) {
System.err.println("Bad conversion of " + s + "got " +
tmp + "precision = " + tmp.precision());
throw new RuntimeException("String constructor failure.");
}
}
}
private static void leadingExponentZeroTest() {
BigDecimal twelve = new BigDecimal("12");
BigDecimal onePointTwo = new BigDecimal("1.2");
String start = "1.2e0";
String end = "1";
String middle = "";
// Test with more excess zeros than the largest number of
// decimal digits needed to represent a long
int limit = ((int)Math.log10(Long.MAX_VALUE)) + 6;
for(int i = 0; i < limit; i++, middle += "0") {
String t1 = start + middle;
String t2 = t1 + end;
// System.out.println(i + "\t" + t1 + "\t" + t2);
testString(t1, onePointTwo);
testString(t2, twelve);
}
}
private static void testString(String s, BigDecimal expected) {
testString0(s, expected);
testString0(switchZero(s), expected);
}
private static void testString0(String s, BigDecimal expected) {
if (!expected.equals(new BigDecimal(s)))
throw new RuntimeException(s + " is not equal to " + expected);
}
private static String switchZero(String s) {
return s.replace('0', '\u0660'); // Arabic-Indic zero
}
private static void constructWithError(String badString) {
try {
BigDecimal d = new BigDecimal(badString);
throw new RuntimeException(badString + " accepted");
} catch(NumberFormatException e) {
}
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2003, 2025, 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 4108852
* @summary A few tests of stripTrailingZeros
* @run main StrippingZerosTest
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 StrippingZerosTest
*/
import java.math.*;
public class StrippingZerosTest {
public static void main(String argv[]) {
BigDecimal [][] testCases = {
{new BigDecimal("1.00000"), new BigDecimal("1")},
{new BigDecimal("1.000"), new BigDecimal("1")},
{new BigDecimal("1"), new BigDecimal("1")},
{new BigDecimal("0.1234"), new BigDecimal("0.1234")},
{new BigDecimal("0.12340"), new BigDecimal("0.1234")},
{new BigDecimal("0.12340000000"), new BigDecimal("0.1234")},
{new BigDecimal("1234.5678"), new BigDecimal("1234.5678")},
{new BigDecimal("1234.56780"), new BigDecimal("1234.5678")},
{new BigDecimal("1234.567800000"), new BigDecimal("1234.5678")},
{new BigDecimal("0"), new BigDecimal("0")},
{new BigDecimal("0e2"), BigDecimal.ZERO},
{new BigDecimal("0e-2"), BigDecimal.ZERO},
{new BigDecimal("0e42"), BigDecimal.ZERO},
{new BigDecimal("+0e42"), BigDecimal.ZERO},
{new BigDecimal("-0e42"), BigDecimal.ZERO},
{new BigDecimal("0e-42"), BigDecimal.ZERO},
{new BigDecimal("+0e-42"), BigDecimal.ZERO},
{new BigDecimal("-0e-42"), BigDecimal.ZERO},
{new BigDecimal("0e-2"), BigDecimal.ZERO},
{new BigDecimal("0e100"), BigDecimal.ZERO},
{new BigDecimal("0e-100"), BigDecimal.ZERO},
{new BigDecimal("10"), new BigDecimal("1e1")},
{new BigDecimal("20"), new BigDecimal("2e1")},
{new BigDecimal("100"), new BigDecimal("1e2")},
{new BigDecimal("1000000000"), new BigDecimal("1e9")},
{new BigDecimal("100000000e1"), new BigDecimal("1e9")},
{new BigDecimal("10000000e2"), new BigDecimal("1e9")},
{new BigDecimal("1000000e3"), new BigDecimal("1e9")},
{new BigDecimal("100000e4"), new BigDecimal("1e9")},
// BD value which larger than Long.MaxValue
{new BigDecimal("1.0000000000000000000000000000"), new BigDecimal("1")},
{new BigDecimal("-1.0000000000000000000000000000"), new BigDecimal("-1")},
{new BigDecimal("1.00000000000000000000000000001"), new BigDecimal("1.00000000000000000000000000001")},
{new BigDecimal("1000000000000000000000000000000e4"), new BigDecimal("1e34")},
};
for(int i = 0; i < testCases.length; i++) {
if (!(testCases[i][0]).stripTrailingZeros().equals(testCases[i][1])) {
throw new RuntimeException("For input " + testCases[i][0].toString() +
" did not received expected result " +
testCases[i][1].toString() + ", got " +
testCases[i][0].stripTrailingZeros());
}
testCases[i][0] = testCases[i][0].negate();
testCases[i][1] = testCases[i][1].negate();
if (!(testCases[i][0]).stripTrailingZeros().equals(testCases[i][1])) {
throw new RuntimeException("For input " + testCases[i][0].toString() +
" did not received expected result " +
testCases[i][1].toString() + ", got " +
testCases[i][0].stripTrailingZeros());
}
}
}
}

View file

@ -0,0 +1,131 @@
/*
* Copyright (c) 2004, 2025, 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 4984872 8318915
* @summary Basic tests of toPlainString method
* @run main ToPlainStringTests
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 ToPlainStringTests
*/
import java.math.*;
public class ToPlainStringTests {
public static void main(String argv[]) {
String [][] testCases = {
{"0", "0"},
{"1", "1"},
{"10", "10"},
{"2e1", "20"},
{"3e2", "300"},
{"4e3", "4000"},
{"5e4", "50000"},
{"6e5", "600000"},
{"7e6", "7000000"},
{"8e7", "80000000"},
{"9e8", "900000000"},
{"1e9", "1000000000"},
{".0", "0.0"},
{".1", "0.1"},
{".10", "0.10"},
{"1e-1", "0.1"},
{"1e-1", "0.1"},
{"2e-2", "0.02"},
{"3e-3", "0.003"},
{"4e-4", "0.0004"},
{"5e-5", "0.00005"},
{"6e-6", "0.000006"},
{"7e-7", "0.0000007"},
{"8e-8", "0.00000008"},
{"9e-9", "0.000000009"},
{"9000e-12", "0.000000009000"},
{"9000e-22", "0.0000000000000000009000"},
{"12345678901234567890", "12345678901234567890"},
{"12345678901234567890e22", "123456789012345678900000000000000000000000"},
{"12345678901234567890e-22", "0.0012345678901234567890"},
{"12345e-1", "1234.5"},
{"12345e-2", "123.45"},
{"12345e-3", "12.345"},
{"12345e-4", "1.2345"},
};
int errors = 0;
for(String[] testCase: testCases) {
BigDecimal bd = new BigDecimal(testCase[0]);
String s;
if (!(s=bd.toPlainString()).equals(testCase[1])) {
errors++;
System.err.println("Unexpected plain result ``" +
s + "'' from BigDecimal " +
bd);
}
bd = new BigDecimal("-"+testCase[0]);
if (bd.signum()!=0 && !(s=(bd.toPlainString())).equals("-"+testCase[1])) {
errors++;
System.err.println("Unexpected plain result ``" +
s + "'' from BigDecimal " +
bd);
}
}
String[] failingCases = {
"1E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 2 chars
"1E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 1 chars
"-1E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 3 chars
"-1E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 2 chars
"-1E-" + (Integer.MAX_VALUE - 2), // MAX_VALUE + 1 chars
"123456789E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 2 chars
"123456789E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 1 chars
"-123456789E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 3 chars
"-123456789E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 2 chars
"-123456789E-" + (Integer.MAX_VALUE - 2), // MAX_VALUE + 1 chars
"1E" + Integer.MAX_VALUE, // MAX_VALUE + 1 chars
"123456789E" + Integer.MAX_VALUE, // MAX_VALUE + 9 chars
"-1E" + Integer.MAX_VALUE, // MAX_VALUE + 2 chars
"-123456789E" + Integer.MAX_VALUE, // MAX_VALUE + 10 chars
};
/* We expect pre-emptive OutOfMemoryErrors, nothing else */
for (String failingCase : failingCases) {
try {
new BigDecimal(failingCase).toPlainString();
} catch (OutOfMemoryError expected) {
continue;
} catch (Throwable ignored) {
}
++errors;
}
if(errors > 0)
throw new RuntimeException(errors + " errors during run.");
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2025, 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 8356709
* @summary Test Double.toString(double)
* @run junit ValueOfDouble
*/
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ValueOfDouble {
private static final String DIGITS = "1234567000003456789"; // Enough digits to fill a long
@Test
public void testValueOfDouble() {
checkValue(0.0);
checkValue(-0.0);
checkValue(Math.PI);
checkValue(-Math.PI);
checkValue(Double.MAX_VALUE);
checkValue(Double.MIN_VALUE);
checkValue(1e-44); // Lots of digits with lots of 9s
for (int prec = 1; prec < DIGITS.length(); prec++) {
String prefix = DIGITS.substring(0, prec);
for (int exp = -30; exp < 30; exp++) {
double value = Double.parseDouble(prefix + "e" + exp);
checkValue(value);
checkValue(-value);
}
}
}
private static void checkValue(double value) {
BigDecimal expected = new BigDecimal(Double.toString(value));
assertEquals(expected, BigDecimal.valueOf(value));
}
@Test
public void testExceptions() {
assertThrows(NumberFormatException.class, () -> BigDecimal.valueOf(Double.NaN));
assertThrows(NumberFormatException.class, () -> BigDecimal.valueOf(Double.POSITIVE_INFINITY));
assertThrows(NumberFormatException.class, () -> BigDecimal.valueOf(Double.NEGATIVE_INFINITY));
}
}

View file

@ -0,0 +1,476 @@
/*
* Copyright (c) 2003, 2025, 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 4902952 4905407 4916149 8057793
* @summary Tests that the scale of zero is propagated properly and has the
* proper effect and that setting the scale to zero does not mutate the
* BigDecimal.
*/
import java.math.*;
import java.util.*;
public class ZeroScalingTests {
static MathContext longEnough = new MathContext(50, RoundingMode.UNNECESSARY);
static BigDecimal[] zeros = new BigDecimal[23];
static {
for(int i = 0; i < 21; i++) {
zeros[i] = new BigDecimal(BigInteger.ZERO, i-10);
}
zeros[21] = new BigDecimal(BigInteger.ZERO, Integer.MIN_VALUE);
zeros[22] = new BigDecimal(BigInteger.ZERO, Integer.MAX_VALUE);
}
static BigDecimal element = BigDecimal.valueOf(100, -2);
static MathContext contexts[] = {
new MathContext(0, RoundingMode.UNNECESSARY),
new MathContext(100, RoundingMode.UNNECESSARY),
new MathContext(5, RoundingMode.UNNECESSARY),
new MathContext(4, RoundingMode.UNNECESSARY),
new MathContext(3, RoundingMode.UNNECESSARY),
new MathContext(2, RoundingMode.UNNECESSARY),
new MathContext(1, RoundingMode.UNNECESSARY),
};
static int addTests() {
int failures = 0;
for(BigDecimal zero1: zeros) {
for(BigDecimal zero2: zeros) {
BigDecimal expected = new BigDecimal(BigInteger.ZERO,
Math.max(zero1.scale(), zero2.scale()));
BigDecimal result;
if(! (result=zero1.add(zero2)).equals(expected) ) {
failures++;
System.err.println("For classic exact add, expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
if(! (result=zero1.add(zero2, MathContext.UNLIMITED)).equals(expected) ) {
failures++;
System.err.println("For UNLIMITED math context add," +
" expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
if(! (result=zero1.add(zero2, longEnough)).equals(expected) ) {
failures++;
System.err.println("For longEnough math context add," +
" expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
}
}
// Test effect of adding zero to a nonzero value.
for (MathContext mc: contexts) {
for (BigDecimal zero: zeros) {
if (Math.abs((long)zero.scale()) < 100 ) {
int preferredScale = Math.max(zero.scale(), element.scale());
if (mc.getPrecision() != 0) {
if (preferredScale < -4 )
preferredScale = -4;
else if (preferredScale > -(5 - mc.getPrecision())) {
preferredScale = -(5 - mc.getPrecision());
}
}
/*
System.err.println("\n " + element + " +\t" + zero + " =\t" + result);
System.err.println("scales" + element.scale() + " \t" + zero.scale() +
" \t " + result.scale() + "\t precison = " + mc.getPrecision());
System.err.println("expected scale = " + preferredScale);
*/
BigDecimal result = element.add(zero, mc);
if (result.scale() != preferredScale ||
result.compareTo(element) != 0) {
failures++;
System.err.println("Expected scale " + preferredScale +
" result scale was " + result.scale() +
" ; value was " + result);
}
result = zero.add(element, mc);
if (result.scale() != preferredScale ||
result.compareTo(element) != 0) {
failures++;
System.err.println("Expected scale " + preferredScale +
" result scale was " + result.scale() +
" ; value was " + result);
}
result = element.negate().add(zero, mc);
if (result.scale() != preferredScale ||
result.compareTo(element.negate()) != 0) {
failures++;
System.err.println("Expected scale " + preferredScale +
" result scale was " + result.scale() +
" ; value was " + result);
}
result = zero.add(element.negate(), mc);
if (result.scale() != preferredScale ||
result.compareTo(element.negate()) != 0) {
failures++;
System.err.println("Expected scale " + preferredScale +
" result scale was " + result.scale() +
" ; value was " + result);
}
}
}
}
return failures;
}
static int subtractTests() {
int failures = 0;
for(BigDecimal zero1: zeros) {
for(BigDecimal zero2: zeros) {
BigDecimal expected = new BigDecimal(BigInteger.ZERO,
Math.max(zero1.scale(), zero2.scale()));
BigDecimal result;
if(! (result=zero1.subtract(zero2)).equals(expected) ) {
failures++;
System.err.println("For classic exact subtract, expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
if(! (result=zero1.subtract(zero2, MathContext.UNLIMITED)).equals(expected) ) {
failures++;
System.err.println("For UNLIMITED math context subtract," +
" expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
if(! (result=zero1.subtract(zero2, longEnough)).equals(expected) ) {
failures++;
System.err.println("For longEnough math context subtract," +
" expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
}
}
// Test effect of adding zero to a nonzero value.
for (MathContext mc: contexts) {
for (BigDecimal zero: zeros) {
if (Math.abs((long)zero.scale()) < 100 ) {
int preferredScale = Math.max(zero.scale(), element.scale());
if (mc.getPrecision() != 0) {
if (preferredScale < -4 )
preferredScale = -4;
else if (preferredScale > -(5 - mc.getPrecision())) {
preferredScale = -(5 - mc.getPrecision());
}
}
/*
System.err.println("\n " + element + " +\t" + zero + " =\t" + result);
System.err.println("scales" + element.scale() + " \t" + zero.scale() +
" \t " + result.scale() + "\t precison = " + mc.getPrecision());
System.err.println("expected scale = " + preferredScale);
*/
BigDecimal result = element.subtract(zero, mc);
if (result.scale() != preferredScale ||
result.compareTo(element) != 0) {
failures++;
System.err.println("Expected scale " + preferredScale +
" result scale was " + result.scale() +
" ; value was " + result);
}
result = zero.subtract(element, mc);
if (result.scale() != preferredScale ||
result.compareTo(element.negate()) != 0) {
failures++;
System.err.println("Expected scale " + preferredScale +
" result scale was " + result.scale() +
" ; value was " + result);
}
result = element.negate().subtract(zero, mc);
if (result.scale() != preferredScale ||
result.compareTo(element.negate()) != 0) {
failures++;
System.err.println("Expected scale " + preferredScale +
" result scale was " + result.scale() +
" ; value was " + result);
}
result = zero.subtract(element.negate(), mc);
if (result.scale() != preferredScale ||
result.compareTo(element) != 0) {
failures++;
System.err.println("Expected scale " + preferredScale +
" result scale was " + result.scale() +
" ; value was " + result);
}
}
}
}
return failures;
}
static int multiplyTests() {
int failures = 0;
BigDecimal ones[] = {
BigDecimal.valueOf(1, 0),
BigDecimal.valueOf(10, 1),
BigDecimal.valueOf(1000, 3),
BigDecimal.valueOf(100000000, 8),
};
List<BigDecimal> values = new LinkedList<BigDecimal>();
values.addAll(Arrays.asList(zeros));
values.addAll(Arrays.asList(ones));
for(BigDecimal zero1: zeros) {
for(BigDecimal value: values) {
BigDecimal expected = new BigDecimal(BigInteger.ZERO,
(int)Math.min(Math.max((long)zero1.scale()+value.scale(),
Integer.MIN_VALUE ),
Integer.MAX_VALUE ) );
BigDecimal result;
if(! (result=zero1.multiply(value)).equals(expected) ) {
failures++;
System.err.println("For classic exact multiply, expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
if(! (result=zero1.multiply(value, MathContext.UNLIMITED)).equals(expected) ) {
failures++;
System.err.println("For UNLIMITED math context multiply," +
" expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
if(! (result=zero1.multiply(value, longEnough)).equals(expected) ) {
failures++;
System.err.println("For longEnough math context multiply," +
" expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
}
}
return failures;
}
static int divideTests() {
int failures = 0;
BigDecimal [] ones = {
BigDecimal.valueOf(1, 0),
BigDecimal.valueOf(10, -1),
BigDecimal.valueOf(100, -2),
BigDecimal.valueOf(1000, -3),
BigDecimal.valueOf(1000000, -5),
};
for(BigDecimal one: ones) {
for(BigDecimal zero: zeros) {
BigDecimal expected = new BigDecimal(BigInteger.ZERO,
(int)Math.min(Math.max((long)zero.scale() - one.scale(),
Integer.MIN_VALUE ),
Integer.MAX_VALUE ) );
BigDecimal result;
if(! (result=zero.divide(one)).equals(expected) ) {
failures++;
System.err.println("For classic exact divide, expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
if(! (result=zero.divide(one, MathContext.UNLIMITED)).equals(expected) ) {
failures++;
System.err.println("For UNLIMITED math context divide," +
" expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
if(! (result=zero.divide(one, longEnough)).equals(expected) ) {
failures++;
System.err.println("For longEnough math context divide," +
" expected scale of " +
expected.scale() + "; got " +
result.scale() + ".");
}
}
}
return failures;
}
static int setScaleTests() {
int failures = 0;
int scales[] = {
Integer.MIN_VALUE,
Integer.MIN_VALUE+1,
-10000000,
-3,
-2,
-1,
0,
1,
2,
3,
10,
10000000,
Integer.MAX_VALUE-1,
Integer.MAX_VALUE
};
for(BigDecimal zero: zeros) {
for(int scale: scales) {
try {
BigDecimal bd = zero.setScale(scale);
}
catch (ArithmeticException e) {
failures++;
System.err.println("Exception when trying to set a scale of " + scale +
" on " + zero);
}
}
}
return failures;
}
static int toEngineeringStringTests() {
int failures = 0;
String [][] testCases = {
{"0E+10", "0.00E+12"},
{"0E+9", "0E+9"},
{"0E+8", "0.0E+9"},
{"0E+7", "0.00E+9"},
{"0E-10", "0.0E-9"},
{"0E-9", "0E-9"},
{"0E-8", "0.00E-6"},
{"0E-7", "0.0E-6"},
};
for(String[] testCase: testCases) {
BigDecimal bd = new BigDecimal(testCase[0]);
String result = bd.toEngineeringString();
if (!result.equals(testCase[1]) ||
!bd.equals(new BigDecimal(result))) {
failures++;
System.err.println("From input ``" + testCase[0] + ",'' " +
" bad engineering string output ``" + result +
"''; expected ``" + testCase[1] + ".''");
}
}
return failures;
}
static int ulpTests() {
int failures = 0;
for(BigDecimal zero: zeros) {
BigDecimal result;
BigDecimal expected = BigDecimal.valueOf(1, zero.scale());
if (! (result=zero.ulp()).equals(expected) ) {
failures++;
System.err.println("Unexpected ulp value for zero value " +
zero + "; expected " + expected +
", got " + result);
}
}
return failures;
}
static int setScaleDoesNotMutateTest() {
BigDecimal total = new BigDecimal("258815507198903607775511093103396443816569106750031264155319238473795838680758514810110764742309284477206138527975952150289602995045050194333030191178778772026538699925775139201970526695485362661420908248887297829319881475178467494779683293036572059595504702727301324759997409522995072582369210284334718757260859794972695026582432867589093687280300148141501712013226636373167978223780290547640482160818746599330924736802844173226042389174403401903999447463440670236056324929325189403433689"
+ ".426167432065785331444814035799717606745777287606858873045971898862329763544687891847664736523584843544347118836628373041412918374550458884706686730726101338872517021688769782894793734049819222924171842793485919753186993388451909096042127903835765393729547730953942175461146061715108701615615142134282261293656760570061554783195726716403304101469782303957325142638493327692352838806741611887655695029948975509680496573999174402058593454203190963443179532640446352828089016874853634851387762579319853267317320515941105912189838719919259277721994880193541634872882180184303434360412344059435559680494807415573269199203376126242271766939666939316648575065702750502798973418978204972336924254702551350654650573582614211506856383897692911422458286912085339575875324832979140870119455620532272318122103640233069115700020760625493816902806241630788230268031695140687964931377988962507263990468276009750998066442971308866347136022907166625330623130307555914930120150437900510530537258665172619821272937026713977709974434967165159545592482710663639966781678268622620229577009317698254134914742098420792313931843709810905414336383757407675429663714210967924767434203021205270369316797752411974617662200898086335322218191674846795163102021505555508444216708745911194321674887527227200297039471799580744303346354057273540730643842091810899490590914195225087593013834388801018488174855060306804024894292757613618190472234110859436472645203753139820658279559340251226992556744343475086923568365637919479462424794554522865559888240039662899509652221329892034706445253487898044421278283079233226845124525434586324657471286953226255430662125870993375281512713207125720748163498642795960457639954616530163959004770092547297392499137383176609646505351001304840762905826237024982330597805063521162285806541220110524989649256399233792799406995068469271941269511818994954109392839548141262324660472253632382325038836831429045617036015122388070240133760858500132713255407855625837956886349324981003917084922808187223285051144454915441134217743066575863563572152133978905444998209075763950909784148142018992367290485890072303179512881131769414783097454103103347826517701720263541869335631166977965013552647906729408522950996105479525445916501155305220090853891226367184989434453290788068397817927893708837722255115237672194162924260945492012622891770365546831236789867922136747819364833843397165107825773447549885351449899330007200651144003961228091210630807333236718793283427788965479074476288255387824982443633190938302785760754436525586544523339170400053128503337395428393881357669568532722167493096151221381017320147344991331421789379785964440840684363041795410525097564979585773948558651896834067324427900848255265001498890329859444233861478388742393060996236783742654761350763876989363052609107226398858310051497856931093693697981165801539060516895227818925342535261227134364063673285588256280386915163875872231395348293505967057794409379709079685798908660258077792158532257603211711587587586356431658240229896344639704");
if (total.setScale(0, RoundingMode.DOWN).equals(total.setScale(0, RoundingMode.DOWN))) {
return 0;
} else {
return 1;
}
}
public static void main(String argv[]) {
int failures = 0;
failures += addTests();
failures += subtractTests();
failures += multiplyTests();
failures += divideTests();
failures += setScaleTests();
failures += toEngineeringStringTests();
failures += ulpTests();
failures += setScaleDoesNotMutateTest();
if (failures > 0 ) {
throw new RuntimeException("Incurred " + failures + " failures" +
" testing the preservation of zero scales.");
}
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 1998, 2020, 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
* @run main BigIntegerParallelMultiplyTest
* @summary tests parallelMultiply() method in BigInteger
* @author Heinz Kabutz heinz@javaspecialists.eu
*/
import java.math.BigInteger;
import java.util.function.BinaryOperator;
/**
* This is a simple test class created to ensure that the results
* of multiply() are the same as multiplyParallel(). We calculate
* the Fibonacci numbers using Dijkstra's sum of squares to get
* very large numbers (hundreds of thousands of bits).
*
* @author Heinz Kabutz, heinz@javaspecialists.eu
*/
public class BigIntegerParallelMultiplyTest {
public static BigInteger fibonacci(int n, BinaryOperator<BigInteger> multiplyOperator) {
if (n == 0) return BigInteger.ZERO;
if (n == 1) return BigInteger.ONE;
int half = (n + 1) / 2;
BigInteger f0 = fibonacci(half - 1, multiplyOperator);
BigInteger f1 = fibonacci(half, multiplyOperator);
if (n % 2 == 1) {
BigInteger b0 = multiplyOperator.apply(f0, f0);
BigInteger b1 = multiplyOperator.apply(f1, f1);
return b0.add(b1);
} else {
BigInteger b0 = f0.shiftLeft(1).add(f1);
return multiplyOperator.apply(b0, f1);
}
}
public static void main(String[] args) throws Exception {
compare(1000, 324);
compare(10_000, 3473);
compare(100_000, 34883);
compare(1_000_000, 347084);
}
private static void compare(int n, int expectedBitCount) {
BigInteger multiplyResult = fibonacci(n, BigInteger::multiply);
BigInteger parallelMultiplyResult = fibonacci(n, BigInteger::parallelMultiply);
checkBitCount(n, expectedBitCount, multiplyResult);
checkBitCount(n, expectedBitCount, parallelMultiplyResult);
if (!multiplyResult.equals(parallelMultiplyResult))
throw new AssertionError("multiply() and parallelMultiply() give different results");
}
private static void checkBitCount(int n, int expectedBitCount, BigInteger number) {
if (number.bitCount() != expectedBitCount)
throw new AssertionError(
"bitCount of fibonacci(" + n + ") was expected to be " + expectedBitCount
+ " but was " + number.bitCount());
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2013, 2021, 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 6910473 8272541
* @summary Test that bitLength() is not negative
* @author Dmitry Nadezhin
*/
import java.math.BigInteger;
import java.util.function.Supplier;
public class BitLengthOverflow {
private static void test(Supplier<BigInteger> s) {
try {
BigInteger x = s.get();
System.out.println("Surprisingly passed with correct bitLength() " +
x.bitLength());
} catch (ArithmeticException e) {
// expected
System.out.println("Overflow reported by ArithmeticException, as expected");
} catch (OutOfMemoryError e) {
// possible
System.err.println("BitLengthOverflow skipped: OutOfMemoryError");
System.err.println("Run jtreg with -javaoption:-Xmx8g");
}
}
public static void main(String[] args) {
test(() -> {
// x = pow(2,Integer.MAX_VALUE)
BigInteger x = BigInteger.ONE.shiftLeft(Integer.MAX_VALUE);
if (x.bitLength() != (1L << 31)) {
throw new RuntimeException("Incorrect bitLength() " +
x.bitLength());
}
return x;
});
test(() -> {
BigInteger a = BigInteger.ONE.shiftLeft(1073742825);
BigInteger b = BigInteger.ONE.shiftLeft(1073742825);
return a.multiply(b);
});
}
}

View file

@ -0,0 +1,148 @@
/*
* Copyright (c) 2023, 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.
*/
import jdk.test.lib.RandomFactory;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.math.Accessor;
import java.math.BigInteger;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @test
* @bug 8319174
* @summary Exercises minimality of BigInteger.mag field (use -Dseed=X to set PRANDOM seed)
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @build java.base/java.math.Accessor
* @key randomness
* @run junit/othervm -DmaxDurationMillis=3000 ByteArrayConstructorTest
*/
public class ByteArrayConstructorTest {
private static final int DEFAULT_MAX_DURATION_MILLIS = 3_000;
public static final int N = 1_024;
private static int maxDurationMillis;
private static final Random rnd = RandomFactory.getRandom();
private volatile boolean stop = false;
@BeforeAll
static void setMaxDurationMillis() {
maxDurationMillis = Math.max(maxDurationMillis(), 0);
}
@Test
public void testNonNegative() throws InterruptedException {
byte[] ba = nonNegativeBytes();
doBigIntegers(ba, ba[0]); // a mask to flip to 0 and back to ba[0]
}
@Test
public void testNegative() throws InterruptedException {
byte[] ba = negativeBytes();
doBigIntegers(ba, (byte) ~ba[0]); // a mask to flip to -1 and back to ba[0]
}
/*
* Starts a thread th that keeps flipping the "sign" byte in the array ba
* from the original value to 0 or -1 and back, depending on ba[0] being
* non-negative or negative, resp.
* (ba is "big endian", the least significant byte is the one with the
* highest index.)
*
* In the meantime, the current thread keeps creating BigInteger instances
* with ba and checks that the internal invariant holds, despite the
* attempts by thread th to racily modify ba.
* It does so at least as indicated by maxDurationMillis.
*
* Finally, this thread requests th to stop and joins with it, either
* because maxDurationMillis has expired, or because of an invalid invariant.
*/
private void doBigIntegers(byte[] ba, byte mask) throws InterruptedException {
Thread th = new Thread(() -> {
while (!stop) {
ba[0] ^= mask;
}
});
th.start();
try {
createBigIntegers(maxDurationMillis, ba);
} finally {
stop = true;
th.join(1_000);
}
}
private void createBigIntegers(int maxDurationMillis, byte[] ba) {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < maxDurationMillis) {
BigInteger bi = new BigInteger(ba);
int[] mag = Accessor.mag(bi);
assertTrue(mag.length == 0 || mag[0] != 0,
String.format("inconsistent BigInteger: mag.length=%d, mag[0]=%d",
mag.length, mag[0]));
}
}
private byte[] nonNegativeBytes() {
byte[] ba = new byte[1 + N];
byte b0;
while ((b0 = (byte) rnd.nextInt()) < 0); // empty body
rnd.nextBytes(ba);
ba[0] = b0;
/* Except for ba[0], fill most significant half with zeros. */
for (int i = 1; i <= N / 2; ++i) {
ba[i] = 0;
}
return ba;
}
private byte[] negativeBytes() {
byte[] ba = new byte[1 + N];
byte b0;
while ((b0 = (byte) rnd.nextInt()) >= 0); // empty body
rnd.nextBytes(ba);
ba[0] = b0;
/* Except for ba[0], fill most significant half with -1 bytes. */
for (int i = 1; i <= N / 2; ++i) {
ba[i] = -1;
}
return ba;
}
private static int maxDurationMillis() {
try {
return Integer.parseInt(System.getProperty("maxDurationMillis",
Integer.toString(DEFAULT_MAX_DURATION_MILLIS)));
} catch (NumberFormatException ignore) {
}
return DEFAULT_MAX_DURATION_MILLIS;
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2006, 2025, 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 6473768
* @summary Tests of BigInteger.compareTo
*/
import java.math.*;
import static java.math.BigInteger.*;
public class CompareToTests {
private static int compareToTests() {
int failures = 0;
final BigInteger MINUS_ONE = BigInteger.ONE.negate();
final BigInteger TWO_POW_126 = ONE.shiftLeft(126);
final BigInteger TWO_POW_127 = ONE.shiftLeft(127);
final BigInteger TWO_POW_128 = ONE.shiftLeft(128);
// First operand, second operand, expected compareTo result
BigInteger [][] testCases = {
// Basics
{valueOf(0), valueOf(0), ZERO},
{valueOf(0), valueOf(1), MINUS_ONE},
{valueOf(1), valueOf(2), MINUS_ONE},
{valueOf(2), valueOf(1), ONE},
{valueOf(10), valueOf(10), ZERO},
// Various relative lengths of internal mag array.
{TWO_POW_127, TWO_POW_127, ZERO},
{TWO_POW_127.negate(), TWO_POW_127, MINUS_ONE},
{TWO_POW_128.or(TWO_POW_126), TWO_POW_128, ONE},
{TWO_POW_128.or(TWO_POW_126), TWO_POW_128.negate(), ONE},
{TWO_POW_128, TWO_POW_128.or(TWO_POW_126), MINUS_ONE},
{TWO_POW_128.negate(), TWO_POW_128.or(TWO_POW_126), MINUS_ONE},
{TWO_POW_127, TWO_POW_128, MINUS_ONE},
{TWO_POW_127.negate(), TWO_POW_128, MINUS_ONE},
{TWO_POW_128, TWO_POW_127, ONE},
{TWO_POW_128.negate(), TWO_POW_127, MINUS_ONE},
// Long boundary and near boundary values
{valueOf(Long.MAX_VALUE), valueOf(Long.MAX_VALUE), ZERO},
{valueOf(Long.MAX_VALUE).negate(), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MAX_VALUE-1), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MAX_VALUE-1).negate(), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MIN_VALUE), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MIN_VALUE).negate(), valueOf(Long.MAX_VALUE), ONE},
{valueOf(Long.MIN_VALUE+1), valueOf(Long.MAX_VALUE), MINUS_ONE},
{valueOf(Long.MIN_VALUE+1).negate(), valueOf(Long.MAX_VALUE), ZERO},
{valueOf(Long.MAX_VALUE), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MAX_VALUE).negate(), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MAX_VALUE-1), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MAX_VALUE-1).negate(), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MIN_VALUE), valueOf(Long.MIN_VALUE), ZERO},
{valueOf(Long.MIN_VALUE).negate(), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MIN_VALUE+1), valueOf(Long.MIN_VALUE), ONE},
{valueOf(Long.MIN_VALUE+1).negate(), valueOf(Long.MIN_VALUE), ONE},
};
for (BigInteger[] testCase : testCases) {
BigInteger a = testCase[0];
BigInteger a_negate = a.negate();
BigInteger b = testCase[1];
BigInteger b_negate = b.negate();
int expected = testCase[2].intValue();
failures += compareToTest(a, b, expected);
failures += compareToTest(a_negate, b_negate, -expected);
}
return failures;
}
private static int compareToTest(BigInteger a, BigInteger b, int expected) {
int result = a.compareTo(b);
int failed = (result==expected) ? 0 : 1;
if (failed == 1) {
System.err.println("(" + a + ").compareTo(" + b + ") => " + result +
"\n\tExpected " + expected);
}
return failed;
}
public static void main(String argv[]) {
int failures = 0;
failures += compareToTests();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
" failures while testing exact compareTo.");
}
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 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 8021203
* @summary Test that doubleValue() doesn't overflow
* @author Dmitry Nadezhin
*/
import java.math.BigInteger;
public class DoubleValueOverflow {
public static void main(String[] args) {
try {
BigInteger x = BigInteger.valueOf(2).shiftLeft(Integer.MAX_VALUE); // x = pow(2,pow(2,31))
if (x.doubleValue() != Double.POSITIVE_INFINITY) {
throw new RuntimeException("Incorrect doubleValue() " + x.doubleValue());
}
System.out.println("Passed with correct result");
} catch (ArithmeticException e) {
// expected
System.out.println("Overflow is reported by ArithmeticException, as expected");
} catch (OutOfMemoryError e) {
// possible
System.err.println("DoubleValueOverflow skipped: OutOfMemoryError");
System.err.println("Run jtreg with -javaoption:-Xmx8g");
}
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2009, 2025, 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 6371401
* @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE
* @requires os.maxMemory >= 1g
* @run main/othervm -Xmx512m ExtremeShiftingTests
*/
import java.math.BigInteger;
import static java.math.BigInteger.*;
public class ExtremeShiftingTests {
public static void main(String... args) {
BigInteger bi = ONE.shiftLeft(Integer.MIN_VALUE);
if (!bi.equals(ZERO))
throw new RuntimeException("1 << " + Integer.MIN_VALUE);
bi = ZERO.shiftLeft(Integer.MIN_VALUE);
if (!bi.equals(ZERO))
throw new RuntimeException("0 << " + Integer.MIN_VALUE);
bi = BigInteger.valueOf(-1);
bi = bi.shiftLeft(Integer.MIN_VALUE);
if (!bi.equals(BigInteger.valueOf(-1)))
throw new RuntimeException("-1 << " + Integer.MIN_VALUE);
try {
ONE.shiftRight(Integer.MIN_VALUE);
throw new RuntimeException("1 >> " + Integer.MIN_VALUE);
} catch (ArithmeticException ae) {
; // Expected
}
bi = ZERO.shiftRight(Integer.MIN_VALUE);
if (!bi.equals(ZERO))
throw new RuntimeException("0 >> " + Integer.MIN_VALUE);
try {
BigInteger.valueOf(-1).shiftRight(Integer.MIN_VALUE);
throw new RuntimeException("-1 >> " + Integer.MIN_VALUE);
} catch (ArithmeticException ae) {
; // Expected
}
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2023, 2024, 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.
*/
import java.math.BigInteger;
/*
* @test
* @bug 8310813
* @summary Check hashCode implementation against reference values
*/
public class HashCode {
// This test guards against inadvertent changes to BigInteger.hashCode,
// by checking generated hashCode values against reference values
// captured immediately before 8310813
public static void main(String[] args) {
equals( 0, BigInteger.ZERO);
equals( 1, BigInteger.ONE);
equals( 2, BigInteger.TWO);
equals( 10, BigInteger.TEN);
equals( -128, BigInteger.valueOf(Byte.MIN_VALUE));
equals( 127, BigInteger.valueOf(Byte.MAX_VALUE));
equals( -32768, BigInteger.valueOf(Short.MIN_VALUE));
equals( 32767, BigInteger.valueOf(Short.MAX_VALUE));
equals( 0, BigInteger.valueOf(Character.MIN_VALUE));
equals( 65535, BigInteger.valueOf(Character.MAX_VALUE));
equals(-2147483648, BigInteger.valueOf(Integer.MIN_VALUE));
equals( 2147483647, BigInteger.valueOf(Integer.MAX_VALUE));
equals(-2147483648, BigInteger.valueOf(Long.MIN_VALUE));
equals( 2147483616, BigInteger.valueOf(Long.MAX_VALUE));
equals( -1, BigInteger.valueOf(-1));
// a 37-byte negative number, generated at random
equals( 1428257188, new BigInteger("""
-5573526435790097067262357965922443376770234990700620666883\
2705705469477701887396205062479"""));
// a 123-byte positive number, generated at random
equals( -412503667, new BigInteger("""
13093241912251296135908856604398494061635394768699286753760\
22827291528069076557720973813183142494646514532475660126948\
43316474303725664231917408569680292008962577772928370936861\
12952691245923210726443405774197400117701581498597123145452\
15111774818054200162634242662445757757255702394598235971294\
50"""));
}
private static void equals(int expectedHashCode, BigInteger i) {
int actualHashCode = i.hashCode();
if (expectedHashCode != actualHashCode)
throw new AssertionError("%s: expectedHashCode=%s, actual=%s"
.formatted(i, expectedHashCode, actualHashCode));
}
}

View file

@ -0,0 +1,221 @@
/*
* Copyright (c) 2018, 2025, 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 8200698
* @summary Tests that exceptions are thrown for ops which would overflow
* @requires (sun.arch.data.model == "64" & os.maxMemory >= 4g)
* @run junit/othervm/timeout=480 -Xmx4g LargeValueExceptions
*/
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.math.BigInteger;
import static java.math.BigInteger.ONE;
//
// The intent of this test is to probe the boundaries between overflow and
// non-overflow, principally for multiplication and squaring, specifically
// the largest values which should not overflow and the smallest values which
// should. The transition values used are not necessarily at the exact
// boundaries but should be "close." Quite a few different values were used
// experimentally before settling on the ones in this test. For multiplication
// and squaring all cases are exercised: definite overflow and non-overflow
// which can be detected "up front," and "indefinite" overflow, i.e., overflow
// which cannot be detected up front so further calculations are required.
//
// Testing negative values is unnecessary. For both multiplication and squaring
// the paths lead to the Toom-Cook algorithm where the signum is used only to
// determine the sign of the result and not in the intermediate calculations.
// This is also true for exponentiation.
//
// @Test annotations with optional element "enabled" set to "false" should
// succeed when "enabled" is set to "true" but they take too to run in the
// course of the typical regression test execution scenario.
//
public class LargeValueExceptions {
// BigInteger.MAX_MAG_LENGTH
private static final int MAX_INTS = 1 << 26;
// Number of bits corresponding to MAX_INTS
private static final long MAX_BITS = (0xffffffffL & MAX_INTS) << 5L;
// Half BigInteger.MAX_MAG_LENGTH
private static final int MAX_INTS_HALF = MAX_INTS / 2;
// --- squaring ---
// Largest no overflow determined by examining data lengths alone.
@Test
@Disabled
public void squareNoOverflow() {
BigInteger x = ONE.shiftLeft(16*MAX_INTS - 1).subtract(ONE);
BigInteger y = x.multiply(x);
}
// Smallest no overflow determined by extra calculations.
@Test
@Disabled
public void squareIndefiniteOverflowSuccess() {
BigInteger x = ONE.shiftLeft(16*MAX_INTS - 1);
BigInteger y = x.multiply(x);
}
// Largest overflow detected by extra calculations.
@Test
@Disabled
public void squareIndefiniteOverflowFailure() {
Assertions.assertThrows(ArithmeticException.class, () -> {
BigInteger x = ONE.shiftLeft(16*MAX_INTS).subtract(ONE);
BigInteger y = x.multiply(x);
});
}
// Smallest overflow detected by examining data lengths alone.
@Test
public void squareDefiniteOverflow() {
Assertions.assertThrows(ArithmeticException.class, () -> {
BigInteger x = ONE.shiftLeft(16*MAX_INTS);
BigInteger y = x.multiply(x);
});
}
// --- multiplication ---
// Largest no overflow determined by examining data lengths alone.
@Test
@Disabled
public void multiplyNoOverflow() {
final int halfMaxBits = MAX_INTS_HALF << 5;
BigInteger x = ONE.shiftLeft(halfMaxBits).subtract(ONE);
BigInteger y = ONE.shiftLeft(halfMaxBits - 1).subtract(ONE);
BigInteger z = x.multiply(y);
}
// Smallest no overflow determined by extra calculations.
@Test
@Disabled
public void multiplyIndefiniteOverflowSuccess() {
BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2) - 1);
long m = MAX_BITS - x.bitLength();
BigInteger y = ONE.shiftLeft((int)(MAX_BITS/2) - 1);
long n = MAX_BITS - y.bitLength();
if (m + n != MAX_BITS) {
throw new RuntimeException("Unexpected leading zero sum");
}
BigInteger z = x.multiply(y);
}
// Largest overflow detected by extra calculations.
@Test
@Disabled
public void multiplyIndefiniteOverflowFailure() {
Assertions.assertThrows(ArithmeticException.class, () -> {
BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE);
long m = MAX_BITS - x.bitLength();
BigInteger y = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE);
long n = MAX_BITS - y.bitLength();
if (m + n != MAX_BITS) {
throw new RuntimeException("Unexpected leading zero sum");
}
BigInteger z = x.multiply(y);
});
}
// Smallest overflow detected by examining data lengths alone.
@Test
public void multiplyDefiniteOverflow() {
Assertions.assertThrows(ArithmeticException.class, () -> {
// multiply by 4 as MAX_INTS_HALF refers to ints
byte[] xmag = new byte[4*MAX_INTS_HALF];
xmag[0] = (byte)0xff;
BigInteger x = new BigInteger(1, xmag);
byte[] ymag = new byte[4*MAX_INTS_HALF + 1];
ymag[0] = (byte)0xff;
BigInteger y = new BigInteger(1, ymag);
BigInteger z = x.multiply(y);
});
}
// --- exponentiation ---
@Test
public void powOverflow() {
Assertions.assertThrows(ArithmeticException.class, () -> {
BigInteger.TEN.pow(Integer.MAX_VALUE);
});
}
@Test
public void powOverflow1() {
Assertions.assertThrows(ArithmeticException.class, () -> {
int shift = 20;
int exponent = 1 << shift;
BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent));
BigInteger y = x.pow(exponent);
});
}
@Test
public void powOverflow2() {
Assertions.assertThrows(ArithmeticException.class, () -> {
int shift = 20;
int exponent = 1 << shift;
BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).add(ONE);
BigInteger y = x.pow(exponent);
});
}
@Test
@Disabled
public void powOverflow3() {
Assertions.assertThrows(ArithmeticException.class, () -> {
int shift = 20;
int exponent = 1 << shift;
BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).subtract(ONE);
BigInteger y = x.pow(exponent);
});
}
@Test
@Disabled
public void powOverflow4() {
int shift = 20;
int exponent = 1 << shift;
BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent - 1)).add(ONE);
BigInteger y = x.pow(exponent);
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2020, 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 8225603
* @summary Tests whether modInverse() completes in a reasonable time
* @run main/othervm ModInvTime
*/
import java.math.BigInteger;
public class ModInvTime {
public static void main(String[] args) throws InterruptedException {
BigInteger prime = new BigInteger("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643");
BigInteger s = new BigInteger("9552729729729327851382626410162104591956625415831952158766936536163093322096473638446154604799898109762512409920799");
System.out.format("int length: %d, modulus length: %d%n",
s.bitLength(), prime.bitLength());
System.out.println("Computing modular inverse ...");
BigInteger mi = s.modInverse(prime);
System.out.format("Modular inverse: %s%n", mi);
check(s, prime, mi);
BigInteger ns = s.negate();
BigInteger nmi = ns.modInverse(prime);
System.out.format("Modular inverse of negation: %s%n", nmi);
check(ns, prime, nmi);
}
public static void check(BigInteger val, BigInteger mod, BigInteger inv) {
BigInteger r = inv.multiply(val).remainder(mod);
if (r.signum() == -1)
r = r.add(mod);
if (!r.equals(BigInteger.ONE))
throw new RuntimeException("Numerically incorrect modular inverse");
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 1998, 2018, 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 8215759
* @summary test BigInteger modPow method (use -Dseed=X to set PRNG seed)
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @run main ModPow
* @key randomness
*/
import java.math.BigInteger;
import java.util.Random;
import jdk.test.lib.RandomFactory;
public class ModPow {
public static void main(String[] args) {
Random rnd = RandomFactory.getRandom();
for (int i=0; i<2000; i++) {
// Clamp random modulus to a positive value or modPow() will
// throw an ArithmeticException.
BigInteger m = new BigInteger(800, rnd).max(BigInteger.ONE);
BigInteger base = new BigInteger(16, rnd);
if (rnd.nextInt() % 1 == 0)
base = base.negate();
BigInteger exp = new BigInteger(8, rnd);
BigInteger z = base.modPow(exp, m);
BigInteger w = base.pow(exp.intValue()).mod(m);
if (!z.equals(w)){
System.err.println(base +" ** " + exp + " mod "+ m);
System.err.println("modPow : " + z);
System.err.println("pow.mod: " + w);
throw new RuntimeException("BigInteger modPow failure.");
}
}
}
}

View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2003, 2017, 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
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @run main ModPow65537
* @bug 4891312 8074460 8078672
* @summary verify that modPow() not broken by the special case for 65537 (use -Dseed=X to set PRNG seed)
* @author Andreas Sterbenz
* @key randomness
*/
import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import java.util.Random;
import jdk.test.lib.RandomFactory;
public class ModPow65537 {
public static void main(String[] args) throws Exception {
// SunRsaSign uses BigInteger internally
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "SunRsaSign");
kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(65537)));
KeyPair kp = kpg.generateKeyPair();
testSigning(kp);
kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(65539)));
kp = kpg.generateKeyPair();
testSigning(kp);
kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(3)));
kp = kpg.generateKeyPair();
testSigning(kp);
// basic known answer test
BigInteger base = new BigInteger("19058071224156864789844466979330892664777520457048234786139035643344145635582");
BigInteger mod = new BigInteger("75554098474976067521257305210610421240510163914613117319380559667371251381587");
BigInteger exp1 = BigInteger.valueOf(65537);
BigInteger exp2 = BigInteger.valueOf(75537);
BigInteger exp3 = new BigInteger("13456870775607312149");
BigInteger res1 = new BigInteger("5770048609366563851320890693196148833634112303472168971638730461010114147506");
BigInteger res2 = new BigInteger("63446979364051087123350579021875958137036620431381329472348116892915461751531");
BigInteger res3 = new BigInteger("39016891919893878823999350081191675846357272199067075794096200770872982089502");
if (base.modPow(exp1, mod).equals(res1) == false) {
throw new Exception("Error using " + exp1);
}
if (base.modPow(exp2, mod).equals(res2) == false) {
throw new Exception("Error using " + exp2);
}
if (base.modPow(exp3, mod).equals(res3) == false) {
throw new Exception("Error using " + exp3);
}
System.out.println("Passed");
}
private static void testSigning(KeyPair kp) throws Exception {
System.out.println(kp.getPublic());
byte[] data = new byte[1024];
Random random = RandomFactory.getRandom();
random.nextBytes(data);
Signature sig = Signature.getInstance("SHA1withRSA", "SunRsaSign");
sig.initSign(kp.getPrivate());
sig.update(data);
byte[] sigBytes = sig.sign();
sig.initVerify(kp.getPublic());
sig.update(data);
if (sig.verify(sigBytes) == false) {
throw new Exception("signature verification failed");
}
System.out.println("OK");
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 1998, 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 4098742
@summary Test biginteger modpow method
@author Michael McCloskey
@run main/othervm ModPowPowersof2
*/
import java.math.BigInteger;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.File;
import java.io.IOException;
/**
* This class tests to see if using modPow on a power
* of two crashes the vm
*
*/
public class ModPowPowersof2 {
public static void main(String args[]) throws Exception {
// Construct a command that runs the test in other vm
String[] command = new String[4];
int n = 0;
command[n++] = System.getProperty("java.home") + File.separator +
"bin" + File.separator + "java";
if (System.getProperty("java.class.path") != null) {
command[n++] = "-classpath";
command[n++] = System.getProperty("java.class.path");
}
command[n++] = "ModPowPowersof2$ModTester";
// Exec another vm to run test in
Process p = null;
p = Runtime.getRuntime().exec(command);
// Read the result to determine if test failed
BufferedReader in = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String s;
s = in.readLine();
if (s == null)
throw new RuntimeException("ModPow causes vm crash");
}
public static class ModTester {
public static void main(String [] args) {
BigInteger two = BigInteger.valueOf(2);
BigInteger four = BigInteger.valueOf(4);
two.modPow(two, BigInteger.valueOf(4));
two.modPow(two, BigInteger.valueOf(8));
two.modPow(four, BigInteger.valueOf(8));
System.out.println("success");
}
}
}

View file

@ -0,0 +1,191 @@
/*
* Copyright (c) 2024, 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.
*/
import jdk.test.lib.RandomFactory;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.Arguments;
import java.math.BigInteger;
import java.math.MutableBigIntegerBox;
import java.util.Arrays;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static java.math.MutableBigIntegerBox.*;
/**
* @test
* @bug 8336274
* @summary Tests for correctness of MutableBigInteger.leftShift(int)
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @build java.base/java.math.MutableBigIntegerBox
* @key randomness
* @run junit MutableBigIntegerShiftTests
*/
public class MutableBigIntegerShiftTests {
private static final int ORDER_SMALL = 60;
private static final int ORDER_MEDIUM = 100;
private static final Random random = RandomFactory.getRandom();
private static int[] orders() {
return new int[] { ORDER_SMALL, ORDER_MEDIUM };
}
@ParameterizedTest
@MethodSource("orders")
public void shift(int order) {
for (int i = 0; i < 100; i++) {
test(fetchNumber(order), random.nextInt(200));
}
}
@ParameterizedTest
@MethodSource("pathTargetedCases")
public void test(MutableBigIntegerBox x, int n) {
leftShiftAssertions(x, n);
}
private static Arguments[] pathTargetedCases() {
return new Arguments[] {
// intLen == 0
Arguments.of(MutableBigIntegerBox.ZERO,
random.nextInt(33)),
// intLen != 0 && n <= leadingZeros
Arguments.of(new MutableBigIntegerBox(new int[] { (int) random.nextLong(1L, 1L << 16) }),
random.nextInt(1, 17)),
// intLen != 0 && n > leadingZeros && nBits <= leadingZeros && value.length < newLen && nBits == 0
Arguments.of(new MutableBigIntegerBox(new int[] { (int) random.nextLong(1L, 1L << 32) }),
32),
// intLen != 0 && n > leadingZeros && nBits <= leadingZeros && value.length < newLen && nBits != 0
Arguments.of(new MutableBigIntegerBox(new int[] { (int) random.nextLong(1L, 1L << 16) }),
32 + random.nextInt(1, 17)),
// intLen != 0 && n > leadingZeros && nBits <= leadingZeros && value.length >= newLen && nBits == 0
// && newOffset != offset
Arguments.of(new MutableBigIntegerBox(new int[] { random.nextInt(), (int) random.nextLong(1L, 1L << 32) }, 1, 1),
32),
// intLen != 0 && n > leadingZeros && nBits <= leadingZeros && value.length >= newLen && nBits == 0
// && newOffset == offset
Arguments.of(new MutableBigIntegerBox(new int[] { (int) random.nextLong(1L, 1L << 32), random.nextInt() }, 0, 1),
32),
// intLen != 0 && n > leadingZeros && nBits <= leadingZeros && value.length >= newLen && nBits != 0
// && newOffset != offset
Arguments.of(new MutableBigIntegerBox(new int[] { random.nextInt(), (int) random.nextLong(1L, 1L << 16) }, 1, 1),
32 + random.nextInt(1, 17)),
// intLen != 0 && n > leadingZeros && nBits <= leadingZeros && value.length >= newLen && nBits != 0
// && newOffset == offset
Arguments.of(new MutableBigIntegerBox(new int[] { (int) random.nextLong(1L, 1L << 16), random.nextInt() }, 0, 1),
32 + random.nextInt(1, 17)),
// intLen != 0 && n > leadingZeros && nBits > leadingZeros && value.length < newLen
Arguments.of(new MutableBigIntegerBox(new int[] { (int) random.nextLong(1L << 15, 1L << 32) }),
random.nextInt(17, 32)),
// intLen != 0 && n > leadingZeros && nBits > leadingZeros && value.length >= newLen && newOffset != offset
Arguments.of(new MutableBigIntegerBox(new int[] { random.nextInt(), (int) random.nextLong(1L << 15, 1L << 32) }, 1, 1),
random.nextInt(17, 32)),
// intLen != 0 && n > leadingZeros && nBits > leadingZeros && value.length >= newLen && newOffset == offset
Arguments.of(new MutableBigIntegerBox(new int[] { (int) random.nextLong(1L << 15, 1L << 32), random.nextInt() }, 0, 1),
random.nextInt(17, 32)),
};
}
private static void leftShiftAssertions(MutableBigIntegerBox x, int n) {
MutableBigIntegerBox xShifted = x.shiftLeft(n);
assertEquals(x.multiply(new MutableBigIntegerBox(BigInteger.TWO.pow(n))), xShifted);
assertEquals(x, xShifted.shiftRight(n));
}
/*
* 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 MutableBigIntegers, etc.
*
* If order is less than 2, order is changed to 2.
*/
private static MutableBigIntegerBox fetchNumber(int order) {
int numType = random.nextInt(8);
MutableBigIntegerBox result = null;
if (order < 2) order = 2;
int[] val;
switch (numType) {
case 0: // Empty
result = MutableBigIntegerBox.ZERO;
break;
case 1: // One
result = MutableBigIntegerBox.ONE;
break;
case 2: // All bits set in number
int numInts = (order + 31) >> 5;
int[] fullBits = new int[numInts];
Arrays.fill(fullBits, -1);
fullBits[0] &= -1 >>> -order;
result = new MutableBigIntegerBox(fullBits);
break;
case 3: // One bit in number
result = MutableBigIntegerBox.ONE.shiftLeft(random.nextInt(order));
break;
case 4: // Random bit density
val = new int[(order + 31) >> 5];
int iterations = random.nextInt(order);
for (int i = 0; i < iterations; i++) {
int bitIdx = random.nextInt(order);
val[bitIdx >> 5] |= 1 << bitIdx;
}
result = new MutableBigIntegerBox(val);
break;
case 5: // Runs of consecutive ones and zeros
result = ZERO;
int remaining = order;
int bit = random.nextInt(2);
while (remaining > 0) {
int runLength = Math.min(remaining, random.nextInt(order));
result = result.shiftLeft(runLength);
if (bit > 0)
result = result.add(ONE.shiftLeft(runLength).subtract(ONE));
remaining -= runLength;
bit = 1 - bit;
}
break;
case 6: // random bits with trailing space
int len = random.nextInt((order + 31) >> 5) + 1;
int offset = random.nextInt(len);
val = new int[len << 1];
for (int i = 0; i < val.length; i++)
val[i] = random.nextInt();
result = new MutableBigIntegerBox(val, offset, len);
break;
default: // random bits
result = new MutableBigIntegerBox(new BigInteger(order, random));
}
return result;
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2006, 2025, 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 6365176
* @summary Get NullPointerExceptions when expected
*/
import java.math.*;
import static java.math.BigInteger.*;
public class OperatorNpeTests {
public static void main(String... argv) {
BigInteger[] specialValues = {ZERO, ONE, TEN};
for (BigInteger bd : specialValues) {
BigInteger result;
try {
result = bd.multiply(null);
throw new RuntimeException("Instead of NPE got " + result);
} catch (NullPointerException npe) {
; // Expected
}
try {
result = bd.divide(null);
throw new RuntimeException("Instead of NPE got " + result);
} catch (NullPointerException npe) {
; // Expected
}
try {
result = bd.add(null);
throw new RuntimeException("Instead of NPE got " + result);
} catch (NullPointerException npe) {
; // Expected
}
try {
result = bd.subtract(null);
throw new RuntimeException("Instead of NPE got " + result);
} catch (NullPointerException npe) {
; // Expected
}
}
}
}

View file

@ -0,0 +1,252 @@
/*
* Copyright (c) 2014, 2022, 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
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @run main PrimeTest
* @bug 8026236 8074460 8078672 8294593
* @summary test primality verification methods in BigInteger (use -Dseed=X to set PRNG seed)
* @author bpb
* @key randomness
*/
import java.math.BigInteger;
import java.util.BitSet;
import java.util.List;
import java.util.NavigableSet;
import java.util.Set;
import java.util.SplittableRandom;
import java.util.TreeSet;
import jdk.test.lib.RandomFactory;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toList;
public class PrimeTest {
private static final int DEFAULT_UPPER_BOUND = 1299709; // 100000th prime
private static final int DEFAULT_CERTAINTY = 100;
private static final int NUM_NON_PRIMES = 10000;
/**
* Run the test.
*
* @param args The parameters.
* @throws Exception on failure
*/
public static void main(String[] args) throws Exception {
// Prepare arguments
int upperBound = args.length > 0 ? Integer.valueOf(args[0]) : DEFAULT_UPPER_BOUND;
int certainty = args.length > 1 ? Integer.valueOf(args[1]) : DEFAULT_CERTAINTY;
boolean parallel = args.length > 2 ? Boolean.valueOf(args[2]) : true;
// Echo parameter settings
System.out.println("Upper bound = " + upperBound
+ "\nCertainty = " + certainty
+ "\nParallel = " + parallel);
// Get primes through specified bound (inclusive) and Integer.MAX_VALUE
NavigableSet<BigInteger> primes = getPrimes(upperBound);
// Check whether known primes are identified as such
boolean primeTest = checkPrime(primes, certainty, parallel);
System.out.println("Prime test result: " + (primeTest ? "SUCCESS" : "FAILURE"));
if (!primeTest) {
System.err.println("Prime test failed");
}
// Check whether known non-primes are not identified as primes
boolean nonPrimeTest = checkNonPrime(primes, certainty);
System.out.println("Non-prime test result: " + (nonPrimeTest ? "SUCCESS" : "FAILURE"));
boolean mersennePrimeTest = checkMersennePrimes(certainty);
System.out.println("Mersenne test result: " + (mersennePrimeTest ? "SUCCESS" : "FAILURE"));
if (!primeTest || !nonPrimeTest || !mersennePrimeTest) {
throw new Exception("PrimeTest FAILED!");
}
if (!checkHugeFails()) {
throw new Exception("Primality test on huge integer should fail but succeeded");
}
System.out.println("PrimeTest succeeded!");
}
/**
* Create a {@code BitSet} wherein a set bit indicates the corresponding
* index plus 2 is prime. That is, if bit N is set, then the integer N + 2
* is prime. The values 0 and 1 are intentionally excluded. See the
* <a
* href="http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithm_description">
* Sieve of Eratosthenes</a> algorithm description for more information.
*
* @param upperBound The maximum prime to allow
* @return bits indicating which indexes represent primes
*/
private static BitSet createPrimes(int upperBound) {
int nbits = upperBound - 1;
BitSet bs = new BitSet(nbits);
for (int p = 2; p * p < upperBound;) {
for (int i = p * p; i < nbits + 2; i += p) {
bs.set(i - 2, true);
}
do {
++p;
} while (p > 1 && bs.get(p - 2));
}
bs.flip(0, nbits);
return bs;
}
/**
* Load the primes up to the specified bound (inclusive) into a
* {@code NavigableSet}, appending the prime {@code Integer.MAX_VALUE}.
*
* @param upperBound The maximum prime to allow
* @return a set of primes
*/
private static NavigableSet<BigInteger> getPrimes(int upperBound) {
BitSet bs = createPrimes(upperBound);
NavigableSet<BigInteger> primes = bs.stream()
.mapToObj(p -> BigInteger.valueOf(p + 2))
.collect(toCollection(TreeSet::new));
primes.add(BigInteger.valueOf(Integer.MAX_VALUE));
System.out.println(String.format("Created %d primes", primes.size()));
return primes;
}
/**
* Verifies whether the fraction of probable primes detected is at least 1 -
* 1/2^certainty.
*
* @return true if and only if the test succeeds
*/
private static boolean checkPrime(Set<BigInteger> primes,
int certainty,
boolean parallel) {
long probablePrimes = (parallel ? primes.parallelStream() : primes.stream())
.filter(bi -> bi.isProbablePrime(certainty))
.count();
// N = certainty / 2
// Success if p/t >= 1 - 1/4^N
// or (p/t)*4^N >= 4^N - 1
// or p*4^N >= t*(4^N - 1)
BigInteger p = BigInteger.valueOf(probablePrimes);
BigInteger t = BigInteger.valueOf(primes.size());
BigInteger fourToTheC = BigInteger.valueOf(4).pow(certainty / 2);
BigInteger fourToTheCMinusOne = fourToTheC.subtract(BigInteger.ONE);
BigInteger left = p.multiply(fourToTheC);
BigInteger right = t.multiply(fourToTheCMinusOne);
if (left.compareTo(right) < 0) {
System.err.println("Probable prime certainty test failed");
}
return left.compareTo(right) >= 0;
}
/**
* Verifies whether all {@code BigInteger}s in the tested range for which
* {@code isProbablePrime()} returns {@code false} are <i>not</i>
* prime numbers.
*
* @return true if and only if the test succeeds
*/
private static boolean checkNonPrime(NavigableSet<BigInteger> primes,
int certainty) {
int maxPrime = DEFAULT_UPPER_BOUND;
try {
maxPrime = primes.last().intValueExact();
} catch (ArithmeticException e) {
// ignore it
}
// Create a list of non-prime BigIntegers.
SplittableRandom splitRandom = RandomFactory.getSplittableRandom();
List<BigInteger> nonPrimeBigInts = (splitRandom)
.ints(NUM_NON_PRIMES, 2, maxPrime).mapToObj(BigInteger::valueOf)
.filter(b -> !b.isProbablePrime(certainty)).collect(toList());
// If there are any non-probable primes also in the primes list then fail.
boolean failed = nonPrimeBigInts.stream().anyMatch(primes::contains);
// In the event, print which purported non-primes were actually prime.
if (failed) {
for (BigInteger bigInt : nonPrimeBigInts) {
if (primes.contains(bigInt)) {
System.err.println("Prime value thought to be non-prime: " + bigInt);
}
}
}
return !failed;
}
/**
* Verifies whether a specified subset of Mersenne primes are correctly
* identified as being prime. See
* <a href="https://en.wikipedia.org/wiki/Mersenne_prime">Mersenne prime</a>
* for more information.
*
* @return true if and only if the test succeeds
*/
private static boolean checkMersennePrimes(int certainty) {
int[] MERSENNE_EXPONENTS = {
2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203,
2281, 3217, 4253, // uncomment remaining array elements to make this test run a long time
/* 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497,
86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269,
2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951,
30402457, 32582657, 37156667, 42643801, 43112609, 57885161 */
};
System.out.println("Checking first "+MERSENNE_EXPONENTS.length+" Mersenne primes");
boolean result = true;
for (int n : MERSENNE_EXPONENTS) {
BigInteger mp = BigInteger.ONE.shiftLeft(n).subtract(BigInteger.ONE);
if (!mp.isProbablePrime(certainty)) {
System.err.println("Mp with p = "+n+" not classified as prime");
result = false;
}
}
return result;
}
private static boolean checkHugeFails() {
try {
// huge odd integer
BigInteger a = BigInteger.ONE.shiftLeft(500_000_000 + 1)
.setBit(0);
a.isProbablePrime(1);
// not expected to reach here
return false;
} catch (ArithmeticException e) {
// this is the expected behavior
return true;
}
}
}

View file

@ -0,0 +1,109 @@
/*
* Copyright (c) 1998, 2018, 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.
*/
import static java.math.BigInteger.ONE;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/**
* @test
* @bug 7131192
* @summary This test ensures that BigInteger.floatValue() and
* BigInteger.doubleValue() behave correctly.
* @author Louis Wasserman
*/
public class PrimitiveConversionTests {
static final List<BigInteger> ALL_BIGINTEGER_CANDIDATES;
static {
List<BigInteger> samples = new ArrayList<>();
// Now add values near 2^N for lots of values of N.
for (int exponent : Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 31, 32, 33,
34, 62, 63, 64, 65, 71, 72, 73, 79, 80, 81, 255, 256, 257, 511,
512, 513, Double.MAX_EXPONENT - 1, Double.MAX_EXPONENT,
Double.MAX_EXPONENT + 1, 2000, 2001, 2002)) {
BigInteger x = ONE.shiftLeft(exponent);
for (BigInteger y : Arrays.asList(x, x.add(ONE), x.subtract(ONE))) {
samples.add(y);
samples.add(y.negate());
}
}
Random rng = new Random(1234567);
for (int i = 0; i < 2000; i++) {
samples.add(new BigInteger(rng.nextInt(2000), rng));
}
ALL_BIGINTEGER_CANDIDATES = Collections.unmodifiableList(samples);
}
public static int testDoubleValue() {
System.out.println("--- testDoubleValue ---");
int failures = 0;
for (BigInteger big : ALL_BIGINTEGER_CANDIDATES) {
double expected = Double.parseDouble(big.toString());
double actual = big.doubleValue();
// should be bitwise identical
if (Double.doubleToRawLongBits(expected) != Double
.doubleToRawLongBits(actual)) {
System.out.format("big: %s, expected: %f, actual: %f%n",
big, expected, actual);
failures++;
}
}
return failures;
}
public static int testFloatValue() {
System.out.println("--- testFloatValue ---");
int failures = 0;
for (BigInteger big : ALL_BIGINTEGER_CANDIDATES) {
float expected = Float.parseFloat(big.toString());
float actual = big.floatValue();
// should be bitwise identical
if (Float.floatToRawIntBits(expected) != Float
.floatToRawIntBits(actual)) {
System.out.format("big: %s, expected: %f, actual: %f%n",
big, expected, actual);
failures++;
}
}
return failures;
}
public static void main(String[] args) {
int failures = testDoubleValue();
failures += testFloatValue();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures
+ " failures while testing primitive conversions.");
}
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2002, 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 4654323
* @summary Tests functionality of isProbablePrime(Integer.MAX_VALUE)
*/
import java.math.*;
public class ProbablePrime {
public static void main(String [] argv) {
BigInteger num = new BigInteger("4");
int certainties[] = {-1, 0, 1, 2, 100, Integer.MAX_VALUE-1,
Integer.MAX_VALUE};
boolean expectations[] = {true, true, false, false, false,
false, false};
for(int i = 0; i < certainties.length; i++) {
boolean b;
if((b=num.isProbablePrime(certainties[i])) !=
expectations[i])
throw new RuntimeException("Unexpected answer " + b +
" for certainty " +
certainties[i]);
}
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2005, 2022, 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 8282252
* @summary Verify BigInteger objects are serialized properly.
*/
import java.math.*;
import java.io.*;
import java.util.Arrays;
import java.util.List;
public class SerializationTests {
public static void main(String... args) throws Exception {
checkBigIntegerSerialRoundTrip();
checkBigIntegerSubSerialRoundTrip();
}
private static void checkSerialForm(BigInteger bi) throws Exception {
checkSerialForm0(bi);
checkSerialForm0(bi.negate());
}
private static void checkSerialForm0(BigInteger bi) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try(ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(bi);
oos.flush();
}
ObjectInputStream ois = new
ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
BigInteger tmp = (BigInteger)ois.readObject();
if (!bi.equals(tmp) ||
bi.hashCode() != tmp.hashCode() ||
bi.getClass() != tmp.getClass() ||
// For extra measure, directly test equality of components
bi.signum() != tmp.signum() ||
!Arrays.equals(bi.toByteArray(), (tmp.toByteArray())) ) {
System.err.print(" original : " + bi);
System.err.println(" (hash: 0x" + Integer.toHexString(bi.hashCode()) + ")");
System.err.print("serialized : " + tmp);
System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")");
throw new RuntimeException("Bad serial roundtrip");
}
}
private static void checkBigIntegerSerialRoundTrip() throws Exception {
var values =
List.of(BigInteger.ZERO,
BigInteger.ONE,
BigInteger.TWO,
BigInteger.TEN,
BigInteger.valueOf(100),
BigInteger.valueOf(Integer.MAX_VALUE),
BigInteger.valueOf(Long.MAX_VALUE-1),
new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1
for(BigInteger value : values) {
checkSerialForm(value);
}
}
// Subclass with specialized toString output
private static class BigIntegerSub extends BigInteger {
public BigIntegerSub(BigInteger bi) {
super(bi.toByteArray());
}
@Override
public String toString() {
return Arrays.toString(toByteArray());
}
}
// Subclass defining a serialVersionUID
private static class BigIntegerSubSVUID extends BigInteger {
@java.io.Serial
private static long serialVesionUID = 0x0123_4567_89ab_cdefL;
public BigIntegerSubSVUID(BigInteger bi) {
super(bi.toByteArray());
}
@Override
public String toString() {
return Arrays.toString(toByteArray());
}
}
// Subclass defining writeReplace
private static class BigIntegerSubWR extends BigInteger {
public BigIntegerSubWR(BigInteger bi) {
super(bi.toByteArray());
}
// Just return this; could use a serial proxy instead
@java.io.Serial
private Object writeReplace() throws ObjectStreamException {
return this;
}
}
private static void checkBigIntegerSubSerialRoundTrip() throws Exception {
var values = List.of(BigInteger.ZERO,
BigInteger.ONE,
BigInteger.TEN,
new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1
for(var value : values) {
checkSerialForm(new BigIntegerSub(value));
checkSerialForm(new BigIntegerSubSVUID(value));
checkSerialForm(new BigIntegerSubWR(value));
}
}
}

View file

@ -0,0 +1,89 @@
/*
* Copyright (c) 2001, 2025, 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 4489146 5017980
* @summary tests String constructors of BigInteger
*/
import java.math.*;
public class StringConstructor {
public static void main(String [] argv) {
// Good strings
constructWithoutError("0", 0L);
constructWithoutError("000000000000000000", 0L);
constructWithoutError("1", 1L);
constructWithoutError("-1", -1L);
constructWithoutError("+1", +1L);
constructWithoutError( "123456789123456789", 123456789123456789L);
constructWithoutError("+123456789123456789", 123456789123456789L);
constructWithoutError("-123456789123456789", -123456789123456789L);
constructWithoutError(Integer.toString(Integer.MIN_VALUE),
(long)Integer.MIN_VALUE);
constructWithoutError(Integer.toString(Integer.MAX_VALUE),
(long)Integer.MAX_VALUE);
constructWithoutError(Long.toString(Long.MIN_VALUE),
Long.MIN_VALUE);
constructWithoutError(Long.toString(Long.MAX_VALUE),
Long.MAX_VALUE);
// Bad strings
constructWithError("");
constructWithError("-");
constructWithError("+");
constructWithError("--");
constructWithError("++");
constructWithError("-000-0");
constructWithError("+000+0");
constructWithError("+000-0");
constructWithError("--1234567890");
constructWithError("++1234567890");
constructWithError("-0-12345678");
constructWithError("+0+12345678");
constructWithError("--12345678-12345678-12345678");
constructWithError("++12345678+12345678+12345678");
constructWithError("12345-");
constructWithError("12345+");
}
// this method adapted from ../BigDecimal/StringConstructor.java
private static void constructWithError(String badString) {
try {
BigInteger bi = new BigInteger(badString);
throw new RuntimeException(badString + " accepted");
} catch(NumberFormatException e) {
}
}
private static void constructWithoutError(String goodString, long value) {
BigInteger bi = new BigInteger(goodString);
if(bi.longValue() != value) {
System.err.printf("From ``%s'' expected %d, got %s.\n", goodString, value, bi);
throw new RuntimeException();
}
}
}

View file

@ -0,0 +1,193 @@
/*
* Copyright (c) 2011, 2025, 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 6371401
* @summary Tests of fooValueExact methods
*/
import java.math.BigInteger;
public class TestValueExact {
public static void main(String... args) {
int errors = 0;
errors += testLongValueExact();
errors += testIntValueExact();
errors += testShortValueExact();
errors += testByteValueExact();
if (errors > 0)
throw new RuntimeException();
}
private static int testLongValueExact() {
int errors = 0;
BigInteger[] inRange = {
BigInteger.valueOf(Long.MIN_VALUE),
BigInteger.ZERO,
BigInteger.valueOf(Long.MAX_VALUE)
};
BigInteger[] outOfRange = {
BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE),
BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE)
};
for (BigInteger bi : inRange) {
if (bi.longValueExact() != bi.longValue()) {
System.err.println("Mismatching int conversion for " + bi);
errors++;
}
}
for (BigInteger bi : outOfRange) {
try {
long value = bi.longValueExact();
System.err.println("Failed to get expected exception on " +
bi + " got " + value);
errors++;
} catch(ArithmeticException ae) {
; // Expected
}
}
return errors;
}
private static int testIntValueExact() {
int errors = 0;
BigInteger[] inRange = {
BigInteger.valueOf(Integer.MIN_VALUE),
BigInteger.ZERO,
BigInteger.ONE,
BigInteger.TEN,
BigInteger.valueOf(Integer.MAX_VALUE)
};
BigInteger[] outOfRange = {
BigInteger.valueOf((long)Integer.MIN_VALUE - 1),
BigInteger.valueOf((long)Integer.MAX_VALUE + 1)
};
for (BigInteger bi : inRange) {
if (bi.intValueExact() != bi.intValue()) {
System.err.println("Mismatching int conversion for " + bi);
errors++;
}
}
for (BigInteger bi : outOfRange) {
try {
int value = bi.intValueExact();
System.err.println("Failed to get expected exception on " +
bi + " got " + value);
errors++;
} catch(ArithmeticException ae) {
; // Expected
}
}
return errors;
}
private static int testShortValueExact() {
int errors = 0;
BigInteger[] inRange = {
BigInteger.valueOf(Short.MIN_VALUE),
BigInteger.ZERO,
BigInteger.ONE,
BigInteger.TEN,
BigInteger.valueOf(Short.MAX_VALUE)
};
BigInteger[] outOfRange = {
BigInteger.valueOf((long)Integer.MIN_VALUE - 1),
BigInteger.valueOf((long)Integer.MIN_VALUE),
BigInteger.valueOf( (int)Short.MIN_VALUE - 1),
BigInteger.valueOf( (int)Short.MAX_VALUE + 1),
BigInteger.valueOf((long)Integer.MAX_VALUE),
BigInteger.valueOf((long)Integer.MAX_VALUE + 1)
};
for (BigInteger bi : inRange) {
if (bi.shortValueExact() != bi.shortValue()) {
System.err.println("Mismatching short conversion for " + bi);
errors++;
}
}
for (BigInteger bi : outOfRange) {
try {
int value = bi.shortValueExact();
System.err.println("Failed to get expected exception on " +
bi + " got " + value);
errors++;
} catch(ArithmeticException ae) {
; // Expected
}
}
return errors;
}
private static int testByteValueExact() {
int errors = 0;
BigInteger[] inRange = {
BigInteger.valueOf(Byte.MIN_VALUE),
BigInteger.valueOf(0),
BigInteger.ONE,
BigInteger.TEN,
BigInteger.valueOf(Byte.MAX_VALUE)
};
BigInteger[] outOfRange = {
BigInteger.valueOf((long)Integer.MIN_VALUE - 1),
BigInteger.valueOf((long)Integer.MIN_VALUE),
BigInteger.valueOf( (int)Short.MIN_VALUE - 1),
BigInteger.valueOf( (int)Short.MIN_VALUE),
BigInteger.valueOf( (int)Byte.MIN_VALUE - 1),
BigInteger.valueOf( (int)Byte.MAX_VALUE + 1),
BigInteger.valueOf( (int)Short.MAX_VALUE + 1),
BigInteger.valueOf( (int)Short.MAX_VALUE),
BigInteger.valueOf((long)Integer.MAX_VALUE),
BigInteger.valueOf((long)Integer.MAX_VALUE + 1)
};
for (BigInteger bi : inRange) {
if (bi.byteValueExact() != bi.byteValue()) {
System.err.println("Mismatching byte conversion for " + bi);
errors++;
}
}
for (BigInteger bi : outOfRange) {
try {
int value = bi.byteValueExact();
System.err.println("Failed to get expected exception on " +
bi + " got " + value);
errors++;
} catch(ArithmeticException ae) {
; // Expected
}
}
return errors;
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 1998, 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 4040456
* @summary Test biginteger constructor with i18n string
*/
import java.math.*;
/**
* This class tests to see if creating a biginteger with an
* unicode japanese zero and one succeeds
*
*/
public class UnicodeConstructor {
public static void main(String args[]) {
try {
// the code for japanese zero
BigInteger b1 = new BigInteger("\uff10");
System.err.println(b1.toString());
// Japanese 1010
BigInteger b2 = new BigInteger("\uff11\uff10\uff11\uff10");
System.err.println(b2.toString());
}
catch (ArrayIndexOutOfBoundsException e) {
throw new RuntimeException(
"BigInteger is not accepting unicode initializers.");
}
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2023, 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.
*/
package java.math;
public class Accessor {
public static int[] mag(BigInteger bi) {
return bi.mag;
}
}

View file

@ -0,0 +1,180 @@
/*
* Copyright (c) 2024, 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.
*/
package java.math;
import java.util.Arrays;
/**
* A class for tests.
*/
public class MutableBigIntegerBox {
/**
* Constant zero
*/
public static final MutableBigIntegerBox ZERO = new MutableBigIntegerBox(new MutableBigInteger());
/**
* Constant one
*/
public static final MutableBigIntegerBox ONE = new MutableBigIntegerBox(MutableBigInteger.ONE);
/**
* Constant two
*/
public static final MutableBigIntegerBox TWO = new MutableBigIntegerBox(new MutableBigInteger(2));
private MutableBigInteger val;
MutableBigIntegerBox(MutableBigInteger val) {
this.val = val;
}
/**
* Construct MutableBigIntegerBox from magnitude, starting from
* offset and with a length of intLen ints.
* The value is normalized.
* @param mag the magnitude
* @param offset the offset where the value starts
* @param intLen the length of the value, in int words.
*/
public MutableBigIntegerBox(int[] mag, int offset, int intLen) {
this(new MutableBigInteger(mag));
val.offset = offset;
val.intLen = intLen;
val.normalize();
}
/**
* Construct MutableBigIntegerBox from magnitude.
* The value is normalized.
* @param mag the magnitude
*/
public MutableBigIntegerBox(int[] mag) {
this(mag, 0, mag.length);
}
/**
* Construct MutableBigIntegerBox from BigInteger val
* @param val the value
*/
public MutableBigIntegerBox(BigInteger val) {
this(val.mag);
}
/**
* Returns the bit length of this MutableBigInteger value
* @return the bit length of this MutableBigInteger value
*/
public long bitLength() {
return val.bitLength();
}
/**
* Return {@code this << n}
* @return {@code this << n}
* @param n the shift
*/
public MutableBigIntegerBox shiftLeft(int n) {
MutableBigIntegerBox res = new MutableBigIntegerBox(val.value.clone(), val.offset, val.intLen);
res.val.safeLeftShift(n);
return res;
}
/**
* Return {@code this >> n}
* @return {@code this >> n}
* @param n the shift
*/
public MutableBigIntegerBox shiftRight(int n) {
MutableBigInteger res = new MutableBigInteger(val);
res.safeRightShift(n);
return new MutableBigIntegerBox(res);
}
/**
* Return this + addend
* @return this + addend
* @param addend the addend
*/
public MutableBigIntegerBox add(MutableBigIntegerBox addend) {
MutableBigInteger res = new MutableBigInteger(val);
res.add(addend.val);
return new MutableBigIntegerBox(res);
}
/**
* Return this - subtraend
* @return this - subtraend
* @param subtraend the subtraend
*/
public MutableBigIntegerBox subtract(MutableBigIntegerBox subtraend) {
MutableBigInteger res = new MutableBigInteger(val);
res.subtract(subtraend.val);
return new MutableBigIntegerBox(res);
}
/**
* Return this * multiplier
* @return this * multiplier
* @param multiplier the multiplier
*/
public MutableBigIntegerBox multiply(MutableBigIntegerBox multiplier) {
MutableBigInteger res = new MutableBigInteger();
if (!(val.isZero() || multiplier.val.isZero()))
val.multiply(multiplier.val, res);
return new MutableBigIntegerBox(res);
}
/**
* Compare the magnitude of two MutableBigIntegers. Returns -1, 0 or 1
* as this is numerically less than, equal to, or greater than {@code b}.
* @return -1, 0 or 1 as this is numerically less than, equal to, or
* greater than {@code b}.
* @param b the value to compare
*/
public int compare(MutableBigIntegerBox b) {
return val.compare(b.val);
}
/**
* Compares this MutableBigIntegerBox with the specified Object for equality.
*
* @param x Object to which this MutableBigIntegerBox is to be compared.
* @return {@code true} if and only if the specified Object is a
* MutableBigIntegerBox whose value is numerically equal to this MutableBigIntegerBox.
*/
@Override
public boolean equals(Object x) {
return (x instanceof MutableBigIntegerBox xInt)
&& Arrays.equals(val.value, val.offset, val.offset + val.intLen,
xInt.val.value, xInt.val.offset, xInt.val.offset + xInt.val.intLen);
}
@Override
public String toString() {
return val.toString();
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2011, 2019, 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 8022780
* @summary Test division of large values
* @requires (sun.arch.data.model == "64" & os.maxMemory > 8g)
* @run main/othervm -Xshare:off -Xmx8g DivisionOverflow
* @author Dmitry Nadezhin
*/
import java.math.BigInteger;
public class DivisionOverflow {
public static void main(String[] args) {
try {
BigInteger a = BigInteger.ONE.shiftLeft(2147483646);
BigInteger b = BigInteger.ONE.shiftLeft(1568);
BigInteger[] qr = a.divideAndRemainder(b);
BigInteger q = qr[0];
BigInteger r = qr[1];
if (!r.equals(BigInteger.ZERO)) {
throw new RuntimeException("Incorrect signum() of remainder " + r.signum());
}
if (q.bitLength() != 2147482079) {
throw new RuntimeException("Incorrect bitLength() of quotient " + q.bitLength());
}
System.out.println("Division of large values passed without overflow.");
} catch (OutOfMemoryError e) {
// possible
System.err.println("DivisionOverflow skipped: OutOfMemoryError");
System.err.println("Run jtreg with -javaoption:-Xmx8g");
}
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2013, 2019, 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 8021204
* @summary Test constructor BigInteger(String val, int radix) on very long string
* @requires (sun.arch.data.model == "64" & os.maxMemory > 8g)
* @run main/othervm -Xshare:off -Xmx8g StringConstructorOverflow
* @author Dmitry Nadezhin
*/
import java.math.BigInteger;
public class StringConstructorOverflow {
// String with hexadecimal value pow(2,pow(2,34))+1
private static String makeLongHexString() {
StringBuilder sb = new StringBuilder();
sb.append('1');
for (int i = 0; i < (1 << 30) - 1; i++) {
sb.append('0');
}
sb.append('1');
return sb.toString();
}
public static void main(String[] args) {
try {
BigInteger bi = new BigInteger(makeLongHexString(), 16);
if (bi.compareTo(BigInteger.ONE) <= 0) {
throw new RuntimeException("Incorrect result " + bi.toString());
}
} catch (ArithmeticException e) {
// expected
System.out.println("Overflow is reported by ArithmeticException, as expected");
} catch (OutOfMemoryError e) {
// possible
System.err.println("StringConstructorOverflow skipped: OutOfMemoryError");
System.err.println("Run jtreg with -javaoption:-Xmx8g");
}
}
}

View file

@ -0,0 +1,685 @@
/*
* Copyright (c) 2013, 2023, 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 6910473 8021204 8021203 9005933 8074460 8078672
* @summary Test range of BigInteger values (use -Dseed=X to set PRNG seed)
* @library /test/lib
* @requires (sun.arch.data.model == "64" & os.maxMemory >= 10g)
* @run main/timeout=180/othervm -Xmx8g -XX:+CompactStrings SymmetricRangeTests
* @author Dmitry Nadezhin
* @key randomness
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.math.BigInteger;
import java.util.Random;
import jdk.test.lib.RandomFactory;
public class SymmetricRangeTests {
private static final BigInteger MAX_VALUE = makeMaxValue();
private static final BigInteger MIN_VALUE = MAX_VALUE.negate();
private static final Random RANDOM = RandomFactory.getRandom();
private static BigInteger makeMaxValue() {
byte[] ba = new byte[1 << 28];
Arrays.fill(ba, (byte) 0xFF);
ba[0] = (byte) 0x7F;
return new BigInteger(ba);
}
private static void check(String msg, BigInteger actual, BigInteger expected) {
if (!actual.equals(expected)) {
throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
}
}
private static void check(String msg, double actual, double expected) {
if (actual != expected) {
throw new RuntimeException(msg + "=" + actual);
}
}
private static void check(String msg, float actual, float expected) {
if (actual != expected) {
throw new RuntimeException(msg + "=" + actual);
}
}
private static void check(String msg, long actual, long expected) {
if (actual != expected) {
throw new RuntimeException(msg + "=" + actual);
}
}
private static void check(String msg, int actual, int expected) {
if (actual != expected) {
throw new RuntimeException(msg + "=" + actual);
}
}
private static void testOverflowInMakePositive() {
System.out.println("Testing overflow in BigInteger.makePositive");
byte[] ba = new byte[Integer.MAX_VALUE - 2];
ba[0] = (byte) 0x80;
try {
BigInteger actual = new BigInteger(ba);
throw new RuntimeException("new BigInteger(ba).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testBug8021204() {
System.out.println("Testing Bug 8021204");
StringBuilder sb = new StringBuilder();
sb.append('1');
for (int i = 0; i < (1 << 30) - 1; i++) {
sb.append('0');
}
sb.append('1');
String s = sb.toString();
sb = null;
try {
BigInteger actual = new BigInteger(s, 16);
throw new RuntimeException("new BigInteger(\"1000...001\").bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testOverflowInBitSieve() {
System.out.println("Testing overflow in BitSieve.sieveSingle");
int bitLength = (5 << 27) - 1;
try {
BigInteger actual = new BigInteger(bitLength, 0, RANDOM);
throw new RuntimeException("new BigInteger(bitLength, 0, null).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
try {
BigInteger bi = BigInteger.ONE.shiftLeft(bitLength - 1).subtract(BigInteger.ONE);
BigInteger actual = bi.nextProbablePrime();
throw new RuntimeException("bi.nextActualPrime().bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testAdd() {
System.out.println("Testing BigInteger.add");
try {
BigInteger actual = MAX_VALUE.add(BigInteger.ONE);
throw new RuntimeException("BigInteger.MAX_VALUE.add(BigInteger.ONE).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testSubtract() {
System.out.println("Testing BigInteger.subtract");
try {
BigInteger actual = MIN_VALUE.subtract(BigInteger.ONE);
throw new RuntimeException("BigInteger.MIN_VALUE.subtract(BigInteger.ONE).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testMultiply() {
System.out.println("Testing BigInteger.multiply");
int py = 2000;
int px = Integer.MAX_VALUE - py;
BigInteger x = BigInteger.ONE.shiftLeft(px);
BigInteger y = BigInteger.ONE.shiftLeft(py);
try {
BigInteger actual = x.multiply(y);
throw new RuntimeException("(1 << " + px + " ) * (1 << " + py + ").bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testDivide() {
System.out.println("Testing BigInteger.divide");
check("BigInteger.MIN_VALUE.divide(BigInteger.valueOf(-1))",
MIN_VALUE.divide(BigInteger.valueOf(-1)), MAX_VALUE);
check("BigInteger.MIN_VALUE.divide(BigInteger.ONE)",
MIN_VALUE.divide(BigInteger.ONE), MIN_VALUE);
}
private static void testDivideAndRemainder(String msg, BigInteger dividend, BigInteger divisor,
BigInteger expectedQuotent, BigInteger expectedRemainder) {
BigInteger[] qr = dividend.divideAndRemainder(divisor);
check(msg + "[0]", qr[0], expectedQuotent);
check(msg + "[1]", qr[1], expectedRemainder);
}
private static void testDivideAndRemainder() {
System.out.println("Testing BigInteger.divideAndRemainder");
testDivideAndRemainder("BigInteger.MIN_VALUE.divideAndRemainder(BigInteger.valueOf(-1))",
MIN_VALUE, BigInteger.valueOf(-1),
MAX_VALUE,
BigInteger.ZERO);
}
private static void testBug9005933() {
System.out.println("Testing Bug 9005933");
int dividendPow = 2147483646;
int divisorPow = 1568;
BigInteger dividend = BigInteger.ONE.shiftLeft(dividendPow);
BigInteger divisor = BigInteger.ONE.shiftLeft(divisorPow);
testDivideAndRemainder("(1 << " + dividendPow + ").divideAndRemainder(1 << " + divisorPow + ")",
dividend, divisor,
BigInteger.ONE.shiftLeft(dividendPow - divisorPow),
BigInteger.ZERO);
}
private static void testRemainder() {
System.out.println("Testing BigInteger.remainder");
check("BigInteger.MIN_VALUE.remainder(BigInteger.valueOf(-1))",
MIN_VALUE.remainder(BigInteger.valueOf(-1)), BigInteger.ZERO);
}
private static void testPow() {
System.out.println("Testing BigInteger.pow");
check("BigInteger.MIN_VALUE.pow(1)",
MIN_VALUE.pow(1), MIN_VALUE);
try {
BigInteger actual = BigInteger.valueOf(4).pow(Integer.MAX_VALUE);
throw new RuntimeException("BigInteger.valueOf(4).pow(Integer.MAX_VALUE).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testGcd() {
System.out.println("Testing BigInteger.gcd");
check("BigInteger.MIN_VALUE.gcd(BigInteger.MIN_VALUE)",
MIN_VALUE.gcd(MIN_VALUE), MAX_VALUE);
check("BigInteger.MIN_VALUE.gcd(BigInteger.ZERO)",
MIN_VALUE.gcd(BigInteger.ZERO), MAX_VALUE);
check("BigInteger.ZERO.gcd(MIN_VALUE)",
BigInteger.ZERO.gcd(MIN_VALUE), MAX_VALUE);
}
private static void testAbs() {
System.out.println("Testing BigInteger.abs");
check("BigInteger.MIN_VALUE.abs()",
MIN_VALUE.abs(), MAX_VALUE);
check("BigInteger.MAX_VALUE.abs()",
MAX_VALUE.abs(), MAX_VALUE);
}
private static void testNegate() {
System.out.println("Testing BigInteger.negate");
check("BigInteger.MIN_VALUE.negate()",
MIN_VALUE.negate(), MAX_VALUE);
check("BigInteger.MAX_VALUE.negate()",
MAX_VALUE.negate(), MIN_VALUE);
}
private static void testMod() {
System.out.println("Testing BigInteger.mod");
check("BigInteger.MIN_VALUE.mod(BigInteger.MAX_VALUE)",
MIN_VALUE.mod(MAX_VALUE), BigInteger.ZERO);
check("BigInteger.MAX_VALUE.mod(BigInteger.MAX_VALUE)",
MIN_VALUE.mod(MAX_VALUE), BigInteger.ZERO);
}
private static void testModPow() {
System.out.println("Testing BigInteger.modPow");
BigInteger x = BigInteger.valueOf(3);
BigInteger m = BigInteger.valueOf(-4).subtract(MIN_VALUE);
check("BigInteger.valueOf(3).modPow(BigInteger.ONE, m)",
x.modPow(BigInteger.ONE, m), x);
}
// slow test
private static void testModInverse() {
System.out.println("Testing BigInteger.modInverse");
check("BigInteger.MIN_VALUE.modInverse(BigInteger.MAX_VALUE)",
MIN_VALUE.modInverse(MAX_VALUE), MAX_VALUE.subtract(BigInteger.ONE));
}
private static void testShiftLeft() {
System.out.println("Testing BigInteger.shiftLeft");
try {
BigInteger actual = MIN_VALUE.shiftLeft(1);
throw new RuntimeException("BigInteger.MIN_VALUE.shiftLeft(1).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
try {
BigInteger actual = MAX_VALUE.shiftLeft(1);
throw new RuntimeException("BigInteger.MAX_VALUE.shiftLeft(1).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testShiftRight() {
System.out.println("Testing BigInteger.shiftRight");
try {
BigInteger actual = MIN_VALUE.shiftRight(-1);
throw new RuntimeException("BigInteger.MIN_VALUE.shiftRight(-1).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
try {
BigInteger actual = MAX_VALUE.shiftRight(-1);
throw new RuntimeException("BigInteger.MAX_VALUE.shiftRight(-1).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testAnd() {
System.out.println("Testing BigInteger.and");
check("BigInteger.MIN_VALUE.and(BigInteger.MIN_VALUE)",
MIN_VALUE.and(MIN_VALUE), MIN_VALUE);
check("BigInteger.MAX_VALUE.and(BigInteger.MAX_VALUE)",
MAX_VALUE.and(MAX_VALUE), MAX_VALUE);
check("BigInteger.MIN_VALUE.and(BigInteger.MAX_VALUE)",
MIN_VALUE.and(MAX_VALUE), BigInteger.ONE);
try {
BigInteger actual = MIN_VALUE.and(BigInteger.valueOf(-2));
throw new RuntimeException("BigInteger.MIN_VALUE.and(-2)).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testOr() {
System.out.println("Testing BigInteger.or");
check("BigInteger.MIN_VALUE.or(BigInteger.MIN_VALUE)",
MIN_VALUE.or(MIN_VALUE), MIN_VALUE);
check("BigInteger.MAX_VALUE.or(BigInteger.MAX_VALUE)",
MAX_VALUE.or(MAX_VALUE), MAX_VALUE);
check("BigInteger.MIN_VALUE.and(BigInteger.MAX_VALUE)",
MIN_VALUE.or(MAX_VALUE), BigInteger.valueOf(-1));
}
private static void testXor() {
System.out.println("Testing BigInteger.xor");
check("BigInteger.MIN_VALUE.xor(BigInteger.MIN_VALUE)",
MIN_VALUE.xor(MIN_VALUE), BigInteger.ZERO);
check("BigInteger.MAX_VALUE.xor(BigInteger.MAX_VALUE)",
MAX_VALUE.xor(MAX_VALUE), BigInteger.ZERO);
check("BigInteger.MIN_VALUE.xor(BigInteger.MAX_VALUE)",
MIN_VALUE.xor(MAX_VALUE), BigInteger.valueOf(-2));
try {
BigInteger actual = MIN_VALUE.xor(BigInteger.ONE);
throw new RuntimeException("BigInteger.MIN_VALUE.xor(BigInteger.ONE)).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testNot() {
System.out.println("Testing BigInteger.not");
check("BigInteger.MIN_VALUE.not()",
MIN_VALUE.not(), MAX_VALUE.subtract(BigInteger.ONE));
try {
BigInteger actual = MAX_VALUE.not();
throw new RuntimeException("BigInteger.MAX_VALUE.not()).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testSetBit() {
System.out.println("Testing BigInteger.setBit");
check("BigInteger.MIN_VALUE.setBit(" + Integer.MAX_VALUE + ")",
MIN_VALUE.setBit(Integer.MAX_VALUE), MIN_VALUE);
try {
BigInteger actual = MAX_VALUE.setBit(Integer.MAX_VALUE);
throw new RuntimeException("BigInteger.MAX_VALUE.setBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testClearBit() {
System.out.println("Testing BigInteger.clearBit");
check("BigInteger.MAX_VALUE.clearBit(" + Integer.MAX_VALUE + ")",
MAX_VALUE.clearBit(Integer.MAX_VALUE), MAX_VALUE);
try {
BigInteger actual = MIN_VALUE.clearBit(Integer.MAX_VALUE);
throw new RuntimeException("BigInteger.MIN_VALUE.clearBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
try {
BigInteger actual = MIN_VALUE.clearBit(0);
throw new RuntimeException("BigInteger.MIN_VALUE.clearBit(0).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testFlipBit() {
System.out.println("Testing BigInteger.flipBit");
try {
BigInteger actual = MIN_VALUE.flipBit(Integer.MAX_VALUE);
throw new RuntimeException("BigInteger.MIN_VALUE.flipBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
try {
BigInteger actual = MIN_VALUE.flipBit(0);
throw new RuntimeException("BigInteger.MIN_VALUE.flipBit(0).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
try {
BigInteger actual = MAX_VALUE.flipBit(Integer.MAX_VALUE);
throw new RuntimeException("BigInteger.MAX_VALUE.flipBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testGetLowestSetBit() {
System.out.println("Testing BigInteger.getLowestSetBit");
check("BigInteger.MIN_VALUE.getLowestSetBit()",
MIN_VALUE.getLowestSetBit(), 0);
check("BigInteger.MAX_VALUE.getLowestSetBit()",
MAX_VALUE.getLowestSetBit(), 0);
}
private static void testBitLength() {
System.out.println("Testing BigInteger.bitLength");
check("BigInteger.MIN_NEXT.bitLength()",
MIN_VALUE.bitLength(), Integer.MAX_VALUE);
check("BigInteger.MAX_VALUE.bitLength()",
MAX_VALUE.bitLength(), Integer.MAX_VALUE);
}
private static void testBitCount() {
System.out.println("Testing BigInteger.bitCount");
check("BigInteger.MIN_VALUE.bitCount()",
MIN_VALUE.bitCount(), Integer.MAX_VALUE - 1);
check("BigInteger.MAX_VALUE.bitCount()",
MAX_VALUE.bitCount(), Integer.MAX_VALUE);
}
private static void testToString(String msg, int radix, BigInteger bi, int length, String startsWith, char c) {
String s = bi.toString(radix);
if (s.length() != length) {
throw new RuntimeException(msg + ".length=" + s.length());
}
if (!s.startsWith(startsWith)) {
throw new RuntimeException(msg + "[0]=" + s.substring(0, startsWith.length()));
}
for (int i = startsWith.length(); i < s.length(); i++) {
if (s.charAt(i) != c) {
throw new RuntimeException(msg + "[" + i + "]='" + s.charAt(i) + "'");
}
}
}
private static void testToString() {
System.out.println("Testing BigInteger.toString");
testToString("BigInteger.MIN_VALUE.toString(16)=", 16,
BigInteger.valueOf(-1).shiftLeft(Integer.MAX_VALUE - 1),
(1 << 29) + 1, "-4", '0');
}
private static void testToByteArrayWithConstructor(String msg, BigInteger bi, int length, byte msb, byte b, byte lsb) {
byte[] ba = bi.toByteArray();
if (ba.length != length) {
throw new RuntimeException(msg + ".length=" + ba.length);
}
if (ba[0] != msb) {
throw new RuntimeException(msg + "[0]=" + ba[0]);
}
for (int i = 1; i < ba.length - 1; i++) {
if (ba[i] != b) {
throw new RuntimeException(msg + "[" + i + "]=" + ba[i]);
}
}
if (ba[ba.length - 1] != lsb) {
throw new RuntimeException(msg + "[" + (ba.length - 1) + "]=" + ba[ba.length - 1]);
}
BigInteger actual = new BigInteger(ba);
if (!actual.equals(bi)) {
throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
}
}
private static void testToByteArrayWithConstructor() {
System.out.println("Testing BigInteger.toByteArray with constructor");
testToByteArrayWithConstructor("BigInteger.MIN_VALUE.toByteArray()",
MIN_VALUE, (1 << 28), (byte) 0x80, (byte) 0x00, (byte) 0x01);
testToByteArrayWithConstructor("BigInteger.MAX_VALUE.toByteArray()",
MAX_VALUE, (1 << 28), (byte) 0x7f, (byte) 0xff, (byte) 0xff);
byte[] ba = new byte[1 << 28];
ba[0] = (byte) 0x80;
try {
BigInteger actual = new BigInteger(-1, ba);
throw new RuntimeException("new BigInteger(-1, ba).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
try {
BigInteger actual = new BigInteger(1, ba);
throw new RuntimeException("new BigInteger(1, ba).bitLength()=" + actual.bitLength());
} catch (ArithmeticException e) {
// expected
}
}
private static void testIntValue() {
System.out.println("Testing BigInteger.intValue");
check("BigInteger.MIN_VALUE.intValue()",
MIN_VALUE.intValue(), 1);
check("BigInteger.MAX_VALUE.floatValue()",
MAX_VALUE.intValue(), -1);
}
private static void testLongValue() {
System.out.println("Testing BigInteger.longValue");
check("BigInteger.MIN_VALUE.longValue()",
MIN_VALUE.longValue(), 1L);
check("BigInteger.MAX_VALUE.longValue()",
MAX_VALUE.longValue(), -1L);
}
private static void testFloatValue() {
System.out.println("Testing BigInteger.floatValue, Bug 8021203");
check("BigInteger.MIN_VALUE_.floatValue()",
MIN_VALUE.floatValue(), Float.NEGATIVE_INFINITY);
check("BigInteger.MAX_VALUE.floatValue()",
MAX_VALUE.floatValue(), Float.POSITIVE_INFINITY);
}
private static void testDoubleValue() {
System.out.println("Testing BigInteger.doubleValue, Bug 8021203");
check("BigInteger.MIN_VALUE.doubleValue()",
MIN_VALUE.doubleValue(), Double.NEGATIVE_INFINITY);
check("BigInteger.MAX_VALUE.doubleValue()",
MAX_VALUE.doubleValue(), Double.POSITIVE_INFINITY);
}
private static void testSerialization(String msg, BigInteger bi) {
try {
ByteArrayOutputStream baOut = new ByteArrayOutputStream((1 << 28) + 1000);
ObjectOutputStream out = new ObjectOutputStream(baOut);
out.writeObject(bi);
out.close();
out = null;
byte[] ba = baOut.toByteArray();
baOut = null;
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(ba));
BigInteger actual = (BigInteger) in.readObject();
if (!actual.equals(bi)) {
throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
}
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(msg + " raised exception ", e);
}
}
private static void testSerialization() {
System.out.println("Testing BigInteger serialization");
testSerialization("BigInteger.MIN_VALUE.intValue()",
MIN_VALUE);
testSerialization("BigInteger.MAX_VALUE.floatValue()",
MAX_VALUE);
}
private static void testLongValueExact() {
System.out.println("Testing BigInteger.longValueExact");
try {
long actual = MIN_VALUE.longValueExact();
throw new RuntimeException("BigInteger.MIN_VALUE.longValueExact()= " + actual);
} catch (ArithmeticException e) {
// excpected
}
try {
long actual = MAX_VALUE.longValueExact();
throw new RuntimeException("BigInteger.MAX_VALUE.longValueExact()= " + actual);
} catch (ArithmeticException e) {
// excpected
}
}
private static void testIntValueExact() {
System.out.println("Testing BigInteger.intValueExact");
try {
long actual = MIN_VALUE.intValueExact();
throw new RuntimeException("BigInteger.MIN_VALUE.intValueExact()= " + actual);
} catch (ArithmeticException e) {
// excpected
}
try {
long actual = MAX_VALUE.intValueExact();
throw new RuntimeException("BigInteger.MAX_VALUE.intValueExact()= " + actual);
} catch (ArithmeticException e) {
// excpected
}
}
private static void testShortValueExact() {
System.out.println("Testing BigInteger.shortValueExact");
try {
long actual = MIN_VALUE.shortValueExact();
throw new RuntimeException("BigInteger.MIN_VALUE.shortValueExact()= " + actual);
} catch (ArithmeticException e) {
// excpected
}
try {
long actual = MAX_VALUE.shortValueExact();
throw new RuntimeException("BigInteger.MAX_VALUE.shortValueExact()= " + actual);
} catch (ArithmeticException e) {
// excpected
}
}
private static void testByteValueExact() {
System.out.println("Testing BigInteger.byteValueExact");
try {
long actual = MIN_VALUE.byteValueExact();
throw new RuntimeException("BigInteger.MIN_VALUE.byteValueExact()= " + actual);
} catch (ArithmeticException e) {
// excpected
}
try {
long actual = MAX_VALUE.byteValueExact();
throw new RuntimeException("BigInteger.MAX_VALUE.byteValueExact()= " + actual);
} catch (ArithmeticException e) {
// excpected
}
}
public static void main(String... args) {
// subset zero indicates to run all subsets
int subset = Integer.valueOf(System.getProperty("subset",
String.valueOf(1 + RANDOM.nextInt(4))));
if (subset < 0 || subset > 4) {
throw new RuntimeException("Unknown subset " + subset);
}
if (subset == 0)
System.out.println("Testing all subsets");
else
System.out.println("Testing subset " + subset);
if (subset == 0 || subset == 1) {
testOverflowInMakePositive();
testBug8021204();
testOverflowInBitSieve();
testAdd();
testSubtract();
}
if (subset == 0 || subset == 2) {
testMultiply();
testDivide();
testDivideAndRemainder();
testBug9005933();
}
if (subset == 0 || subset == 3) {
testRemainder();
testPow();
testGcd();
testAbs();
testNegate();
testMod();
testModPow();
// testModInverse();
testShiftLeft();
testShiftRight();
testAnd();
testOr();
testXor();
testNot();
testSetBit();
testClearBit();
testFlipBit();
testGetLowestSetBit();
testBitLength();
testBitCount();
}
if (subset == 0 || subset == 4) {
testToString();
testToByteArrayWithConstructor();
testIntValue();
testLongValue();
testFloatValue();
testDoubleValue();
testSerialization();
testLongValueExact();
testIntValueExact();
testShortValueExact();
testByteValueExact();
}
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2003, 2025, 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 4851776 4891522 4905335
* @summary Basic tests for the RoundingMode class.
*/
import java.math.RoundingMode;
import java.math.BigDecimal;
public class RoundingModeTests {
public static void main(String [] argv) {
// For each member of the family, make sure
// rm == valueOf(rm.toString())
for(RoundingMode rm: RoundingMode.values()) {
if (rm != RoundingMode.valueOf(rm.toString())) {
throw new RuntimeException("Bad roundtrip conversion of " +
rm.toString());
}
}
// Test that mapping of old integers to new values is correct
if (RoundingMode.valueOf(BigDecimal.ROUND_CEILING) !=
RoundingMode.CEILING) {
throw new RuntimeException("Bad mapping for ROUND_CEILING");
}
if (RoundingMode.valueOf(BigDecimal.ROUND_DOWN) !=
RoundingMode.DOWN) {
throw new RuntimeException("Bad mapping for ROUND_DOWN");
}
if (RoundingMode.valueOf(BigDecimal.ROUND_FLOOR) !=
RoundingMode.FLOOR) {
throw new RuntimeException("Bad mapping for ROUND_FLOOR");
}
if (RoundingMode.valueOf(BigDecimal.ROUND_HALF_DOWN) !=
RoundingMode.HALF_DOWN) {
throw new RuntimeException("Bad mapping for ROUND_HALF_DOWN");
}
if (RoundingMode.valueOf(BigDecimal.ROUND_HALF_EVEN) !=
RoundingMode.HALF_EVEN) {
throw new RuntimeException("Bad mapping for ROUND_HALF_EVEN");
}
if (RoundingMode.valueOf(BigDecimal.ROUND_HALF_UP) !=
RoundingMode.HALF_UP) {
throw new RuntimeException("Bad mapping for ROUND_HALF_UP");
}
if (RoundingMode.valueOf(BigDecimal.ROUND_UNNECESSARY) !=
RoundingMode.UNNECESSARY) {
throw new RuntimeException("Bad mapping for ROUND_UNNECESARY");
}
}
}