diff options
Diffstat (limited to 'math/math-narrow.h')
-rw-r--r-- | math/math-narrow.h | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/math/math-narrow.h b/math/math-narrow.h index 1a3a5c57d7..03397a6d28 100644 --- a/math/math-narrow.h +++ b/math/math-narrow.h @@ -49,6 +49,64 @@ u.d; \ }) +/* Check for error conditions from a narrowing add function returning + RET with arguments X and Y and set errno as needed. Overflow and + underflow can occur for finite arguments and a domain error for + infinite ones. */ +#define CHECK_NARROW_ADD(RET, X, Y) \ + do \ + { \ + if (!isfinite (RET)) \ + { \ + if (isnan (RET)) \ + { \ + if (!isnan (X) && !isnan (Y)) \ + __set_errno (EDOM); \ + } \ + else if (isfinite (X) && isfinite (Y)) \ + __set_errno (ERANGE); \ + } \ + else if ((RET) == 0 && (X) != -(Y)) \ + __set_errno (ERANGE); \ + } \ + while (0) + +/* Implement narrowing add 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_ADD_ROUND_TO_ODD(X, Y, TYPE, UNION, SUFFIX, MANTISSA) \ + do \ + { \ + TYPE ret; \ + \ + /* Ensure a zero result is computed in the original rounding \ + mode. */ \ + if ((X) == -(Y)) \ + ret = (TYPE) ((X) + (Y)); \ + else \ + ret = (TYPE) ROUND_TO_ODD (math_opt_barrier (X) + (Y), \ + UNION, SUFFIX, MANTISSA); \ + \ + CHECK_NARROW_ADD (ret, (X), (Y)); \ + return ret; \ + } \ + while (0) + +/* Implement a narrowing add function that is not actually narrowing + or where no attempt is made to be correctly rounding (the latter + only applies to IBM long double). The arguments are X and Y and + the return type is TYPE. */ +#define NARROW_ADD_TRIVIAL(X, Y, TYPE) \ + do \ + { \ + TYPE ret; \ + \ + ret = (TYPE) ((X) + (Y)); \ + CHECK_NARROW_ADD (ret, (X), (Y)); \ + return ret; \ + } \ + while (0) + /* The following macros declare aliases for a narrowing function. The sole argument is the base name of a family of functions, such as "add". If any platform changes long double format after the |