xref: /openbsd/regress/usr.bin/bc/t19.c (revision 62198fa5)
1 /*	$OpenBSD: t19.c,v 1.6 2022/04/22 18:05:29 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 #define PI 3.141592653589793238462643383279502884L
23 int scale[] = { 1, 2, 3, 10, 15, 20, 30};
24 long double num[] = {-10.0L, -PI, -3.0L, -2.0L, -1.0L, -0.5L, -0.01L, 0.0L,
25   0.01L, 0.5L, 1.0L, 2.0L, 3.0L, PI, 10.0L};
26 
27 struct func {const char *name; long double (*f)(long double);};
28 
29 struct func funcs[] = { {"s", sinl},
30 			{"c", cosl},
31 			{"e", expl},
32 			{"l", logl},
33 			{"a", atanl}
34 };
35 
36 #define nitems(_a)      (sizeof((_a)) / sizeof((_a)[0]))
37 
38 int
main(void)39 main(void)
40 {
41 	int ret, si, ni, fi;
42 	int status = 0;
43 
44 	for (si = 0; si < nitems(scale); si++) {
45 		for (ni = 0; ni < nitems(num); ni++) {
46 			for (fi = 0; fi < nitems(funcs); fi++) {
47 				char cmd[100];
48 				FILE *fp;
49 				long double v, d1, d2, diff, prec;
50 
51 				v = num[ni];
52 				if (v == 0.0 && funcs[fi].f == logl)
53 					continue;
54 				snprintf(cmd, sizeof(cmd),
55 				    "bc -l -e scale=%d -e '%s(%.36Lf)' -equit",
56 				    scale[si], funcs[fi].name, v);
57 				fp = popen(cmd, "r");
58 				ret = fscanf(fp, "%Lf", &d1);
59 				pclose(fp);
60 				d2 = funcs[fi].f(v);
61 				diff = fabsl(d1 - d2);
62 				prec = powl(10.0L, (long double)-scale[si]);
63 				if (prec < LDBL_EPSILON)
64 					prec = LDBL_EPSILON;
65 				prec *= 2;
66 				/* XXX cheating ? */
67 				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