JDK 9 RFR of JDK-4851642: Add fused mac to Java math library
Joseph D. Darcy
joe.darcy at oracle.com
Wed Apr 13 22:02:08 UTC 2016
Hi Brian and Dmitry,
On 4/13/2016 12:43 PM, Brian Burkhalter wrote:
> Joe / Dmitry,
>
> On Apr 12, 2016, at 5:21 PM, joe darcy <joe.darcy at oracle.com
> <mailto:joe.darcy at oracle.com>> wrote:
>
>> Please review the changes for
>>
>> JDK-4851642: Add fused mac to Java math library
>> http://cr.openjdk.java.net/~darcy/4851642.0/
>> <http://cr.openjdk.java.net/%7Edarcy/4851642.0/>
>>
>> Fused mac (multiply-accumulate) is a ternary floating-point operation
>> which accepts three inputs, a, b, c, and computes
>>
>> a * b + c
>>
>> with a single rounding error rather than the usual two rounding
>> errors (a first for the multiply, a second one for the add).
>
> A couple of points of curiosity. Firstly, is this not “fused
> multiply-add” rather than “fused multiply-accumulate?” Secondly, why
> the choice of name “fusedMac()” instead of the common “fma()” or the
> longer but perhaps clearer “fusedMultiplyAdd()?”
On naming, there are a few candidates. As background, I'll note that the
naming in java.lang.Math at times follows the C-style naming ("cos"
rather than "cosine"), but that methods we've added more recently
outside of the traditional C math.h have followed more Java-style
conventions. FWIW, C99 calls this "fma".
So, "fma()" is a possible choice, certainly concise, but I don't think
many people would find it very suggestive as to what it does, at least
not with the current familiarity with fused multiply-add.
In the IEEE 754 2008 standard, the operation is spelled out as
"fusedMultiplyAdd", but that is a bit long.
The "multiply accumulate" term is how I first heard of the operation and
there is some other usage of it
(https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation),
but "fused multiply add" is also an accurate description.
>
> A picayune javadoc point: in the unordered lists <ul></ul> should
> “</li>” be used to close the list items?
I don't think that is necessary. The javadoc does pass fine through
doclint without warnings.
>
> On Apr 13, 2016, at 5:41 AM, Dmitry Nadezhin
> <dmitry.nadezhin at gmail.com <mailto:dmitry.nadezhin at gmail.com>> wrote:
>
> I concur with Dmitry’s points. With respect to the second one,
>
>> 2) Lines Math:1508-1525 could be simpler:
>> ====
>> double result = a * b + c;
>> return Double.isNaN(result) && Double.isFinite(a) &&
>> Double.isFinite(b)
>> ? c : result;
>> ====
>
> not trusting this to my own visual inspection, I wrote nested loops to
> run a, b, and c over
>
> double[] values = new double[] {
> -0.0, 0.0, +0.0, -42.0, 42.0,
> -Double.MAX_VALUE, Double.MAX_VALUE,
> Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY
> };
>
> and there is no difference between the webrev and Dmitry’s suggestion
> above for the cases where
>
> !Double.isFinite(a) || !Double.isFinite(b) || !Double.isFinite(c) == true
>
As part of favoring "simplicity over speed," I intentionally wrote the
code in a way that tried to follow the structure of the specification in
a straightforward manner. For example, the spec says
"<li> If any argument is NaN, the result is NaN."
and there is code
1508 if (Double.isNaN(a) || Double.isNaN(b) ||
Double.isNaN(c)) {
1509 return Double.NaN;
and the spec says
1472 * <li> If one of the first two arguments is infinite and the
1473 * other is zero, the result is NaN.
and there is code
1511 if ((Double.isInfinite(a) && b == 0.0) ||
1512 (Double.isInfinite(b) && a == 0.0)) {
1513 return Double.NaN;
etc.
For this initial implementation, I think this kind of simplicity is
desirable. Longer term, I wouldn't be surprised if this implementation
was retired out to be a reference implementation for additional
regression tests.
Thanks,
-Joe
More information about the core-libs-dev
mailing list