1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * Single-precision math error handling. 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 2017-2020, Arm Limited. 5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT 6bbbf1280Sopenharmony_ci */ 7bbbf1280Sopenharmony_ci 8bbbf1280Sopenharmony_ci#include "math_config.h" 9bbbf1280Sopenharmony_ci 10bbbf1280Sopenharmony_ci#if WANT_ERRNO 11bbbf1280Sopenharmony_ci#include <errno.h> 12bbbf1280Sopenharmony_ci/* NOINLINE reduces code size and avoids making math functions non-leaf 13bbbf1280Sopenharmony_ci when the error handling is inlined. */ 14bbbf1280Sopenharmony_ciNOINLINE static float 15bbbf1280Sopenharmony_ciwith_errnof (float y, int e) 16bbbf1280Sopenharmony_ci{ 17bbbf1280Sopenharmony_ci errno = e; 18bbbf1280Sopenharmony_ci return y; 19bbbf1280Sopenharmony_ci} 20bbbf1280Sopenharmony_ci#else 21bbbf1280Sopenharmony_ci#define with_errnof(x, e) (x) 22bbbf1280Sopenharmony_ci#endif 23bbbf1280Sopenharmony_ci 24bbbf1280Sopenharmony_ci/* NOINLINE reduces code size. */ 25bbbf1280Sopenharmony_ciNOINLINE static float 26bbbf1280Sopenharmony_cixflowf (uint32_t sign, float y) 27bbbf1280Sopenharmony_ci{ 28bbbf1280Sopenharmony_ci y = eval_as_float (opt_barrier_float (sign ? -y : y) * y); 29bbbf1280Sopenharmony_ci return with_errnof (y, ERANGE); 30bbbf1280Sopenharmony_ci} 31bbbf1280Sopenharmony_ci 32bbbf1280Sopenharmony_ciHIDDEN float 33bbbf1280Sopenharmony_ci__math_uflowf (uint32_t sign) 34bbbf1280Sopenharmony_ci{ 35bbbf1280Sopenharmony_ci return xflowf (sign, 0x1p-95f); 36bbbf1280Sopenharmony_ci} 37bbbf1280Sopenharmony_ci 38bbbf1280Sopenharmony_ci#if WANT_ERRNO_UFLOW 39bbbf1280Sopenharmony_ci/* Underflows to zero in some non-nearest rounding mode, setting errno 40bbbf1280Sopenharmony_ci is valid even if the result is non-zero, but in the subnormal range. */ 41bbbf1280Sopenharmony_ciHIDDEN float 42bbbf1280Sopenharmony_ci__math_may_uflowf (uint32_t sign) 43bbbf1280Sopenharmony_ci{ 44bbbf1280Sopenharmony_ci return xflowf (sign, 0x1.4p-75f); 45bbbf1280Sopenharmony_ci} 46bbbf1280Sopenharmony_ci#endif 47bbbf1280Sopenharmony_ci 48bbbf1280Sopenharmony_ciHIDDEN float 49bbbf1280Sopenharmony_ci__math_oflowf (uint32_t sign) 50bbbf1280Sopenharmony_ci{ 51bbbf1280Sopenharmony_ci return xflowf (sign, 0x1p97f); 52bbbf1280Sopenharmony_ci} 53bbbf1280Sopenharmony_ci 54bbbf1280Sopenharmony_ciHIDDEN float 55bbbf1280Sopenharmony_ci__math_divzerof (uint32_t sign) 56bbbf1280Sopenharmony_ci{ 57bbbf1280Sopenharmony_ci float y = opt_barrier_float (sign ? -1.0f : 1.0f) / 0.0f; 58bbbf1280Sopenharmony_ci return with_errnof (y, ERANGE); 59bbbf1280Sopenharmony_ci} 60bbbf1280Sopenharmony_ci 61bbbf1280Sopenharmony_ciHIDDEN float 62bbbf1280Sopenharmony_ci__math_invalidf (float x) 63bbbf1280Sopenharmony_ci{ 64bbbf1280Sopenharmony_ci float y = (x - x) / (x - x); 65bbbf1280Sopenharmony_ci return isnan (x) ? y : with_errnof (y, EDOM); 66bbbf1280Sopenharmony_ci} 67bbbf1280Sopenharmony_ci 68bbbf1280Sopenharmony_ci/* Check result and set errno if necessary. */ 69bbbf1280Sopenharmony_ci 70bbbf1280Sopenharmony_ciHIDDEN float 71bbbf1280Sopenharmony_ci__math_check_uflowf (float y) 72bbbf1280Sopenharmony_ci{ 73bbbf1280Sopenharmony_ci return y == 0.0f ? with_errnof (y, ERANGE) : y; 74bbbf1280Sopenharmony_ci} 75bbbf1280Sopenharmony_ci 76bbbf1280Sopenharmony_ciHIDDEN float 77bbbf1280Sopenharmony_ci__math_check_oflowf (float y) 78bbbf1280Sopenharmony_ci{ 79bbbf1280Sopenharmony_ci return isinf (y) ? with_errnof (y, ERANGE) : y; 80bbbf1280Sopenharmony_ci} 81