Is there still a difference between Math and StrictMath after Java 17 and JEP 306?

237 Views Asked by At

JEP 306, implemented in Java 17, provides always-strict floating point semantics, deprecating the strictfp flag. Does this mean that java.lang.Math can be counted on to behave exactly the same as the analogous methods in StrictMath (i.e., that java.lang.Math methods can no longer be replaced by the JVM with intrinsics as used to be allowed)? Does it also mean that there should no longer be any differences in floating point math results among different architectures, no matter which library is used?

I'm curious if I'm misunderstanding the new Java 17 feature, since we do see differences in today's code between Apple Silicon vs Intel.

1

There are 1 best solutions below

3
Sergey Tsypanov On

First of all, strictfp is not a flag, this is a Java keyword ensuring the same calculation results on every platform while doing operations over floating-point variables (float and double).

As of your question, there are two major PRs in OpenJDK involving the changes for JEP 306

If you look into the first one, especially into StrictMath you'll see that it now delegates directly to j.l.Math and the comment about strictfp semantics is now removed (along with strictfp keyword in OpenJDK codebase). Moreover, starting from Java 17 javac issues an explicit warning for strictfp keyword (see compiler.properties:

as of release 17, all floating-point expressions are evaluated strictly and strictfp is not required

So for the question

Does this mean that java.lang.Math can be counted on to behave exactly the same as the analogous methods in StrictMath

The answer is "yes", for some methods e.g. Math.sinh(double) delegate to StrictMath.sinh(double) (and later on to FdLibm.Sinh.compute(dobule)) and e.g. method StrictMath.toRadians(double) delegates to Math.toRadians(double). Eventually for floating-point variables it does not matter whether you call a method of Math or StrictMath, the same code is executed under the hood.

As of this part of the same question:

i.e., that java.lang.Math methods can no longer be replaced by the JVM with intrinsics as used to be allowed

The PRs does not impose any changes regarding intrinsics which are platform-specific and applied by JVM at runtime regardless of whether operation is strict or not. Moreover, as @Holger pointed out, there is no contradiction between strictness and intrinsics.

Does it also mean that there should no longer be any differences in floating point math results among different architectures, no matter which library is used?

The answer is "yes as of Java 17 or newer". Prior to it there could be difference in results, see https://stackoverflow.com/a/22335100/12473843. Before Java 17 if an operation over floating-point variable was not strict the standard assumed that

a calculation might produce "the correct answer" in situations where exclusive use of the float value set or double value set might result in overflow or underflow. But as soon as for now the semantics is always strict you get the same result on all platforms.

See also 8268224: Cleanup references to "strictfp" in core lib comments

P.S.

we do see differences in today's code between Apple Silicon vs Intel

I think it's quite natural for compiler to produce different code for different platforms, the question here is whether you see different results of computations on mentioned platforms.