testfltfmt.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
testfltfmt.c (3804B) | |
--- | |
1 #include <u.h> | |
2 #include <libc.h> | |
3 #include <stdio.h> | |
4 | |
5 /* | |
6 * try all combination of flags and float conversions | |
7 * with some different widths & precisions | |
8 */ | |
9 | |
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 | |
17 | |
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 }; | |
51 | |
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 }; | |
63 | |
64 d1 = fmtstrtod(num1, 0); | |
65 d2 = fmtstrtod(num2, 0); | |
66 if(d1 != d2) | |
67 return 0; | |
68 | |
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 } | |
92 | |
93 static void | |
94 doit(int just, int plus, int alt, int zero, int width, int prec, int spe… | |
95 { | |
96 char format[256]; | |
97 char *p; | |
98 const char *s; | |
99 int i; | |
100 | |
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]; | |
111 | |
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; | |
118 } | |
119 strcpy(p, s); | |
120 | |
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; | |
127 } | |
128 strcat(p, s); | |
129 | |
130 p = strchr(p, '\0'); | |
131 *p++ = "efgEG"[spec]; | |
132 *p = '\0'; | |
133 | |
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; | |
138 | |
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 ine… | |
148 buf, d2==fmtvals[i] ? "" : " (fmt is ine… | |
149 // exits("oops"); | |
150 } | |
151 | |
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 ine… | |
162 buf, d2==fmtvals[i] ? "" : " (fmt is ine… | |
163 // exits("oops"); | |
164 } | |
165 } | |
166 } | |
167 | |
168 void | |
169 main(int argc, char **argv) | |
170 { | |
171 int just, plus, alt, zero, width, prec, spec; | |
172 | |
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); | |
181 | |
182 exits(0); | |
183 } |