@@ -1830,32 +1830,21 @@ public static double fma(double a, double b, double c) {
18301830 */
18311831 @ IntrinsicCandidate
18321832 public static float fma (float a , float b , float c ) {
1833- /*
1834- * Since the double format has more than twice the precision
1835- * of the float format, the multiply of a * b is exact in
1836- * double. The add of c to the product then incurs one
1837- * rounding error. Since the double format moreover has more
1838- * than (2p + 2) precision bits compared to the p bits of the
1839- * float format, the two roundings of (a * b + c), first to
1840- * the double format and then secondarily to the float format,
1841- * are equivalent to rounding the intermediate result directly
1842- * to the float format.
1843- *
1844- * In terms of strictfp vs default-fp concerns related to
1845- * overflow and underflow, since
1846- *
1847- * (Float.MAX_VALUE * Float.MAX_VALUE) << Double.MAX_VALUE
1848- * (Float.MIN_VALUE * Float.MIN_VALUE) >> Double.MIN_VALUE
1849- *
1850- * neither the multiply nor add will overflow or underflow in
1851- * double. Therefore, it is not necessary for this method to
1852- * be declared strictfp to have reproducible
1853- * behavior. However, it is necessary to explicitly store down
1854- * to a float variable to avoid returning a value in the float
1855- * extended value set.
1856- */
1857- float result = (float )(((double ) a * (double ) b ) + (double ) c );
1858- return result ;
1833+ if (Float .isFinite (a ) && Float .isFinite (b ) && Float .isFinite (c )) {
1834+ if (a == 0.0 || b == 0.0 ) {
1835+ return a * b + c ; // Handled signed zero cases
1836+ } else {
1837+ return (new BigDecimal ((double )a * (double )b ) // Exact multiply
1838+ .add (new BigDecimal ((double )c ))) // Exact sum
1839+ .floatValue (); // One rounding
1840+ // to a float value
1841+ }
1842+ } else {
1843+ // At least one of a,b, and c is non-finite. The result
1844+ // will be non-finite as well and will be the same
1845+ // non-finite value under double as float arithmetic.
1846+ return (float )fma ((double )a , (double )b , (double )c );
1847+ }
18591848 }
18601849
18611850 /**
0 commit comments