git: 9front

Download patch

ref: 08edf42ecca657297a473382b4e22fc9c5330cfc
parent: e808e8db9555d8adcc6229d05db9b06d398aae83
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Wed May 1 12:44:04 EDT 2013

frexp: handle NaN values (from sources)

--- a/sys/src/ape/lib/ap/plan9/frexp.c
+++ b/sys/src/ape/lib/ap/plan9/frexp.c
@@ -6,6 +6,7 @@
 #define	MASK	0x7ffL
 #define	SHIFT	20
 #define	BIAS	1022L
+#define	SIG	52
 
 typedef	union
 {
@@ -25,13 +26,18 @@
 double
 frexp(double d, int *ep)
 {
-	Cheat x;
+	Cheat x, a;
 
-	if(d == 0) {
-		*ep = 0;
-		return 0;
-	}
+	*ep = 0;
+	/* order matters: only isNaN can operate on NaN */
+	if(isNaN(d) || isInf(d, 0) || d == 0)
+		return d;
 	x.d = d;
+	a.d = fabs(d);
+	if((a.ms >> SHIFT) == 0){	/* normalize subnormal numbers */
+		x.d = (double)(1ULL<<SIG) * d;
+		*ep = -SIG;
+	}
 	*ep = ((x.ms >> SHIFT) & MASK) - BIAS;
 	x.ms &= ~(MASK << SHIFT);
 	x.ms |= BIAS << SHIFT;
--- a/sys/src/libc/port/frexp.c
+++ b/sys/src/libc/port/frexp.c
@@ -9,18 +9,24 @@
 #define	MASK	0x7ffL
 #define	SHIFT	20
 #define	BIAS	1022L
+#define	SIG	52
 
 double
 frexp(double d, int *ep)
 {
-	FPdbleword x;
+	FPdbleword x, a;
 
-	if(d == 0) {
-		*ep = 0;
-		return 0;
-	}
+	*ep = 0;
+	/* order matters: only isNaN can operate on NaN */
+	if(isNaN(d) || isInf(d, 0) || d == 0)
+		return d;
 	x.x = d;
-	*ep = ((x.hi >> SHIFT) & MASK) - BIAS;
+	a.x = fabs(d);
+	if((a.hi >> SHIFT) == 0){	/* normalize subnormal numbers */
+		x.x = (double)(1ULL<<SIG) * d;
+		*ep = -SIG;
+	}
+	*ep += ((x.hi >> SHIFT) & MASK) - BIAS;
 	x.hi &= ~(MASK << SHIFT);
 	x.hi |= BIAS << SHIFT;
 	return x.x;
--