2 ./gen can generate testcases using an mp lib
3 ./check can test an mp lib compared to the input
6 T.<rounding>.<inputs>.<outputs>.<outputerr>.<exceptflags>.
7 where . is a sequence of separators: " \t,(){}"
8 the T prefix and rounding mode are optional (default is RN),
9 so the following are all ok and equivalent input:
12 {RN, 1, 2.0, 0.1, INEXACT},
13 T(RN, 1, 2.0, 0.1, INEXACT)
15 for gen only rounding and inputs are required (the rest is discarded)
34 static int scan(const char *fmt, struct t *t, char *buf);
35 static int print(const char *fmt, struct t *t, char *buf, int n);
37 // TODO: many output, fmt->ulp
39 static int check(struct t *want, struct t *got, struct fun *f, float ulpthres);
43 int (*mpf)(struct t*);
46 #define T(f,t) {#f, mp##f, #t},
47 #include "functions.h"
51 int main(int argc, char *argv[])
62 fprintf(stderr, "%s func\n", argv[0]);
65 p = strrchr(argv[0], '/');
70 checkmode = strcmp(p, "check") == 0;
71 for (i = 0; i < sizeof fun/sizeof *fun; i++)
72 if (strcmp(fun[i].name, argv[1]) == 0) {
77 fprintf(stderr, "unknown func: %s\n", argv[1]);
80 for (i = 1; fgets(buf, sizeof buf, stdin); i++) {
82 if (*buf == 0 || *buf == '\n')
84 memset(&t, 0, sizeof t);
85 if (scan(f->fmt, &t, buf))
86 fprintf(stderr, "error scan %s, line %d\n", f->name, i);
89 fprintf(stderr, "error mpf %s, line %d\n", f->name, i);
91 if (check(&tread, &t, f, 1.0)) {
92 print(f->fmt, &tread, buf, sizeof buf);
94 print(f->fmt, &t, buf, sizeof buf);
98 if (print(f->fmt, &t, buf, sizeof buf))
99 fprintf(stderr, "error fmt %s, line %d\n", f->name, i);
106 static int check(struct t *want, struct t *got, struct fun *f, float ulpthres)
109 int m = INEXACT|UNDERFLOW; // TODO: dont check inexact and underflow for now
111 if ((got->e|m) != (want->e|m)) {
112 fprintf(stdout, "%s %s(%La,%La)==%La except: want %s",
113 rstr(want->r), f->name, want->x, want->x2, want->y, estr(want->e));
114 fprintf(stdout, " got %s\n", estr(got->e));
117 if (isnan(got->y) && isnan(want->y))
119 if (got->y != want->y || signbit(got->y) != signbit(want->y)) {
124 p = strchr(f->fmt, '_');
137 d = scalbnl(got->y - want->y, -n);
138 if (fabsf(d + want->dy) <= ulpthres)
140 fprintf(stdout, "%s %s(%La,%La) want %La got %La ulperr %.3f = %a + %a\n",
141 rstr(want->r), f->name, want->x, want->x2, want->y, got->y, d + want->dy, d, want->dy);
147 // scan discards suffixes, this may cause rounding issues (eg scanning 0.1f as long double)
148 static int scan1(long double *x, char *s, int fmt)
154 if (sscanf(s, "%lf", &d) != 1)
157 } else if (fmt == 'f') {
158 if (sscanf(s, "%f", &f) != 1)
161 } else if (fmt == 'l') {
162 return sscanf(s, "%Lf", x) != 1;
168 static int scan(const char *fmt, struct t *t, char *buf)
176 buf = skipstr(buf, "T \t\r\n,(){}");
177 n = splitstr(a, sizeof a/sizeof *a, buf, " \t\r\n,(){}");
180 if (a[0][0] == 'R') {
181 if (rconv(&t->r, a[i++]))
190 for (; *fmt && *fmt != '_'; fmt++) {
194 t->i = strtoll(a[i++], &end, 0);
197 } else if (*fmt == 'd' || *fmt == 'f' || *fmt == 'l') {
198 if (scan1(b[j++], a[i++], *fmt))
210 for (; *fmt && i < n && j < sizeof b/sizeof *b; fmt++) {
212 t->i = strtoll(a[i++], &end, 0);
215 } else if (*fmt == 'd' || *fmt == 'f' || *fmt == 'l') {
216 if (scan1(b[j++], a[i++], *fmt))
218 if (i < n && scan1(b[j++], a[i++], 'f'))
230 /* assume strlen(old) == strlen(new) */
231 static void replace(char *buf, char *old, char *new)
236 while ((p = strstr(p, old)))
240 static void fixl(char *buf)
242 replace(buf, "-infL", " -inf");
243 replace(buf, "infL", " inf");
244 replace(buf, "-nanL", " -nan");
245 replace(buf, "nanL", " nan");
248 static int print1(char *buf, int n, long double x, int fmt)
253 k = snprintf(buf, n, ",%24a", (double)x);
255 k = snprintf(buf, n, ",%16a", (double)x);
256 else if (fmt == 'l') {
257 #if LDBL_MANT_DIG == 53
258 k = snprintf(buf, n, ",%24a", (double)x);
259 #elif LDBL_MANT_DIG == 64
260 k = snprintf(buf, n, ",%30LaL", x);
268 static int print(const char *fmt, struct t *t, char *buf, int n)
273 k = snprintf(buf, n, "T(%s", rstr(t->r));
282 for (; *fmt; fmt++) {
293 k = snprintf(buf, n, ", %11lld", t->i);
299 if (i >= sizeof a/sizeof *a)
301 k = print1(buf, n, a[i++], *fmt);
307 k = print1(buf, n, a[i++], 'f');
315 k = snprintf(buf, n, ", %s)\n", estr(t->e));