aboutsummaryrefslogtreecommitdiff
path: root/math/math-narrow.h
diff options
context:
space:
mode:
Diffstat (limited to 'math/math-narrow.h')
-rw-r--r--math/math-narrow.h45
1 files changed, 28 insertions, 17 deletions
diff --git a/math/math-narrow.h b/math/math-narrow.h
index 93d1b4c52a..0194f8c97e 100644
--- a/math/math-narrow.h
+++ b/math/math-narrow.h
@@ -28,6 +28,7 @@
#include <math_private.h>
#include <fenv_private.h>
#include <math-narrow-alias.h>
+#include <stdbool.h>
/* Carry out a computation using round-to-odd. The computation is
EXPR; the union type in which to store the result is UNION and the
@@ -37,11 +38,15 @@
function rather than a C operator is used when argument and result
types are the same) and the libc_fe* macros to ensure that the
correct rounding mode is used, for platforms with multiple rounding
- modes where those macros set only the relevant mode. This macro
- does not work correctly if the sign of an exact zero result depends
- on the rounding mode, so that case must be checked for
- separately. */
-#define ROUND_TO_ODD(EXPR, UNION, SUFFIX, MANTISSA) \
+ modes where those macros set only the relevant mode.
+ CLEAR_UNDERFLOW indicates whether underflow exceptions must be
+ cleared (in the case where a round-toward-zero underflow might not
+ indicate an underflow after narrowing, when that narrowing only
+ reduces precision not exponent range and the architecture uses
+ before-rounding tininess detection). This macro does not work
+ correctly if the sign of an exact zero result depends on the
+ rounding mode, so that case must be checked for separately. */
+#define ROUND_TO_ODD(EXPR, UNION, SUFFIX, MANTISSA, CLEAR_UNDERFLOW) \
({ \
fenv_t env; \
UNION u; \
@@ -49,6 +54,8 @@
libc_feholdexcept_setround ## SUFFIX (&env, FE_TOWARDZERO); \
u.d = (EXPR); \
math_force_eval (u.d); \
+ if (CLEAR_UNDERFLOW) \
+ feclearexcept (FE_UNDERFLOW); \
u.ieee.MANTISSA \
|= libc_feupdateenv_test ## SUFFIX (&env, FE_INEXACT) != 0; \
\
@@ -91,7 +98,7 @@
ret = (TYPE) ((X) + (Y)); \
else \
ret = (TYPE) ROUND_TO_ODD (math_opt_barrier (X) + (Y), \
- UNION, SUFFIX, MANTISSA); \
+ UNION, SUFFIX, MANTISSA, false); \
\
CHECK_NARROW_ADD (ret, (X), (Y)); \
return ret; \
@@ -149,7 +156,7 @@
ret = (TYPE) ((X) - (Y)); \
else \
ret = (TYPE) ROUND_TO_ODD (math_opt_barrier (X) - (Y), \
- UNION, SUFFIX, MANTISSA); \
+ UNION, SUFFIX, MANTISSA, false); \
\
CHECK_NARROW_SUB (ret, (X), (Y)); \
return ret; \
@@ -194,15 +201,17 @@
while (0)
/* Implement narrowing multiply using round-to-odd. The arguments are
- X and Y, the return type is TYPE and UNION, MANTISSA and SUFFIX are
- as for ROUND_TO_ODD. */
-#define NARROW_MUL_ROUND_TO_ODD(X, Y, TYPE, UNION, SUFFIX, MANTISSA) \
+ X and Y, the return type is TYPE and UNION, MANTISSA, SUFFIX and
+ CLEAR_UNDERFLOW are as for ROUND_TO_ODD. */
+#define NARROW_MUL_ROUND_TO_ODD(X, Y, TYPE, UNION, SUFFIX, MANTISSA, \
+ CLEAR_UNDERFLOW) \
do \
{ \
TYPE ret; \
\
ret = (TYPE) ROUND_TO_ODD (math_opt_barrier (X) * (Y), \
- UNION, SUFFIX, MANTISSA); \
+ UNION, SUFFIX, MANTISSA, \
+ CLEAR_UNDERFLOW); \
\
CHECK_NARROW_MUL (ret, (X), (Y)); \
return ret; \
@@ -246,16 +255,18 @@
} \
while (0)
-/* Implement narrowing divide using round-to-odd. The arguments are
- X and Y, the return type is TYPE and UNION, MANTISSA and SUFFIX are
- as for ROUND_TO_ODD. */
-#define NARROW_DIV_ROUND_TO_ODD(X, Y, TYPE, UNION, SUFFIX, MANTISSA) \
+/* Implement narrowing divide using round-to-odd. The arguments are X
+ and Y, the return type is TYPE and UNION, MANTISSA, SUFFIX and
+ CLEAR_UNDERFLOW are as for ROUND_TO_ODD. */
+#define NARROW_DIV_ROUND_TO_ODD(X, Y, TYPE, UNION, SUFFIX, MANTISSA, \
+ CLEAR_UNDERFLOW) \
do \
{ \
TYPE ret; \
\
ret = (TYPE) ROUND_TO_ODD (math_opt_barrier (X) / (Y), \
- UNION, SUFFIX, MANTISSA); \
+ UNION, SUFFIX, MANTISSA, \
+ CLEAR_UNDERFLOW); \
\
CHECK_NARROW_DIV (ret, (X), (Y)); \
return ret; \
@@ -308,7 +319,7 @@
TYPE ret; \
\
ret = (TYPE) ROUND_TO_ODD (sqrt ## SUFFIX (math_opt_barrier (X)), \
- UNION, SUFFIX, MANTISSA); \
+ UNION, SUFFIX, MANTISSA, false); \
\
CHECK_NARROW_SQRT (ret, (X)); \
return ret; \