82 lines · c
1/*2 * Double-precision math error handling.3 *4 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5 * See https://llvm.org/LICENSE.txt for license information.6 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7 */8 9#include "math_config.h"10 11#if WANT_ERRNO12#include <errno.h>13/* NOINLINE reduces code size and avoids making math functions non-leaf14 when the error handling is inlined. */15NOINLINE static double16with_errno (double y, int e)17{18 errno = e;19 return y;20}21#else22#define with_errno(x, e) (x)23#endif24 25/* NOINLINE reduces code size. */26NOINLINE static double27xflow (uint32_t sign, double y)28{29 y = eval_as_double (opt_barrier_double (sign ? -y : y) * y);30 return with_errno (y, ERANGE);31}32 33HIDDEN double34__math_uflow (uint32_t sign)35{36 return xflow (sign, 0x1p-767);37}38 39#if WANT_ERRNO_UFLOW40/* Underflows to zero in some non-nearest rounding mode, setting errno41 is valid even if the result is non-zero, but in the subnormal range. */42HIDDEN double43__math_may_uflow (uint32_t sign)44{45 return xflow (sign, 0x1.8p-538);46}47#endif48 49HIDDEN double50__math_oflow (uint32_t sign)51{52 return xflow (sign, 0x1p769);53}54 55HIDDEN double56__math_divzero (uint32_t sign)57{58 double y = opt_barrier_double (sign ? -1.0 : 1.0) / 0.0;59 return with_errno (y, ERANGE);60}61 62HIDDEN double63__math_invalid (double x)64{65 double y = (x - x) / (x - x);66 return isnan (x) ? y : with_errno (y, EDOM);67}68 69/* Check result and set errno if necessary. */70 71HIDDEN double72__math_check_uflow (double y)73{74 return y == 0.0 ? with_errno (y, ERANGE) : y;75}76 77HIDDEN double78__math_check_oflow (double y)79{80 return isinf (y) ? with_errno (y, ERANGE) : y;81}82