@@ -1886,32 +1886,21 @@ public static double fma(double a, double b, double c) {
18861886 */
18871887 @ IntrinsicCandidate
18881888 public static float fma (float a , float b , float c ) {
1889- /*
1890- * Since the double format has more than twice the precision
1891- * of the float format, the multiply of a * b is exact in
1892- * double. The add of c to the product then incurs one
1893- * rounding error. Since the double format moreover has more
1894- * than (2p + 2) precision bits compared to the p bits of the
1895- * float format, the two roundings of (a * b + c), first to
1896- * the double format and then secondarily to the float format,
1897- * are equivalent to rounding the intermediate result directly
1898- * to the float format.
1899- *
1900- * In terms of strictfp vs default-fp concerns related to
1901- * overflow and underflow, since
1902- *
1903- * (Float.MAX_VALUE * Float.MAX_VALUE) << Double.MAX_VALUE
1904- * (Float.MIN_VALUE * Float.MIN_VALUE) >> Double.MIN_VALUE
1905- *
1906- * neither the multiply nor add will overflow or underflow in
1907- * double. Therefore, it is not necessary for this method to
1908- * be declared strictfp to have reproducible
1909- * behavior. However, it is necessary to explicitly store down
1910- * to a float variable to avoid returning a value in the float
1911- * extended value set.
1912- */
1913- float result = (float )(((double ) a * (double ) b ) + (double ) c );
1914- return result ;
1889+ if (Float .isFinite (a ) && Float .isFinite (b ) && Float .isFinite (c )) {
1890+ if (a == 0.0 || b == 0.0 ) {
1891+ return a * b + c ; // Handled signed zero cases
1892+ } else {
1893+ return (new BigDecimal ((double )a * (double )b ) // Exact multiply
1894+ .add (new BigDecimal ((double )c ))) // Exact sum
1895+ .floatValue (); // One rounding
1896+ // to a float value
1897+ }
1898+ } else {
1899+ // At least one of a,b, and c is non-finite. The result
1900+ // will be non-finite as well and will be the same
1901+ // non-finite value under double as float arithmetic.
1902+ return (float )fma ((double )a , (double )b , (double )c );
1903+ }
19151904 }
19161905
19171906 /**
0 commit comments