@@ -1830,32 +1830,21 @@ public static double fma(double a, double b, double c) {
1830
1830
*/
1831
1831
@ IntrinsicCandidate
1832
1832
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
+ }
1859
1848
}
1860
1849
1861
1850
/**
0 commit comments