1 /* 2 * Double-precision math error handling. 3 * 4 * Copyright (c) 2018-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 double 15 with_errno (double y, int e) 16 { 17 errno = e; 18 return y; 19 } 20 #else 21 #define with_errno(x, e) (x) 22 #endif 23 24 /* NOINLINE reduces code size. */ 25 NOINLINE static double 26 xflow (uint32_t sign, double y) 27 { 28 y = eval_as_double (opt_barrier_double (sign ? -y : y) * y); 29 return with_errno (y, ERANGE); 30 } 31 32 HIDDEN double 33 __math_uflow (uint32_t sign) 34 { 35 return xflow (sign, 0x1p-767); 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 double 41 __math_may_uflow (uint32_t sign) 42 { 43 return xflow (sign, 0x1.8p-538); 44 } 45 46 HIDDEN double 47 __math_oflow (uint32_t sign) 48 { 49 return xflow (sign, 0x1p769); 50 } 51 52 HIDDEN double 53 __math_divzero (uint32_t sign) 54 { 55 double y = opt_barrier_double (sign ? -1.0 : 1.0) / 0.0; 56 return with_errno (y, ERANGE); 57 } 58 59 HIDDEN double 60 __math_invalid (double x) 61 { 62 double y = (x - x) / (x - x); 63 return isnan (x) ? y : with_errno (y, EDOM); 64 } 65 66 /* Check result and set errno if necessary. */ 67 68 HIDDEN double 69 __math_check_uflow (double y) 70 { 71 return y == 0.0 ? with_errno (y, ERANGE) : y; 72 } 73 74 HIDDEN double 75 __math_check_oflow (double y) 76 { 77 return isinf (y) ? with_errno (y, ERANGE) : y; 78 } 79