1 /* 2 * Single-precision math error handling. 3 * 4 * Copyright (c) 2017-2020, Arm Limited. 5 * SPDX-License-Identifier: MIT 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 #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. */ 41 HIDDEN float 42 __math_may_uflowf (uint32_t sign) 43 { 44 return xflowf (sign, 0x1.4p-75f); 45 } 46 #endif 47 48 HIDDEN float 49 __math_oflowf (uint32_t sign) 50 { 51 return xflowf (sign, 0x1p97f); 52 } 53 54 HIDDEN 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 61 HIDDEN 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 70 HIDDEN float 71 __math_check_uflowf (float y) 72 { 73 return y == 0.0f ? with_errnof (y, ERANGE) : y; 74 } 75 76 HIDDEN float 77 __math_check_oflowf (float y) 78 { 79 return isinf (y) ? with_errnof (y, ERANGE) : y; 80 } 81