#include <u.h>#include <libc.h>#include <stdio.h> /* * try all combination of flags and float conversions * with some different widths & precisions */ #define Njust 2#define Nplus 3#define Nalt 2#define Nzero 2#define Nspec 5#define Nwidth 5#define Nprec 5 static double fmtvals[] = { 3.1415925535897932e15, 3.1415925535897932e14, 3.1415925535897932e13, 3.1415925535897932e12, 3.1415925535897932e11, 3.1415925535897932e10, 3.1415925535897932e9, 3.1415925535897932e8, 3.1415925535897932e7, 3.1415925535897932e6, 3.1415925535897932e5, 3.1415925535897932e4, 3.1415925535897932e3, 3.1415925535897932e2, 3.1415925535897932e1, 3.1415925535897932e0, 3.1415925535897932e-1, 3.1415925535897932e-2, 3.1415925535897932e-3, 3.1415925535897932e-4, 3.1415925535897932e-5, 3.1415925535897932e-6, 3.1415925535897932e-7, 3.1415925535897932e-8, 3.1415925535897932e-9, 3.1415925535897932e-10, 3.1415925535897932e-11, 3.1415925535897932e-12, 3.1415925535897932e-13, 3.1415925535897932e-14, 3.1415925535897932e-15,}; /* * are the numbers close? * used to compare long numbers where the last few digits are garbage * due to precision problems */static intnumclose(char *num1, char *num2){ int ndig; double d1, d2; enum { MAXDIG = 15 }; d1 = fmtstrtod(num1, 0); d2 = fmtstrtod(num2, 0); if(d1 != d2) return 0; ndig = 0; while (*num1) { if (*num1 >= '0' && *num1 <= '9') { ndig++; if (ndig > MAXDIG) { if (!(*num2 >= '0' && *num2 <= '9')) { return 0; } } else if (*num1 != *num2) { return 0; } } else if (*num1 != *num2) { return 0; } else if (*num1 == 'e' || *num1 == 'E') { ndig = 0; } num1++; num2++; } if (*num1 || !num2) return 0; return 1;} static voiddoit(int just, int plus, int alt, int zero, int width, int prec, int spec){ char format[256]; char *p; const char *s; int i; p = format; *p++ = '%'; if (just > 0) *p++ = "-"[just - 1]; if (plus > 0) *p++ = "+ "[plus - 1]; if (alt > 0) *p++ = "#"[alt - 1]; if (zero > 0) *p++ = "0"[zero - 1]; s = ""; switch (width) { case 1: s = "1"; break; case 2: s = "5"; break; case 3: s = "10"; break; case 4: s = "15"; break; } strcpy(p, s); s = ""; switch (prec) { case 1: s = ".0"; break; case 2: s = ".2"; break; case 3: s = ".5"; break; case 4: s = ".15"; break; } strcat(p, s); p = strchr(p, '\0'); *p++ = "efgEG"[spec]; *p = '\0'; for (i = 0; i < sizeof(fmtvals) / sizeof(fmtvals[0]); i++) { char ref[1024], buf[1024]; Rune rbuf[1024]; double d1, d2; sprintf(ref, format, fmtvals[i]); snprint(buf, sizeof(buf), format, fmtvals[i]); if (strcmp(ref, buf) != 0 && !numclose(ref, buf)) { d1 = fmtstrtod(ref, 0); d2 = fmtstrtod(buf, 0); fprintf(stderr, "%s: ref='%s'%s fmt='%s'%s\n", format, ref, d1==fmtvals[i] ? "" : " (ref is inexact!)", buf, d2==fmtvals[i] ? "" : " (fmt is inexact!)"); // exits("oops"); } /* Check again with output to rune string */ runesnprint(rbuf, 1024, format, fmtvals[i]); snprint(buf, sizeof(buf), "%S", rbuf); if (strcmp(ref, buf) != 0 && !numclose(ref, buf)) { d1 = fmtstrtod(ref, 0); d2 = fmtstrtod(buf, 0); fprintf(stderr, "%s: ref='%s'%s fmt='%s'%s\n", format, ref, d1==fmtvals[i] ? "" : " (ref is inexact!)", buf, d2==fmtvals[i] ? "" : " (fmt is inexact!)"); // exits("oops"); } }} voidmain(int argc, char **argv){ int just, plus, alt, zero, width, prec, spec; for (just = 0; just < Njust; just++) for (plus = 0; plus < Nplus; plus++) for (alt = 0; alt < Nalt; alt++) for (zero = 0; zero < Nzero; zero++) for (width = 0; width < Nwidth; width++) for (prec = 0; prec < Nprec; prec++) for (spec = 0; spec < Nspec; spec++) doit(just, plus, alt, zero, width, prec, spec); exits(0);}
#include <u.h>
#include <libc.h>
#include <stdio.h>
/*
* try all combination of flags and float conversions
* with some different widths & precisions
*/
#define Njust 2
#define Nplus 3
#define Nalt 2
#define Nzero 2
#define Nspec 5
#define Nwidth 5
#define Nprec 5
static double fmtvals[] = {
3.1415925535897932e15,
3.1415925535897932e14,
3.1415925535897932e13,
3.1415925535897932e12,
3.1415925535897932e11,
3.1415925535897932e10,
3.1415925535897932e9,
3.1415925535897932e8,
3.1415925535897932e7,
3.1415925535897932e6,
3.1415925535897932e5,
3.1415925535897932e4,
3.1415925535897932e3,
3.1415925535897932e2,
3.1415925535897932e1,
3.1415925535897932e0,
3.1415925535897932e-1,
3.1415925535897932e-2,
3.1415925535897932e-3,
3.1415925535897932e-4,
3.1415925535897932e-5,
3.1415925535897932e-6,
3.1415925535897932e-7,
3.1415925535897932e-8,
3.1415925535897932e-9,
3.1415925535897932e-10,
3.1415925535897932e-11,
3.1415925535897932e-12,
3.1415925535897932e-13,
3.1415925535897932e-14,
3.1415925535897932e-15,
};
/*
* are the numbers close?
* used to compare long numbers where the last few digits are garbage
* due to precision problems
*/
static int
numclose(char *num1, char *num2)
{
int ndig;
double d1, d2;
enum { MAXDIG = 15 };
d1 = fmtstrtod(num1, 0);
d2 = fmtstrtod(num2, 0);
if(d1 != d2)
return 0;
ndig = 0;
while (*num1) {
if (*num1 >= '0' && *num1 <= '9') {
ndig++;
if (ndig > MAXDIG) {
if (!(*num2 >= '0' && *num2 <= '9')) {
return 0;
}
} else if (*num1 != *num2) {
return 0;
}
} else if (*num1 != *num2) {
return 0;
} else if (*num1 == 'e' || *num1 == 'E') {
ndig = 0;
}
num1++;
num2++;
}
if (*num1 || !num2)
return 0;
return 1;
}
static void
doit(int just, int plus, int alt, int zero, int width, int prec, int spec)
{
char format[256];
char *p;
const char *s;
int i;
p = format;
*p++ = '%';
if (just > 0)
*p++ = "-"[just - 1];
if (plus > 0)
*p++ = "+ "[plus - 1];
if (alt > 0)
*p++ = "#"[alt - 1];
if (zero > 0)
*p++ = "0"[zero - 1];
s = "";
switch (width) {
case 1: s = "1"; break;
case 2: s = "5"; break;
case 3: s = "10"; break;
case 4: s = "15"; break;
}
strcpy(p, s);
s = "";
switch (prec) {
case 1: s = ".0"; break;
case 2: s = ".2"; break;
case 3: s = ".5"; break;
case 4: s = ".15"; break;
}
strcat(p, s);
p = strchr(p, '\0');
*p++ = "efgEG"[spec];
*p = '\0';
for (i = 0; i < sizeof(fmtvals) / sizeof(fmtvals[0]); i++) {
char ref[1024], buf[1024];
Rune rbuf[1024];
double d1, d2;
sprintf(ref, format, fmtvals[i]);
snprint(buf, sizeof(buf), format, fmtvals[i]);
if (strcmp(ref, buf) != 0
&& !numclose(ref, buf)) {
d1 = fmtstrtod(ref, 0);
d2 = fmtstrtod(buf, 0);
fprintf(stderr, "%s: ref='%s'%s fmt='%s'%s\n",
format,
ref, d1==fmtvals[i] ? "" : " (ref is inexact!)",
buf, d2==fmtvals[i] ? "" : " (fmt is inexact!)");
// exits("oops");
}
/* Check again with output to rune string */
runesnprint(rbuf, 1024, format, fmtvals[i]);
snprint(buf, sizeof(buf), "%S", rbuf);
if (strcmp(ref, buf) != 0
&& !numclose(ref, buf)) {
d1 = fmtstrtod(ref, 0);
d2 = fmtstrtod(buf, 0);
fprintf(stderr, "%s: ref='%s'%s fmt='%s'%s\n",
format,
ref, d1==fmtvals[i] ? "" : " (ref is inexact!)",
buf, d2==fmtvals[i] ? "" : " (fmt is inexact!)");
// exits("oops");
}
}
}
void
main(int argc, char **argv)
{
int just, plus, alt, zero, width, prec, spec;
for (just = 0; just < Njust; just++)
for (plus = 0; plus < Nplus; plus++)
for (alt = 0; alt < Nalt; alt++)
for (zero = 0; zero < Nzero; zero++)
for (width = 0; width < Nwidth; width++)
for (prec = 0; prec < Nprec; prec++)
for (spec = 0; spec < Nspec; spec++)
doit(just, plus, alt, zero, width, prec, spec);
exits(0);
}