diff options
Diffstat (limited to 'math/math-narrow.h')
-rw-r--r-- | math/math-narrow.h | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/math/math-narrow.h b/math/math-narrow.h index f769830643..c4065e88f7 100644 --- a/math/math-narrow.h +++ b/math/math-narrow.h @@ -219,6 +219,59 @@ } \ while (0) +/* Check for error conditions from a narrowing divide function + returning RET with arguments X and Y and set errno as needed. + Overflow, underflow and divide-by-zero can occur for finite + arguments and a domain error for Inf / Inf and 0 / 0. */ +#define CHECK_NARROW_DIV(RET, X, Y) \ + do \ + { \ + if (!isfinite (RET)) \ + { \ + if (isnan (RET)) \ + { \ + if (!isnan (X) && !isnan (Y)) \ + __set_errno (EDOM); \ + } \ + else if (isfinite (X)) \ + __set_errno (ERANGE); \ + } \ + else if ((RET) == 0 && (X) != 0 && !isinf (Y)) \ + __set_errno (ERANGE); \ + } \ + 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) \ + do \ + { \ + TYPE ret; \ + \ + ret = (TYPE) ROUND_TO_ODD (math_opt_barrier (X) / (Y), \ + UNION, SUFFIX, MANTISSA); \ + \ + CHECK_NARROW_DIV (ret, (X), (Y)); \ + return ret; \ + } \ + while (0) + +/* Implement a narrowing divide 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_DIV_TRIVIAL(X, Y, TYPE) \ + do \ + { \ + TYPE ret; \ + \ + ret = (TYPE) ((X) / (Y)); \ + CHECK_NARROW_DIV (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 |