diff options
Diffstat (limited to 'src/lib9/testfltfmt.c')
| -rw-r--r-- | src/lib9/testfltfmt.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/lib9/testfltfmt.c b/src/lib9/testfltfmt.c new file mode 100644 index 00000000..54050422 --- /dev/null +++ b/src/lib9/testfltfmt.c @@ -0,0 +1,166 @@ +#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; + enum { MAXDIG = 15 }; + + 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[256], buf[256]; + Rune rbuf[256]; + + sprintf(ref, format, fmtvals[i]); + snprint(buf, sizeof(buf), format, fmtvals[i]); + if (strcmp(ref, buf) != 0 + && !numclose(ref, buf)) { + fprintf(stderr, "%s: ref='%s' fmt='%s'\n", format, ref, buf); + exit(1); + } + + /* Check again with output to rune string */ + runesnprint(rbuf, 256, format, fmtvals[i]); + snprint(buf, sizeof(buf), "%S", rbuf); + if (strcmp(ref, buf) != 0 + && !numclose(ref, buf)) { + fprintf(stderr, "%s: rune ref='%s' fmt='%s'\n", format, ref, buf); + 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); +} |
