summaryrefslogtreecommitdiff
path: root/sysdeps/ieee754/flt-32/e_powf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/ieee754/flt-32/e_powf.c')
-rw-r--r--sysdeps/ieee754/flt-32/e_powf.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/sysdeps/ieee754/flt-32/e_powf.c b/sysdeps/ieee754/flt-32/e_powf.c
index ece83f0dd2..9c1902fc5b 100644
--- a/sysdeps/ieee754/flt-32/e_powf.c
+++ b/sysdeps/ieee754/flt-32/e_powf.c
@@ -1,5 +1,5 @@
/* Single-precision pow function.
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ Copyright (C) 2017-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -14,9 +14,11 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ <https://www.gnu.org/licenses/>. */
#include <math.h>
+#include <math-barriers.h>
+#include <math-narrow-eval.h>
#include <stdint.h>
#include <shlib-compat.h>
#include <libm-alias-float.h>
@@ -118,7 +120,8 @@ exp2_inline (double_t xd, uint32_t sign_bias)
return y;
}
-/* Returns 0 if not int, 1 if odd int, 2 if even int. */
+/* Returns 0 if not int, 1 if odd int, 2 if even int. The argument is
+ the bit representation of a non-zero finite floating-point value. */
static inline int
checkint (uint32_t iy)
{
@@ -155,9 +158,9 @@ __powf (float x, float y)
if (__glibc_unlikely (zeroinfnan (iy)))
{
if (2 * iy == 0)
- return issignalingf_inline (x) ? x + y : 1.0f;
+ return issignaling (x) ? x + y : 1.0f;
if (ix == 0x3f800000)
- return issignalingf_inline (y) ? x + y : 1.0f;
+ return issignaling (y) ? x + y : 1.0f;
if (2 * ix > 2u * 0x7f800000 || 2 * iy > 2u * 0x7f800000)
return x + y;
if (2 * ix == 2 * 0x3f800000)
@@ -206,7 +209,17 @@ __powf (float x, float y)
{
/* |y*log(x)| >= 126. */
if (ylogx > 0x1.fffffffd1d571p+6 * POWF_SCALE)
+ /* |x^y| > 0x1.ffffffp127. */
return __math_oflowf (sign_bias);
+ if (WANT_ROUNDING && WANT_ERRNO
+ && ylogx > 0x1.fffffffa3aae2p+6 * POWF_SCALE)
+ /* |x^y| > 0x1.fffffep127, check if we round away from 0. */
+ if ((!sign_bias
+ && math_narrow_eval (1.0f + math_opt_barrier (0x1p-25f)) != 1.0f)
+ || (sign_bias
+ && math_narrow_eval (-1.0f - math_opt_barrier (0x1p-25f))
+ != -1.0f))
+ return __math_oflowf (sign_bias);
if (ylogx <= -150.0 * POWF_SCALE)
return __math_uflowf (sign_bias);
#if WANT_ERRNO_UFLOW