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:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
327
test/jdk/java/math/BigDecimal/AddTests.java
Normal file
327
test/jdk/java/math/BigDecimal/AddTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
115
test/jdk/java/math/BigDecimal/CompareToTests.java
Normal file
115
test/jdk/java/math/BigDecimal/CompareToTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
82
test/jdk/java/math/BigDecimal/Constructor.java
Normal file
82
test/jdk/java/math/BigDecimal/Constructor.java
Normal 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
64
test/jdk/java/math/BigDecimal/ConstructorUnscaledValue.java
Normal file
64
test/jdk/java/math/BigDecimal/ConstructorUnscaledValue.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
5797
test/jdk/java/math/BigDecimal/DivideMcTests.java
Normal file
5797
test/jdk/java/math/BigDecimal/DivideMcTests.java
Normal file
File diff suppressed because it is too large
Load diff
426
test/jdk/java/math/BigDecimal/DivideTests.java
Normal file
426
test/jdk/java/math/BigDecimal/DivideTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
366
test/jdk/java/math/BigDecimal/DoubleFloatValueTests.java
Normal file
366
test/jdk/java/math/BigDecimal/DoubleFloatValueTests.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
91
test/jdk/java/math/BigDecimal/EqualsTests.java
Normal file
91
test/jdk/java/math/BigDecimal/EqualsTests.java
Normal 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;
|
||||
}
|
||||
}
|
||||
188
test/jdk/java/math/BigDecimal/FloatDoubleValueTests.java
Normal file
188
test/jdk/java/math/BigDecimal/FloatDoubleValueTests.java
Normal 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();
|
||||
}
|
||||
}
|
||||
120
test/jdk/java/math/BigDecimal/IntValueExactTests.java
Normal file
120
test/jdk/java/math/BigDecimal/IntValueExactTests.java
Normal 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;
|
||||
}
|
||||
}
|
||||
352
test/jdk/java/math/BigDecimal/IntegralDivisionTests.java
Normal file
352
test/jdk/java/math/BigDecimal/IntegralDivisionTests.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
241
test/jdk/java/math/BigDecimal/IntegralValueTests.java
Normal file
241
test/jdk/java/math/BigDecimal/IntegralValueTests.java
Normal 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();
|
||||
}
|
||||
}
|
||||
144
test/jdk/java/math/BigDecimal/LongValueExactTests.java
Normal file
144
test/jdk/java/math/BigDecimal/LongValueExactTests.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
106
test/jdk/java/math/BigDecimal/MovePointTests.java
Normal file
106
test/jdk/java/math/BigDecimal/MovePointTests.java
Normal 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 + ")");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
98
test/jdk/java/math/BigDecimal/MultiplyTests.java
Normal file
98
test/jdk/java/math/BigDecimal/MultiplyTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
110
test/jdk/java/math/BigDecimal/NegateTests.java
Normal file
110
test/jdk/java/math/BigDecimal/NegateTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
95
test/jdk/java/math/BigDecimal/PowTests.java
Normal file
95
test/jdk/java/math/BigDecimal/PowTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
93
test/jdk/java/math/BigDecimal/PrecisionTests.java
Normal file
93
test/jdk/java/math/BigDecimal/PrecisionTests.java
Normal 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;
|
||||
}
|
||||
}
|
||||
245
test/jdk/java/math/BigDecimal/RangeTests.java
Normal file
245
test/jdk/java/math/BigDecimal/RangeTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
58
test/jdk/java/math/BigDecimal/RoundingTests.java
Normal file
58
test/jdk/java/math/BigDecimal/RoundingTests.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
57
test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java
Normal file
57
test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java
Normal 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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
150
test/jdk/java/math/BigDecimal/SerializationTests.java
Normal file
150
test/jdk/java/math/BigDecimal/SerializationTests.java
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
834
test/jdk/java/math/BigDecimal/SquareRootTests.java
Normal file
834
test/jdk/java/math/BigDecimal/SquareRootTests.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
185
test/jdk/java/math/BigDecimal/StringConstructor.java
Normal file
185
test/jdk/java/math/BigDecimal/StringConstructor.java
Normal 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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
94
test/jdk/java/math/BigDecimal/StrippingZerosTest.java
Normal file
94
test/jdk/java/math/BigDecimal/StrippingZerosTest.java
Normal 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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
131
test/jdk/java/math/BigDecimal/ToPlainStringTests.java
Normal file
131
test/jdk/java/math/BigDecimal/ToPlainStringTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
74
test/jdk/java/math/BigDecimal/ValueOfDouble.java
Normal file
74
test/jdk/java/math/BigDecimal/ValueOfDouble.java
Normal 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));
|
||||
}
|
||||
}
|
||||
476
test/jdk/java/math/BigDecimal/ZeroScalingTests.java
Normal file
476
test/jdk/java/math/BigDecimal/ZeroScalingTests.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue