summaryrefslogtreecommitdiffstats
path: root/lib/libm/src/e_pow.c
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2013-08-02 20:23:28 +0000
committerkettenis <kettenis@openbsd.org>2013-08-02 20:23:28 +0000
commitd205ab02eabefec09df68de8ff35e0519ffc9a86 (patch)
treebd1af2e134d4ae75481b006c069142022a9a87d2 /lib/libm/src/e_pow.c
parentNo longer needed since miod taught elf to mkuboot. (diff)
downloadwireguard-openbsd-d205ab02eabefec09df68de8ff35e0519ffc9a86.tar.xz
wireguard-openbsd-d205ab02eabefec09df68de8ff35e0519ffc9a86.zip
Fix a couple of corner cases in the implementation of pow(3) to make it
compatible with C99. Most notably: - 1**y == 1, even if y is NaN - (-1)**+-Inf == 1 and adjust the cephes testsuite to test for the right thing here. ok martynas@
Diffstat (limited to 'lib/libm/src/e_pow.c')
-rw-r--r--lib/libm/src/e_pow.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/lib/libm/src/e_pow.c b/lib/libm/src/e_pow.c
index 5fce17c8c7b..2af0e921b3e 100644
--- a/lib/libm/src/e_pow.c
+++ b/lib/libm/src/e_pow.c
@@ -24,13 +24,13 @@
* Special cases:
* 1. (anything) ** 0 is 1
* 2. (anything) ** 1 is itself
- * 3. (anything) ** NAN is NAN
+ * 3. (anything except 1) ** NAN is NAN
* 4. NAN ** (anything except 0) is NAN
* 5. +-(|x| > 1) ** +INF is +INF
* 6. +-(|x| > 1) ** -INF is +0
* 7. +-(|x| < 1) ** +INF is +0
* 8. +-(|x| < 1) ** -INF is +INF
- * 9. +-1 ** +-INF is NAN
+ * 9. +-1 ** +-INF is 1
* 10. +0 ** (+anything except 0, NAN) is +0
* 11. -0 ** (+anything except 0, NAN, odd integer) is +0
* 12. +0 ** (-anything except 0, NAN) is +INF
@@ -109,6 +109,9 @@ pow(double x, double y)
/* y==zero: x**0 = 1 */
if((iy|ly)==0) return one;
+ /* x==1: 1**y = 1, even if y is NaN */
+ if (hx==0x3ff00000 && lx == 0) return one;
+
/* +-NaN return x+y */
if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
@@ -138,7 +141,7 @@ pow(double x, double y)
if(ly==0) {
if (iy==0x7ff00000) { /* y is +-inf */
if(((ix-0x3ff00000)|lx)==0)
- return y - y; /* inf**+-1 is NaN */
+ return one; /* (-1)**+-inf is 1 */
else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
return (hy>=0)? y: zero;
else /* (|x|<1)**-,+inf = inf,0 */