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