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-exception
7 */
8
9#include "math_config.h"
10
11#if WANT_ERRNO
12#include <errno.h>
13/* NOINLINE reduces code size and avoids making math functions non-leaf
14 when the error handling is inlined. */
15NOINLINE static double
16with_errno (double y, int e)
17{
18 errno = e;
19 return y;
20}
21#else
22#define with_errno(x, e) (x)
23#endif
24
25/* NOINLINE reduces code size. */
26NOINLINE static double
27xflow (uint32_t sign, double y)
28{
29 y = eval_as_double (x: opt_barrier_double (x: sign ? -y : y) * y);
30 return with_errno (y, ERANGE);
31}
32
33HIDDEN double
34__math_uflow (uint32_t sign)
35{
36 return xflow (sign, y: 0x1p-767);
37}
38
39#if WANT_ERRNO_UFLOW
40/* Underflows to zero in some non-nearest rounding mode, setting errno
41 is valid even if the result is non-zero, but in the subnormal range. */
42HIDDEN double
43__math_may_uflow (uint32_t sign)
44{
45 return xflow (sign, 0x1.8p-538);
46}
47#endif
48
49HIDDEN double
50__math_oflow (uint32_t sign)
51{
52 return xflow (sign, y: 0x1p769);
53}
54
55HIDDEN double
56__math_divzero (uint32_t sign)
57{
58 double y = opt_barrier_double (x: sign ? -1.0 : 1.0) / 0.0;
59 return with_errno (y, ERANGE);
60}
61
62HIDDEN double
63__math_invalid (double x)
64{
65 double y = (x - x) / (x - x);
66 return isnan (x: x) ? y : with_errno (y, EDOM);
67}
68
69/* Check result and set errno if necessary. */
70
71HIDDEN double
72__math_check_uflow (double y)
73{
74 return y == 0.0 ? with_errno (y, ERANGE) : y;
75}
76
77HIDDEN double
78__math_check_oflow (double y)
79{
80 return isinf (x: y) ? with_errno (y, ERANGE) : y;
81}
82

source code of libc/AOR_v20.02/math/math_err.c