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