1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-16 10:20:30 +00:00

- If z is 0, one of x or y is 0, and the other is infinite, raise

an invalid exception and return an NaN.
- If a long double has 113 bits of precision, implement fma in terms
  of simple long double arithmetic instead of complicated double arithmetic.
- If a long double is the same as a double, alias fma as fmal.
This commit is contained in:
David Schultz 2005-03-07 05:02:09 +00:00
parent b3bc33db36
commit c8642491d5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=143230

View File

@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
* XXX On machines supporting quad precision, we should use that, but * XXX On machines supporting quad precision, we should use that, but
* see the caveat in s_fmaf.c. * see the caveat in s_fmaf.c.
*/ */
#if LDBL_MANT_DIG != 113
double double
fma(double x, double y, double z) fma(double x, double y, double z)
{ {
@ -66,10 +67,10 @@ fma(double x, double y, double z)
int ex, ey, ez; int ex, ey, ez;
int spread; int spread;
if (x == 0.0 || y == 0.0)
return (z);
if (z == 0.0) if (z == 0.0)
return (x * y); return (x * y);
if (x == 0.0 || y == 0.0)
return (x * y + z);
/* Results of frexp() are undefined for these cases. */ /* Results of frexp() are undefined for these cases. */
if (!isfinite(x) || !isfinite(y) || !isfinite(z)) if (!isfinite(x) || !isfinite(y) || !isfinite(z))
@ -176,3 +177,18 @@ fma(double x, double y, double z)
fesetround(oround); fesetround(oround);
return (ldexp(r + rr, ex + ey)); return (ldexp(r + rr, ex + ey));
} }
#else /* LDBL_MANT_DIG == 113 */
/*
* 113 bits of precision is more than twice the precision of a double,
* so it is enough to represent the intermediate product exactly.
*/
double
fma(double x, double y, double z)
{
return ((long double)x * y + z);
}
#endif /* LDBL_MANT_DIG != 113 */
#if (LDBL_MANT_DIG == 53)
__strong_reference(fma, fmal);
#endif