1 | /* |
2 | * Single-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. */ |
15 | NOINLINE static float |
16 | with_errnof (float y, int e) |
17 | { |
18 | errno = e; |
19 | return y; |
20 | } |
21 | #else |
22 | #define with_errnof(x, e) (x) |
23 | #endif |
24 | |
25 | /* NOINLINE reduces code size. */ |
26 | NOINLINE static float |
27 | xflowf (uint32_t sign, float y) |
28 | { |
29 | y = eval_as_float (x: opt_barrier_float (x: sign ? -y : y) * y); |
30 | return with_errnof (y, ERANGE); |
31 | } |
32 | |
33 | HIDDEN float |
34 | __math_uflowf (uint32_t sign) |
35 | { |
36 | return xflowf (sign, y: 0x1p-95f); |
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. */ |
42 | HIDDEN float |
43 | __math_may_uflowf (uint32_t sign) |
44 | { |
45 | return xflowf (sign, 0x1.4p-75f); |
46 | } |
47 | #endif |
48 | |
49 | HIDDEN float |
50 | __math_oflowf (uint32_t sign) |
51 | { |
52 | return xflowf (sign, y: 0x1p97f); |
53 | } |
54 | |
55 | HIDDEN float |
56 | __math_divzerof (uint32_t sign) |
57 | { |
58 | float y = opt_barrier_float (x: sign ? -1.0f : 1.0f) / 0.0f; |
59 | return with_errnof (y, ERANGE); |
60 | } |
61 | |
62 | HIDDEN float |
63 | __math_invalidf (float x) |
64 | { |
65 | float y = (x - x) / (x - x); |
66 | return isnan (x: x) ? y : with_errnof (y, EDOM); |
67 | } |
68 | |