mirror of
https://github.com/fluencelabs/musl
synced 2025-06-27 21:52:02 +00:00
make fma and lrint functions build without full fenv support
this is necessary to support archs where fenv is incomplete or unavailable (presently arm). fma, fmal, and the lrint family should work perfectly fine with this change; fmaf is slightly broken with respect to rounding as it depends on non-default rounding modes to do its work.
This commit is contained in:
@ -199,27 +199,37 @@ double fma(double x, double y, double z)
|
|||||||
* modes other than FE_TONEAREST are painful.
|
* modes other than FE_TONEAREST are painful.
|
||||||
*/
|
*/
|
||||||
if (spread < -DBL_MANT_DIG) {
|
if (spread < -DBL_MANT_DIG) {
|
||||||
|
#ifdef FE_INEXACT
|
||||||
feraiseexcept(FE_INEXACT);
|
feraiseexcept(FE_INEXACT);
|
||||||
|
#endif
|
||||||
|
#ifdef FE_UNDERFLOW
|
||||||
if (!isnormal(z))
|
if (!isnormal(z))
|
||||||
feraiseexcept(FE_UNDERFLOW);
|
feraiseexcept(FE_UNDERFLOW);
|
||||||
|
#endif
|
||||||
switch (oround) {
|
switch (oround) {
|
||||||
case FE_TONEAREST:
|
default: /* FE_TONEAREST */
|
||||||
return (z);
|
return (z);
|
||||||
|
#ifdef FE_TOWARDZERO
|
||||||
case FE_TOWARDZERO:
|
case FE_TOWARDZERO:
|
||||||
if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
|
if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
|
||||||
return (z);
|
return (z);
|
||||||
else
|
else
|
||||||
return (nextafter(z, 0));
|
return (nextafter(z, 0));
|
||||||
|
#endif
|
||||||
|
#ifdef FE_DOWNWARD
|
||||||
case FE_DOWNWARD:
|
case FE_DOWNWARD:
|
||||||
if (x > 0.0 ^ y < 0.0)
|
if (x > 0.0 ^ y < 0.0)
|
||||||
return (z);
|
return (z);
|
||||||
else
|
else
|
||||||
return (nextafter(z, -INFINITY));
|
return (nextafter(z, -INFINITY));
|
||||||
default: /* FE_UPWARD */
|
#endif
|
||||||
|
#ifdef FE_UPWARD
|
||||||
|
case FE_UPWARD:
|
||||||
if (x > 0.0 ^ y < 0.0)
|
if (x > 0.0 ^ y < 0.0)
|
||||||
return (nextafter(z, INFINITY));
|
return (nextafter(z, INFINITY));
|
||||||
else
|
else
|
||||||
return (z);
|
return (z);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (spread <= DBL_MANT_DIG * 2)
|
if (spread <= DBL_MANT_DIG * 2)
|
||||||
|
@ -54,7 +54,9 @@ float fmaf(float x, float y, float z)
|
|||||||
* If result is inexact, and exactly halfway between two float values,
|
* If result is inexact, and exactly halfway between two float values,
|
||||||
* we need to adjust the low-order bit in the direction of the error.
|
* we need to adjust the low-order bit in the direction of the error.
|
||||||
*/
|
*/
|
||||||
|
#ifdef FE_TOWARDZERO
|
||||||
fesetround(FE_TOWARDZERO);
|
fesetround(FE_TOWARDZERO);
|
||||||
|
#endif
|
||||||
volatile double vxy = xy; /* XXX work around gcc CSE bug */
|
volatile double vxy = xy; /* XXX work around gcc CSE bug */
|
||||||
double adjusted_result = vxy + z;
|
double adjusted_result = vxy + z;
|
||||||
fesetround(FE_TONEAREST);
|
fesetround(FE_TONEAREST);
|
||||||
|
@ -194,27 +194,37 @@ long double fmal(long double x, long double y, long double z)
|
|||||||
* modes other than FE_TONEAREST are painful.
|
* modes other than FE_TONEAREST are painful.
|
||||||
*/
|
*/
|
||||||
if (spread < -LDBL_MANT_DIG) {
|
if (spread < -LDBL_MANT_DIG) {
|
||||||
|
#ifdef FE_INEXACT
|
||||||
feraiseexcept(FE_INEXACT);
|
feraiseexcept(FE_INEXACT);
|
||||||
|
#endif
|
||||||
|
#ifdef FE_UNDERFLOW
|
||||||
if (!isnormal(z))
|
if (!isnormal(z))
|
||||||
feraiseexcept(FE_UNDERFLOW);
|
feraiseexcept(FE_UNDERFLOW);
|
||||||
|
#endif
|
||||||
switch (oround) {
|
switch (oround) {
|
||||||
case FE_TONEAREST:
|
default: /* FE_TONEAREST */
|
||||||
return (z);
|
return (z);
|
||||||
|
#ifdef FE_TOWARDZERO
|
||||||
case FE_TOWARDZERO:
|
case FE_TOWARDZERO:
|
||||||
if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
|
if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
|
||||||
return (z);
|
return (z);
|
||||||
else
|
else
|
||||||
return (nextafterl(z, 0));
|
return (nextafterl(z, 0));
|
||||||
|
#endif
|
||||||
|
#ifdef FE_DOWNWARD
|
||||||
case FE_DOWNWARD:
|
case FE_DOWNWARD:
|
||||||
if (x > 0.0 ^ y < 0.0)
|
if (x > 0.0 ^ y < 0.0)
|
||||||
return (z);
|
return (z);
|
||||||
else
|
else
|
||||||
return (nextafterl(z, -INFINITY));
|
return (nextafterl(z, -INFINITY));
|
||||||
default: /* FE_UPWARD */
|
#endif
|
||||||
|
#ifdef FE_UPWARD
|
||||||
|
case FE_UPWARD:
|
||||||
if (x > 0.0 ^ y < 0.0)
|
if (x > 0.0 ^ y < 0.0)
|
||||||
return (nextafterl(z, INFINITY));
|
return (nextafterl(z, INFINITY));
|
||||||
else
|
else
|
||||||
return (z);
|
return (z);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (spread <= LDBL_MANT_DIG * 2)
|
if (spread <= LDBL_MANT_DIG * 2)
|
||||||
|
@ -49,8 +49,10 @@ dtype fn(type x)
|
|||||||
|
|
||||||
feholdexcept(&env);
|
feholdexcept(&env);
|
||||||
d = (dtype)roundit(x);
|
d = (dtype)roundit(x);
|
||||||
|
#if defined(FE_INVALID) && defined(FE_INEXACT)
|
||||||
if (fetestexcept(FE_INVALID))
|
if (fetestexcept(FE_INVALID))
|
||||||
feclearexcept(FE_INEXACT);
|
feclearexcept(FE_INEXACT);
|
||||||
|
#endif
|
||||||
feupdateenv(&env);
|
feupdateenv(&env);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user