blob: 07154c57d4fb8341840997c39ee0e2f943de3b77 [file] [log] [blame]
Szabolcs Nagy86067a72017-08-11 15:35:12 +01001/*
Szabolcs Nagy1b945972018-05-14 14:46:40 +01002 * Single-precision math error handling.
Szabolcs Nagy86067a72017-08-11 15:35:12 +01003 *
Szabolcs Nagy11253b02018-11-12 11:10:57 +00004 * Copyright (c) 2017-2018, Arm Limited.
5 * SPDX-License-Identifier: MIT
Szabolcs Nagy86067a72017-08-11 15:35:12 +01006 */
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
Szabolcs Nagy5fa69e12018-06-12 17:18:24 +010024/* NOINLINE reduces code size. */
Szabolcs Nagy86067a72017-08-11 15:35:12 +010025NOINLINE static float
Szabolcs Nagyc65db172018-05-10 17:53:31 +010026xflowf (uint32_t sign, float y)
Szabolcs Nagy86067a72017-08-11 15:35:12 +010027{
Szabolcs Nagy04884bd2018-12-07 14:58:51 +000028 y = eval_as_float (opt_barrier_float (sign ? -y : y) * y);
Szabolcs Nagy86067a72017-08-11 15:35:12 +010029 return with_errnof (y, ERANGE);
30}
31
32HIDDEN float
Szabolcs Nagyc65db172018-05-10 17:53:31 +010033__math_uflowf (uint32_t sign)
Szabolcs Nagy86067a72017-08-11 15:35:12 +010034{
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
Szabolcs Nagyc65db172018-05-10 17:53:31 +010042__math_may_uflowf (uint32_t sign)
Szabolcs Nagy86067a72017-08-11 15:35:12 +010043{
44 return xflowf (sign, 0x1.4p-75f);
45}
46#endif
47
48HIDDEN float
Szabolcs Nagyc65db172018-05-10 17:53:31 +010049__math_oflowf (uint32_t sign)
Szabolcs Nagy86067a72017-08-11 15:35:12 +010050{
51 return xflowf (sign, 0x1p97f);
52}
53
54HIDDEN float
Szabolcs Nagyc65db172018-05-10 17:53:31 +010055__math_divzerof (uint32_t sign)
Szabolcs Nagy86067a72017-08-11 15:35:12 +010056{
Szabolcs Nagy5fa69e12018-06-12 17:18:24 +010057 float y = opt_barrier_float (sign ? -1.0f : 1.0f) / 0.0f;
58 return with_errnof (y, ERANGE);
Szabolcs Nagy86067a72017-08-11 15:35:12 +010059}
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}