summaryrefslogtreecommitdiffstats
path: root/src/lib9/testfltfmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib9/testfltfmt.c')
-rw-r--r--src/lib9/testfltfmt.c166
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);
+}