xref: /openbsd/regress/usr.bin/bc/t19.c (revision a6445c1d)
1 /*	$OpenBSD: t19.c,v 1.2 2012/03/13 10:34:04 otto Exp $	*/
2 
3 /*
4  * Copyright (c) 2012 Otto Moerbeek <otto@drijf.net>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 #include <float.h>
19 #include <math.h>
20 #include <stdio.h>
21 
22 int scale[] = { 1, 2, 3, 10, 15, 20, 30};
23 long double num[] = {-10, -M_PI, -3, -2, -1, -0.5, -0.01, 0, 0.01,
24   0.5, 1, 2, 3, M_PI, 10};
25 
26 struct func {const char *name; long double (*f)(long double);};
27 
28 struct func funcs[] = { {"s", sinl},
29 			{"c", cosl},
30 			{"e", expl},
31 			{"l", logl},
32 			{"a", atanl}
33 };
34 
35 #define nitems(_a)      (sizeof((_a)) / sizeof((_a)[0]))
36 
37 main()
38 {
39 	int ret, si, ni, fi;
40 	int status = 0;
41 
42 	for (si = 0; si < nitems(scale); si++) {
43 		for (ni = 0; ni < nitems(num); ni++) {
44 			for (fi = 0; fi < nitems(funcs); fi++) {
45 				char cmd[100];
46 				FILE *fp;
47 				long double v, d1, d2, diff, prec;
48 
49 				v = num[ni];
50 				if (v == 0.0 && funcs[fi].f == logl)
51 					continue;
52 				snprintf(cmd, sizeof(cmd),
53 				    "bc -l -e scale=%d -e '%s(%.19Lf)' -equit",
54 				    scale[si], funcs[fi].name, v);
55 				fp = popen(cmd, "r");
56 				ret = fscanf(fp, "%Lf", &d1);
57 				pclose(fp);
58 				d2 = funcs[fi].f(v);
59 				diff = fabsl(d1 - d2);
60 				prec = pow(10, -scale[si]);
61 				if (prec < LDBL_EPSILON)
62 					prec = LDBL_EPSILON;
63 				prec *= 2;
64 				/* XXX cheating ? */
65 				if (funcs[fi].f == logl)
66 					prec *= 4;
67 				else if (funcs[fi].f == expl)
68 					prec *= 8;
69 				if (diff > prec) {
70 					printf("%s %d %Le %Le %Le %Le %Le\n",
71 					    funcs[fi].name, scale[si],
72 					    v, d1, d2, diff, prec);
73 					status = 1;
74 				}
75 
76 			}
77 		}
78 	}
79 	return status;
80 }
81