abfb900829
Reviewed-by: bpb
175 lines
7.6 KiB
Java
175 lines
7.6 KiB
Java
/*
|
|
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8301833 8302026 8301444 8302028 8302040 8302027 8304028
|
|
* @build Tests
|
|
* @build FdlibmTranslit
|
|
* @build ExhaustingTests
|
|
* @run main ExhaustingTests
|
|
* @summary Compare StrictMath.foo and FdlibmTranslit.foo for many inputs.
|
|
*/
|
|
|
|
/*
|
|
* Note on usage: for more exhaustive testing to help validate changes
|
|
* to StrictMath, the DEFAULT_SHIFT setting should be set to 0. This
|
|
* will test all float values against the unary methods. Running all
|
|
* the float values for a single method takes on the order of a minute
|
|
* or two. The default setting is a shift of 10, meaning every 1024th
|
|
* float value is tested and the overall test runs within the typical
|
|
* time expectations of a tier 1 test.
|
|
*/
|
|
|
|
import java.util.function.DoubleBinaryOperator;
|
|
import java.util.function.DoubleUnaryOperator;
|
|
|
|
public class ExhaustingTests {
|
|
public static void main(String... args) {
|
|
long failures = 0;
|
|
|
|
failures += testUnaryMethods();
|
|
failures += testBinaryMethods();
|
|
|
|
if (failures > 0) {
|
|
System.err.println("Comparing StrictMath and FdlibmTranslit"
|
|
+ " incurred " + failures + " failures.");
|
|
throw new RuntimeException();
|
|
}
|
|
}
|
|
|
|
private static final int DEFAULT_SHIFT = 10;
|
|
|
|
/**
|
|
* Test the unary (one-argument) StrictMath methods from FDLIBM.
|
|
*/
|
|
private static long testUnaryMethods() {
|
|
long failures = 0;
|
|
UnaryTestCase[] testCases = {
|
|
// Since sqrt is correctly rounded and thus for each input
|
|
// there is one well-defined correct result, additional
|
|
// comparison of the transliteration sqrt or StrictMath
|
|
// sqrt could be made against Math::sqrt.
|
|
new UnaryTestCase("sqrt", FdlibmTranslit::sqrt, StrictMath::sqrt, DEFAULT_SHIFT),
|
|
new UnaryTestCase("cbrt", FdlibmTranslit::cbrt, StrictMath::cbrt, DEFAULT_SHIFT),
|
|
|
|
new UnaryTestCase("log", FdlibmTranslit::log, StrictMath::log, DEFAULT_SHIFT),
|
|
new UnaryTestCase("log10", FdlibmTranslit::log10, StrictMath::log10, DEFAULT_SHIFT),
|
|
new UnaryTestCase("log1p", FdlibmTranslit::log1p, StrictMath::log1p, DEFAULT_SHIFT),
|
|
|
|
new UnaryTestCase("exp", FdlibmTranslit::exp, StrictMath::exp, DEFAULT_SHIFT),
|
|
new UnaryTestCase("expm1", FdlibmTranslit::expm1, StrictMath::expm1, DEFAULT_SHIFT),
|
|
|
|
new UnaryTestCase("sinh", FdlibmTranslit::sinh, StrictMath::sinh, DEFAULT_SHIFT),
|
|
new UnaryTestCase("cosh", FdlibmTranslit::cosh, StrictMath::cosh, DEFAULT_SHIFT),
|
|
new UnaryTestCase("tanh", FdlibmTranslit::tanh, StrictMath::tanh, DEFAULT_SHIFT),
|
|
|
|
new UnaryTestCase("sin", FdlibmTranslit::sin, StrictMath::sin, DEFAULT_SHIFT),
|
|
new UnaryTestCase("cos", FdlibmTranslit::cos, StrictMath::cos, DEFAULT_SHIFT),
|
|
new UnaryTestCase("tan", FdlibmTranslit::tan, StrictMath::tan, DEFAULT_SHIFT),
|
|
|
|
new UnaryTestCase("asin", FdlibmTranslit::asin, StrictMath::asin, DEFAULT_SHIFT),
|
|
new UnaryTestCase("acos", FdlibmTranslit::acos, StrictMath::acos, DEFAULT_SHIFT),
|
|
new UnaryTestCase("atan", FdlibmTranslit::atan, StrictMath::atan, DEFAULT_SHIFT),
|
|
};
|
|
|
|
for (var testCase : testCases) {
|
|
System.out.println("Testing " + testCase.name());
|
|
System.out.flush();
|
|
int i = Integer.MAX_VALUE; // overflow to Integer.MIN_VALUE at start of loop
|
|
int increment = 1 << testCase.shiftDistance;
|
|
do {
|
|
i += increment;
|
|
double input = (double)Float.intBitsToFloat(i);
|
|
failures += Tests.test(testCase.name(),
|
|
input,
|
|
testCase.strictMath,
|
|
testCase.translit.applyAsDouble(input));
|
|
} while (i != Integer.MAX_VALUE);
|
|
}
|
|
return failures;
|
|
}
|
|
|
|
private static record UnaryTestCase(String name,
|
|
DoubleUnaryOperator translit,
|
|
DoubleUnaryOperator strictMath,
|
|
int shiftDistance) {
|
|
UnaryTestCase {
|
|
if (shiftDistance < 0 || shiftDistance >= 31) {
|
|
throw new IllegalArgumentException("Shift out of range");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test the binary (two-argument) StrictMath methods from FDLIBM.
|
|
*/
|
|
private static long testBinaryMethods() {
|
|
long failures = 0;
|
|
// Note: pow does _not_ have a transliteration port.
|
|
|
|
// Shift of 16 for a binary method gives comparable running
|
|
// time to exhaustive testing of a unary method (testing every
|
|
// 2^16 floating point values over two arguments is 2^32
|
|
// probes).
|
|
BinaryTestCase[] testCases = {
|
|
new BinaryTestCase("hypot", FdlibmTranslit::hypot, StrictMath::hypot, 20, 20),
|
|
new BinaryTestCase("atan2", FdlibmTranslit::atan2, StrictMath::atan2, 20, 20),
|
|
new BinaryTestCase("IEEEremainder", FdlibmTranslit::IEEEremainder, StrictMath::IEEEremainder, 20, 20),
|
|
};
|
|
|
|
for (var testCase : testCases) {
|
|
System.out.println("Testing " + testCase.name());
|
|
System.out.flush();
|
|
|
|
int iIncrement = 1 << testCase.xShift;
|
|
int jIncrement = 1 << testCase.yShift;
|
|
|
|
for (long i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i += iIncrement) {
|
|
for (long j = Integer.MIN_VALUE; j <= Integer.MAX_VALUE; j += jIncrement) {
|
|
double input1 = (double)Float.intBitsToFloat((int)i);
|
|
double input2 = (double)Float.intBitsToFloat((int)j);
|
|
failures += Tests.test(testCase.name(),
|
|
input1, input2,
|
|
testCase.strictMath,
|
|
testCase.translit.applyAsDouble(input1, input2));
|
|
}
|
|
}
|
|
}
|
|
return failures;
|
|
}
|
|
|
|
private static record BinaryTestCase(String name,
|
|
DoubleBinaryOperator translit,
|
|
DoubleBinaryOperator strictMath,
|
|
int xShift,
|
|
int yShift) {
|
|
BinaryTestCase {
|
|
if (xShift < 0 || xShift >= 31 ||
|
|
yShift < 0 || yShift >= 31 ) {
|
|
throw new IllegalArgumentException("Shift out of range");
|
|
}
|
|
}
|
|
}
|
|
}
|