1/*
2 * Single-precision math error handling.
3 *
4 * Copyright (c) 2017-2020, Arm Limited.
5 * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6 */
7
8#include "math_config.h"
9
10#if WANT_ERRNO
11#include <errno.h>
12/* NOINLINE reduces code size and avoids making math functions non-leaf
13   when the error handling is inlined.  */
14NOINLINE static float
15with_errnof (float y, int e)
16{
17  errno = e;
18  return y;
19}
20#else
21#define with_errnof(x, e) (x)
22#endif
23
24/* NOINLINE reduces code size.  */
25NOINLINE static float
26xflowf (uint32_t sign, float y)
27{
28  y = eval_as_float (opt_barrier_float (sign ? -y : y) * y);
29  return with_errnof (y, ERANGE);
30}
31
32HIDDEN float
33__math_uflowf (uint32_t sign)
34{
35  return xflowf (sign, 0x1p-95f);
36}
37
38#if WANT_ERRNO_UFLOW
39/* Underflows to zero in some non-nearest rounding mode, setting errno
40   is valid even if the result is non-zero, but in the subnormal range.  */
41HIDDEN float
42__math_may_uflowf (uint32_t sign)
43{
44  return xflowf (sign, 0x1.4p-75f);
45}
46#endif
47
48HIDDEN float
49__math_oflowf (uint32_t sign)
50{
51  return xflowf (sign, 0x1p97f);
52}
53
54HIDDEN float
55__math_divzerof (uint32_t sign)
56{
57  float y = opt_barrier_float (sign ? -1.0f : 1.0f) / 0.0f;
58  return with_errnof (y, ERANGE);
59}
60
61HIDDEN float
62__math_invalidf (float x)
63{
64  float y = (x - x) / (x - x);
65  return isnan (x) ? y : with_errnof (y, EDOM);
66}
67
68/* Check result and set errno if necessary.  */
69
70HIDDEN float
71__math_check_uflowf (float y)
72{
73  return y == 0.0f ? with_errnof (y, ERANGE) : y;
74}
75
76HIDDEN float
77__math_check_oflowf (float y)
78{
79  return isinf (y) ? with_errnof (y, ERANGE) : y;
80}
81