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 spec) 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 inexact!)", 148 buf, d2==fmtvals[i] ? "" : " (fmt is inexact!)"); 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 inexact!)", 162 buf, d2==fmtvals[i] ? "" : " (fmt is inexact!)"); 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 }