| 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 } |