Skip to content
Permalink
Browse files
8253409: Double-rounding possibility in float fma
Backport-of: e5304b3
  • Loading branch information
Ekaterina Vergizova committed Mar 19, 2021
1 parent ff29b0b commit 17c982e3c8e08c7bc0de44814513220d45ef8eb7
Showing 2 changed files with 21 additions and 28 deletions.
@@ -1768,32 +1768,21 @@ public static double fma(double a, double b, double c) {
*/
@HotSpotIntrinsicCandidate
public static float fma(float a, float b, float c) {
/*
* Since the double format has more than twice the precision
* of the float format, the multiply of a * b is exact in
* double. The add of c to the product then incurs one
* rounding error. Since the double format moreover has more
* than (2p + 2) precision bits compared to the p bits of the
* float format, the two roundings of (a * b + c), first to
* the double format and then secondarily to the float format,
* are equivalent to rounding the intermediate result directly
* to the float format.
*
* In terms of strictfp vs default-fp concerns related to
* overflow and underflow, since
*
* (Float.MAX_VALUE * Float.MAX_VALUE) << Double.MAX_VALUE
* (Float.MIN_VALUE * Float.MIN_VALUE) >> Double.MIN_VALUE
*
* neither the multiply nor add will overflow or underflow in
* double. Therefore, it is not necessary for this method to
* be declared strictfp to have reproducible
* behavior. However, it is necessary to explicitly store down
* to a float variable to avoid returning a value in the float
* extended value set.
*/
float result = (float)(((double) a * (double) b ) + (double) c);
return result;
if (Float.isFinite(a) && Float.isFinite(b) && Float.isFinite(c)) {
if (a == 0.0 || b == 0.0) {
return a * b + c; // Handled signed zero cases
} else {
return (new BigDecimal((double)a * (double)b) // Exact multiply
.add(new BigDecimal((double)c))) // Exact sum
.floatValue(); // One rounding
// to a float value
}
} else {
// At least one of a,b, and c is non-finite. The result
// will be non-finite as well and will be the same
// non-finite value under double as float arithmetic.
return (float)fma((double)a, (double)b, (double)c);
}
}

/**
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2021, 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
@@ -23,11 +23,12 @@

/*
* @test
* @bug 4851642
* @bug 4851642 8253409
* @summary Tests for Math.fusedMac and StrictMath.fusedMac.
* @build Tests
* @build FusedMultiplyAddTests
* @run main FusedMultiplyAddTests
* @run main/othervm -XX:-UseFMA FusedMultiplyAddTests
*/

/**
@@ -350,6 +351,9 @@ private static int testSimpleF() {

{1.0f+Math.ulp(1.0f), 1.0f+Math.ulp(1.0f), -1.0f-2.0f*Math.ulp(1.0f),
Math.ulp(1.0f)*Math.ulp(1.0f)},

// Double-rounding if done in double precision
{0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f}
};

for (float[] testCase: testCases)

1 comment on commit 17c982e

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 17c982e Mar 19, 2021

Choose a reason for hiding this comment

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

Please sign in to comment.