testfltfmt.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }