1 /* 2 * Single-precision math error handling. 3 * 4 * Copyright (c) 2017-2023, 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. */ 14 NOINLINE static float 15 with_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. */ 25 NOINLINE static float 26 xflowf (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 32 HIDDEN float 33 __math_uflowf (uint32_t sign) 34 { 35 return xflowf (sign, 0x1p-95f); 36 } 37 38 /* Underflows to zero in some non-nearest rounding mode, setting errno 39 is valid even if the result is non-zero, but in the subnormal range. */ 40 HIDDEN float 41 __math_may_uflowf (uint32_t sign) 42 { 43 return xflowf (sign, 0x1.4p-75f); 44 } 45 46 HIDDEN float 47 __math_oflowf (uint32_t sign) 48 { 49 return xflowf (sign, 0x1p97f); 50 } 51 52 HIDDEN float 53 __math_divzerof (uint32_t sign) 54 { 55 float y = opt_barrier_float (sign ? -1.0f : 1.0f) / 0.0f; 56 return with_errnof (y, ERANGE); 57 } 58 59 HIDDEN float 60 __math_invalidf (float x) 61 { 62 float y = (x - x) / (x - x); 63 return isnan (x) ? y : with_errnof (y, EDOM); 64 } 65 66 /* Check result and set errno if necessary. */ 67 68 HIDDEN float 69 __math_check_uflowf (float y) 70 { 71 return y == 0.0f ? with_errnof (y, ERANGE) : y; 72 } 73 74 HIDDEN float 75 __math_check_oflowf (float y) 76 { 77 return isinf (y) ? with_errnof (y, ERANGE) : y; 78 } 79