ref: 37a5e86bf0aaffb1cdc841150ecc9c847b795e9b
parent: 55f018df8a6006125dcfda55c412ee6908c9ed9b
author: Ori Bernstein <ori@eigenstate.org'>
date: Sun Jun 16 11:55:55 EDT 2019
Handle NaN and Inf edge cases as specified by posix, instead of barfing. We're not a posix system, but the posix spec is a good reference for what we should do. Thanks Geoff for the inspiration for this patch.
--- a/sys/src/libc/port/pow.c
+++ b/sys/src/libc/port/pow.c
@@ -1,6 +1,16 @@
#include <u.h>
#include <libc.h>
+static int
+isodd(double v)
+{
+ double iv;
+
+ if(modf(v, &iv) != 0)
+ return 0;
+ return (vlong)iv & 1;
+}
+
double
pow(double x, double y) /* return x ^ y (exponentiation) */
{
@@ -8,8 +18,44 @@
long i;
int ex, ey, flip;
- if(y == 0.0)
+ /*
+ * Special cases.
+ * Checking early here prevents an infinite loop.
+ * We need to test if !isNaN() here because otherwise
+ * we trap.
+ */
+ if(!isNaN(x) && x == 1.0)
return 1.0;
+ if(!isNaN(y) && y == 0.0)
+ return 1.0;
+ if(isNaN(x) || isNaN(y))
+ return NaN();
+ if(isInf(x, 1)){
+ if(y < 0)
+ return 0.0;
+ else
+ return Inf(1);
+ }else if(isInf(x, -1)){
+ if(y < 0)
+ return isodd(y) ? -0.0 : 0.0;
+ else if(y > 0)
+ return isodd(y) ? Inf(-1) : Inf(1);
+ }
+ if(isInf(y, 1)){
+ if(x == -1.0)
+ return 1.0;
+ else if(fabs(x) < 1.0)
+ return 0.0;
+ else if(fabs(x) > 1.0)
+ return Inf(1);
+ }else if(isInf(y, -1)){
+ if(x == -1.0)
+ return 1.0;
+ else if(fabs(x) < 1.0)
+ return Inf(1);
+ else if(fabs(x) > 1.0)
+ return 0.0;
+ }
flip = 0;
if(y < 0.){