Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,19 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
SET_TRIGFUNC(dpow);

#undef SET_TRIGFUNC

#define SET_TRIGFUNC_OR_NULL(name) \
if (StubRoutines::name() != nullptr) { \
name = StubRoutines::name(); \
} else { \
name = nullptr; \
}

SET_TRIGFUNC_OR_NULL(dtanh);

#undef SET_TRIGFUNC_OR_NULL


}

static jboolean is_c1_supported(vmIntrinsics::ID id){
Expand Down
52 changes: 52 additions & 0 deletions test/jdk/java/lang/Math/HyperbolicTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
*/

import static java.lang.Double.longBitsToDouble;
import java.util.Random;

public class HyperbolicTests {
private HyperbolicTests(){}
Expand Down Expand Up @@ -972,6 +973,46 @@ static int testTanh() {
return failures;
}

/**
* Test accuracy of Math.tanh intrinsic using StrictMath.tanh as the reference.
* The specified accuracy is 2.5 ulps.
*
*/
static int testTanhIntrinsicWithReference() {
double b1 = 0.02;
double b2 = 5.1;
double b3 = 55 * Math.log(2)/2; // ~19.062
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably better to use StrictMath.log here or, better use, precompute the value as a constant and document its conceptual origin.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see the updated code which uses the precomputed value of b3.


int failures = 0;

failures += testTanhWithReferenceInRange(0.0, b3 + 2.0); // entire range
failures += testTanhWithReferenceInRange(b1 - 0.005, 0.01);
failures += testTanhWithReferenceInRange(b2 - 0.5, 1.0);
failures += testTanhWithReferenceInRange(b3 - 2.5, 5.0);

return failures;

}

static int testTanhWithReferenceInRange(double min, double range) {
int failures = 0;

double [] testCases = new double[500];

Random rand = new Random(0);
for (int i = 0; i < testCases.length; i++) {
testCases[i] = min + range * rand.nextDouble();
}

for(int i = 0; i < testCases.length; i++) {
double testCase = testCases[i];
failures += testTanhWithReferenceUlpDiff(testCase, StrictMath.tanh(testCase), 2.5);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The allowable worst-case error is 2.5 ulp, although at many arguments FDLIBM has a smaller error.

For a general Math vs StrictMath test with an allowable 2.5 ulp error, without knowing how accurate FDLIBM is for that function and argument, a large error of approx. 2X the nominal error should be allowed (in case FDLIBM errors in one direction and the Math method errors in the other direction).

If the test is going to use randomness, then its jtreg tags should include

@key randomness

and it is preferable to use jdk.test.lib.RandomFactory to get and Random object since that handles printing out a key so the random sequence can be replicated if the test fails.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the test is going to use randomness, then its jtreg tags should include

@key randomness

and it is preferable to use jdk.test.lib.RandomFactory to get and Random object since that handles printing out a key so the random sequence can be replicated if the test fails.

Please see the test updated to use @key randomness and jdk.test.lib.RandomFactory to get and Random object.

The allowable worst-case error is 2.5 ulp, although at many arguments FDLIBM has a smaller error.
For a general Math vs StrictMath test with an allowable 2.5 ulp error, without knowing how accurate FDLIBM is for that function and argument, a large error of approx. 2X the nominal error should be allowed (in case FDLIBM errors in one direction and the Math method errors in the other direction).

So far the tests haven't failed with error of 2.5ulp. Would it be better to make it 5ulp? Please let me know.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far, this will be the only intrinsic implementation of tanh. Therefore, at the moment it is just checking the consistency of the intrinsic implementation with StrictMath/FDLIBM tanh. If the intrinsic has a ~1 ulp accuracy, it would be expected to often be within 2.5 ulps of FDLIBM tanh. However, as written the regression test would not necessarily pass against any allowable Math.tanh implementation, which is the usual criteria for java.lang.Math tests that aren't otherwise constrained (such as by being limited to a given subset of platforms).

If there was a correctly rounded tanh to compare against, then this style of testing would be valid.

Are there any plan to intrinsify sinh or cosh?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of random we should generate offline additional correctly rounded fixed test points to cater to new algorithm using high precision arithmetic library and then simply extend the HyperbolicTests.java with these new fixed test points using existing ulp testing mechanism in the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Sandhya(@sviswa7) for the suggestion! Will update the existing HyperbolicTests.java with new fixed point tests with quad precision reference values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Joe (@jddarcy),

As suggested by Sandhya (@sviswa7), I added ~750 fixed point tests for tanh in TanhTests.java using the quad precision tanh implementation in libquadmath library from gcc.

Please let me know if this looks good.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vamsi-parasa In my thoughts the best way to do this is add the additional tests points to HyperbolicTests.java itself in the testcases array of testTanh() method. We should remove all the other changes from HyperbolicTests.java. Also no need for separate TanhTests.java file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Sandhya(@sviswa7), please see the updated code in HyperbolicTests.java which removes the previous random based tests with the new fixed point tests. Also removed the TanhTests.java.

}

return failures;
}


public static int testTanhCaseWithTolerance(double input,
double expected,
double tolerance) {
Expand All @@ -996,4 +1037,15 @@ public static int testTanhCaseWithUlpDiff(double input,
failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh", -input, StrictMath::tanh, -expected, ulps, 1.0);
return failures;
}

public static int testTanhWithReferenceUlpDiff(double input,
double expected,
double ulps) {
int failures = 0;

failures += Tests.testUlpDiffWithAbsBound("Math.tanh", input, Math::tanh, expected, ulps, 1.0);
failures += Tests.testUlpDiffWithAbsBound("Math.tanh", -input, Math::tanh, -expected, ulps, 1.0);

return failures;
}
}