code: plan9front

Download patch

ref: cc23b9bf4998d93b8de040f7a5a95a1f3b525b3b
parent: 8738adf91dfbd656908a578fd567a811536ce557
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Thu Mar 9 06:29:12 EST 2023

print, strtod: fix -0 and -NaN, respect verb flags when formatting

--- a/sys/src/libc/fmt/fltfmt.c
+++ b/sys/src/libc/fmt/fltfmt.c
@@ -11,6 +11,8 @@
 	NEXP10	= 308,
 };
 
+#define	SIGN	(1<<31)
+
 static int
 xadd(char *a, int n, int v)
 {
@@ -55,9 +57,10 @@
 xdtoa(Fmt *fmt, char *s2, double f)
 {
 	char s1[NSIGNIF+10];
+	FPdbleword a;
 	double g, h;
 	int e, d, i, n;
-	int c1, c2, c3, c4, ucase, sign, chr, prec;
+	int c1, c2, c3, c4, ucase, sign, chr, prec, isnan, isinf;
 
 	prec = FDEFLT;
 	if(fmt->flags & FmtPrec)
@@ -64,25 +67,16 @@
 		prec = fmt->prec;
 	if(prec > FDIGIT)
 		prec = FDIGIT;
-	if(isNaN(f)) {
-		strcpy(s2, "NaN");
-		return;
-	}
-	if(isInf(f, 1)) {
-		strcpy(s2, "+Inf");
-		return;
-	}
-	if(isInf(f, -1)) {
-		strcpy(s2, "-Inf");
-		return;
-	}
-	sign = 0;
-	if(f < 0) {
-		f = -f;
-		sign++;
-	}
+	a.x = f;
+	sign = a.hi & SIGN;
 	ucase = 0;
 	chr = fmt->r;
+	isnan = isNaN(f);
+	isinf = isInf(f, 0);
+	if(isnan || isinf)
+		goto found;
+	if(sign)
+		f = -f;
 	if(isupper(chr)) {
 		ucase = 1;
 		chr = tolower(chr);
@@ -179,6 +173,15 @@
 		s2[d++] = '+';
 	else if(fmt->flags & FmtSpace)
 		s2[d++] = ' ';
+
+	if(isnan){
+		strcpy(s2+d, "NaN");
+		return;
+	}
+	if(isinf){
+		strcpy(s2+d, "Inf");
+		return;
+	}
 
 	/*
 	 * copy into final place
--- a/sys/src/libc/port/strtod.c
+++ b/sys/src/libc/port/strtod.c
@@ -40,6 +40,8 @@
 	S7,			// _+#.#e+#	#S7
 };
 
+#define	SIGN	(1<<31)
+
 static	int	xcmp(char*, char*);
 static	int	fpcmp(char*, ulong*);
 static	void	frnorm(ulong*);
@@ -60,7 +62,7 @@
 {
 	int na, ona, ex, dp, bp, c, i, flag, state;
 	ulong low[Prec], hig[Prec], mid[Prec], num, den;
-	double d;
+	FPdbleword d;
 	char *s, a[Ndig];
 
 	flag = 0;	// Fsign, Fesign, Fdpoint
@@ -150,12 +152,12 @@
 	 */
 	switch(state) {
 	case S0:
+	case S1:
 		if(xcmp(s, "nan") == 0) {
 			if(aas != nil)
 				*aas = s+3;
 			goto retnan;
 		}
-	case S1:
 		if(xcmp(s, "infinity") == 0) {
 			if(aas != nil)
 				*aas = s+8;
@@ -283,24 +285,28 @@
 		mid[Prec-1] += Sigbit;
 		frnorm(mid);
 	}
-	d = 0;
+	d.x = 0;
 	for(i=0; i<Prec; i++)
-		d = d*One + mid[i];
+		d.x = d.x*One + mid[i];
 	if(flag & Fsign)
-		d = -d;
-	d = ldexp(d, bp - Prec*Nbits);
-	return d;
+		d.x = -d.x;
+	d.x = ldexp(d.x, bp - Prec*Nbits);
+	return d.x;
 
 ret0:
-	return 0;
+	d.x = 0;
+	if(flag & Fsign)
+		d.hi |= SIGN;
+	return d.x;
 
 retnan:
-	return NaN();
+	d.x = NaN();
+	if(flag & Fsign)
+		d.hi |= SIGN;
+	return d.x;
 
 retinf:
-	if(flag & Fsign)
-		return Inf(-1);
-	return Inf(+1);
+	return Inf(-(flag & Fsign));
 }
 
 static void