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