abfb900829
Reviewed-by: bpb
210 lines
6.1 KiB
Java
210 lines
6.1 KiB
Java
/*
|
|
* Copyright (c) 2004, 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 8304028
|
|
* @summary Tests for {Math, StrictMath}.IEEEremainder
|
|
*/
|
|
|
|
public class IeeeRemainderTests {
|
|
private IeeeRemainderTests(){}
|
|
|
|
public static void main(String... args) {
|
|
int failures = 0;
|
|
|
|
failures += testIeeeRemainderSpecials();
|
|
failures += testIeeeRemainderZeroResult();
|
|
failures += testIeeeRemainderOneResult();
|
|
failures += testIeeeRemainderRounding();
|
|
|
|
if (failures > 0) {
|
|
System.err.println("Testing IEEEremainder incurred "
|
|
+ failures + " failures.");
|
|
throw new RuntimeException();
|
|
}
|
|
}
|
|
|
|
private static final double NaNd = Double.NaN;
|
|
private static final double MIN_VALUE = Double.MIN_VALUE;
|
|
private static final double MIN_NORM = Double.MIN_NORMAL;
|
|
private static final double MAX_VALUE = Double.MAX_VALUE;
|
|
private static final double InfinityD = Double.POSITIVE_INFINITY;
|
|
|
|
/**
|
|
* Special cases from the spec interspersed with test cases.
|
|
*/
|
|
private static int testIeeeRemainderSpecials() {
|
|
int failures = 0;
|
|
|
|
/*
|
|
* If either argument is NaN, or the first argument is
|
|
* infinite, or the second argument is positive zero or
|
|
* negative zero, then the result is NaN.
|
|
*
|
|
*/
|
|
for(double nan : Tests.NaNs) {
|
|
failures += testIEEEremainderCase(nan, 1.0, NaNd);
|
|
failures += testIEEEremainderCase(1.0, nan, NaNd);
|
|
}
|
|
|
|
|
|
double [][] nanResultCases = {
|
|
{ InfinityD, InfinityD},
|
|
{-InfinityD, InfinityD},
|
|
|
|
{ InfinityD, 1.0},
|
|
{-InfinityD, 1.0},
|
|
|
|
{ InfinityD, NaNd},
|
|
{-InfinityD, NaNd},
|
|
|
|
{ InfinityD, 0.0},
|
|
{-InfinityD, 0.0},
|
|
{ InfinityD, -0.0},
|
|
{-InfinityD, -0.0},
|
|
};
|
|
|
|
for(double[] testCase : nanResultCases) {
|
|
failures += testIEEEremainderCase(testCase[0], testCase[1], NaNd);
|
|
}
|
|
|
|
/*
|
|
* If the first argument is finite and the second argument is
|
|
* infinite, then the result is the same as the first
|
|
* argument.
|
|
*
|
|
*/
|
|
double [] specialCases = {
|
|
+0.0,
|
|
+MIN_VALUE,
|
|
+MIN_NORM,
|
|
+MAX_VALUE,
|
|
|
|
-0.0,
|
|
-MIN_VALUE,
|
|
-MIN_NORM,
|
|
-MAX_VALUE,
|
|
};
|
|
|
|
double [] infinities = {
|
|
+InfinityD,
|
|
-InfinityD
|
|
};
|
|
|
|
for (double specialCase : specialCases) {
|
|
for (double infinity: infinities) {
|
|
failures += testIEEEremainderCase(specialCase, infinity, specialCase);
|
|
}
|
|
}
|
|
|
|
return failures;
|
|
}
|
|
|
|
private static int testIeeeRemainderZeroResult() {
|
|
int failures = 0;
|
|
|
|
double [] testCases = {
|
|
+MIN_VALUE,
|
|
+MIN_NORM,
|
|
+MAX_VALUE*0.5,
|
|
|
|
-MIN_VALUE,
|
|
-MIN_NORM,
|
|
-MAX_VALUE*0.5,
|
|
};
|
|
|
|
for (double testCase : testCases) {
|
|
/*
|
|
* "If the remainder is zero, its sign is the same as the sign of the first argument."
|
|
*/
|
|
failures += testIEEEremainderCase(testCase*2.0, +testCase, Math.copySign(0.0, testCase));
|
|
failures += testIEEEremainderCase(testCase*2.0, -testCase, Math.copySign(0.0, testCase));
|
|
}
|
|
|
|
return failures;
|
|
}
|
|
|
|
/*
|
|
* Construct test cases where the remainder is one.
|
|
*/
|
|
private static int testIeeeRemainderOneResult() {
|
|
int failures = 0;
|
|
|
|
double [][] testCases = {
|
|
{4.0, 3.0},
|
|
|
|
{10_001.0, 5000.0},
|
|
|
|
{15_001.0, 5000.0},
|
|
|
|
{10_000.0, 9999.0},
|
|
|
|
{0x1.0p52 + 1.0, 0x1.0p52},
|
|
|
|
{0x1.fffffffffffffp52, 0x1.ffffffffffffep52},
|
|
};
|
|
|
|
for (var testCase : testCases) {
|
|
failures += testIEEEremainderCase(testCase[0], testCase[1], 1.0);
|
|
}
|
|
|
|
return failures;
|
|
}
|
|
|
|
/*
|
|
* Test cases that differ in rounding between % and IEEEremainder.
|
|
*/
|
|
private static int testIeeeRemainderRounding() {
|
|
int failures = 0;
|
|
|
|
double [][] testCases = {
|
|
{3.0, 2.0, -1.0},
|
|
{3.0, -2.0, -1.0},
|
|
};
|
|
|
|
for (var testCase : testCases) {
|
|
failures += testIEEEremainderCase(testCase[0], testCase[1], testCase[2]);
|
|
}
|
|
|
|
return failures;
|
|
}
|
|
|
|
/*
|
|
* For exact cases, built-in % remainder and IEEE remainder should
|
|
* be the same since the rounding mode in the implicit divide
|
|
* doesn't come into play.
|
|
*/
|
|
private static double remainder(double a, double b) {
|
|
return a % b;
|
|
}
|
|
|
|
private static int testIEEEremainderCase(double input1, double input2, double expected) {
|
|
int failures = 0;
|
|
failures += Tests.test("StrictMath.IEEEremainder", input1, input2, StrictMath::IEEEremainder, expected);
|
|
failures += Tests.test("Math.IEEEremainder", input1, input2, Math::IEEEremainder, expected);
|
|
|
|
return failures;
|
|
}
|
|
}
|