Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <stdio.h>
5 /*
6 * try all combination of flags and float conversions
7 * with some different widths & precisions
8 */
10 #define Njust 2
11 #define Nplus 3
12 #define Nalt 2
13 #define Nzero 2
14 #define Nspec 5
15 #define Nwidth 5
16 #define Nprec 5
18 static double fmtvals[] = {
19 3.1415925535897932e15,
20 3.1415925535897932e14,
21 3.1415925535897932e13,
22 3.1415925535897932e12,
23 3.1415925535897932e11,
24 3.1415925535897932e10,
25 3.1415925535897932e9,
26 3.1415925535897932e8,
27 3.1415925535897932e7,
28 3.1415925535897932e6,
29 3.1415925535897932e5,
30 3.1415925535897932e4,
31 3.1415925535897932e3,
32 3.1415925535897932e2,
33 3.1415925535897932e1,
34 3.1415925535897932e0,
35 3.1415925535897932e-1,
36 3.1415925535897932e-2,
37 3.1415925535897932e-3,
38 3.1415925535897932e-4,
39 3.1415925535897932e-5,
40 3.1415925535897932e-6,
41 3.1415925535897932e-7,
42 3.1415925535897932e-8,
43 3.1415925535897932e-9,
44 3.1415925535897932e-10,
45 3.1415925535897932e-11,
46 3.1415925535897932e-12,
47 3.1415925535897932e-13,
48 3.1415925535897932e-14,
49 3.1415925535897932e-15,
50 };
52 /*
53 * are the numbers close?
54 * used to compare long numbers where the last few digits are garbage
55 * due to precision problems
56 */
57 static int
58 numclose(char *num1, char *num2)
59 {
60 int ndig;
61 double d1, d2;
62 enum { MAXDIG = 15 };
64 d1 = fmtstrtod(num1, 0);
65 d2 = fmtstrtod(num2, 0);
66 if(d1 != d2)
67 return 0;
69 ndig = 0;
70 while (*num1) {
71 if (*num1 >= '0' && *num1 <= '9') {
72 ndig++;
73 if (ndig > MAXDIG) {
74 if (!(*num2 >= '0' && *num2 <= '9')) {
75 return 0;
76 }
77 } else if (*num1 != *num2) {
78 return 0;
79 }
80 } else if (*num1 != *num2) {
81 return 0;
82 } else if (*num1 == 'e' || *num1 == 'E') {
83 ndig = 0;
84 }
85 num1++;
86 num2++;
87 }
88 if (*num1 || !num2)
89 return 0;
90 return 1;
91 }
93 static void
94 doit(int just, int plus, int alt, int zero, int width, int prec, int spec)
95 {
96 char format[256];
97 char *p;
98 const char *s;
99 int i;
101 p = format;
102 *p++ = '%';
103 if (just > 0)
104 *p++ = "-"[just - 1];
105 if (plus > 0)
106 *p++ = "+ "[plus - 1];
107 if (alt > 0)
108 *p++ = "#"[alt - 1];
109 if (zero > 0)
110 *p++ = "0"[zero - 1];
112 s = "";
113 switch (width) {
114 case 1: s = "1"; break;
115 case 2: s = "5"; break;
116 case 3: s = "10"; break;
117 case 4: s = "15"; break;
119 strcpy(p, s);
121 s = "";
122 switch (prec) {
123 case 1: s = ".0"; break;
124 case 2: s = ".2"; break;
125 case 3: s = ".5"; break;
126 case 4: s = ".15"; break;
128 strcat(p, s);
130 p = strchr(p, '\0');
131 *p++ = "efgEG"[spec];
132 *p = '\0';
134 for (i = 0; i < sizeof(fmtvals) / sizeof(fmtvals[0]); i++) {
135 char ref[1024], buf[1024];
136 Rune rbuf[1024];
137 double d1, d2;
139 sprintf(ref, format, fmtvals[i]);
140 snprint(buf, sizeof(buf), format, fmtvals[i]);
141 if (strcmp(ref, buf) != 0
142 && !numclose(ref, buf)) {
143 d1 = fmtstrtod(ref, 0);
144 d2 = fmtstrtod(buf, 0);
145 fprintf(stderr, "%s: ref='%s'%s fmt='%s'%s\n",
146 format,
147 ref, d1==fmtvals[i] ? "" : " (ref is inexact!)",
148 buf, d2==fmtvals[i] ? "" : " (fmt is inexact!)");
149 // exits("oops");
152 /* Check again with output to rune string */
153 runesnprint(rbuf, 1024, format, fmtvals[i]);
154 snprint(buf, sizeof(buf), "%S", rbuf);
155 if (strcmp(ref, buf) != 0
156 && !numclose(ref, buf)) {
157 d1 = fmtstrtod(ref, 0);
158 d2 = fmtstrtod(buf, 0);
159 fprintf(stderr, "%s: ref='%s'%s fmt='%s'%s\n",
160 format,
161 ref, d1==fmtvals[i] ? "" : " (ref is inexact!)",
162 buf, d2==fmtvals[i] ? "" : " (fmt is inexact!)");
163 // exits("oops");
168 void
169 main(int argc, char **argv)
171 int just, plus, alt, zero, width, prec, spec;
173 for (just = 0; just < Njust; just++)
174 for (plus = 0; plus < Nplus; plus++)
175 for (alt = 0; alt < Nalt; alt++)
176 for (zero = 0; zero < Nzero; zero++)
177 for (width = 0; width < Nwidth; width++)
178 for (prec = 0; prec < Nprec; prec++)
179 for (spec = 0; spec < Nspec; spec++)
180 doit(just, plus, alt, zero, width, prec, spec);
182 exits(0);