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