Add myrddin implementation (the whole point of this project)
[fpmath-consensus.git] / impl-libc / impl-libc.c
blob152e87ca890f1072cf7bcd6351c5ce53b01a9742
1 #include <errno.h>
2 #include <math.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include <unistd.h>
9 /* Whether we're looking at 32-bit or 64-bit floats */
10 typedef enum { P_SINGLE, P_DOUBLE } precision;
12 /* What type of arguments we expect, and what we'll give back. */
13 typedef enum {
14 /* */
15 A_UNKNOWN,
16 A__FLT__FLT,
17 } argtype;
19 /* Types of functions we could call */
20 typedef float (*f__f32__f32)(float);
21 typedef double (*f__f64__f64)(double);
23 /* Wrapper around a function pointer */
24 typedef struct {
25 /* */
26 precision p;
27 argtype a;
29 union {
30 /* */
31 f__f32__f32 f32__f32;
32 } f32;
34 union {
35 /* */
36 f__f64__f64 f64__f64;
37 } f64;
39 } action;
41 void usage(void)
43 fprintf(stderr, "usage: impl-libc [-s|-d] -f <function_name> -n <num_inputs>\n");
44 _exit(1);
47 float idf(float f)
49 return f;
52 double idd(double d)
54 return d;
57 void determine_function(const char *f, action *a)
59 if (!strcmp(f, "zzzzzz")) {
60 a->a = A_UNKNOWN;
61 } else if (!strcmp(f, "id")) {
62 a->a = A__FLT__FLT;
63 a->f32.f32__f32 = idf;
64 a->f64.f64__f64 = idd;
65 } else if (!strcmp(f, "ceil")) {
66 a->a = A__FLT__FLT;
67 a->f32.f32__f32 = ceilf;
68 a->f64.f64__f64 = ceil;
69 } else if (!strcmp(f, "cos")) {
70 a->a = A__FLT__FLT;
71 a->f32.f32__f32 = cosf;
72 a->f64.f64__f64 = cos;
73 } else if (!strcmp(f, "floor")) {
74 a->a = A__FLT__FLT;
75 a->f32.f32__f32 = floorf;
76 a->f64.f64__f64 = floor;
77 } else if (!strcmp(f, "sin")) {
78 a->a = A__FLT__FLT;
79 a->f32.f32__f32 = sinf;
80 a->f64.f64__f64 = sin;
81 } else if (!strcmp(f, "trunc")) {
82 a->a = A__FLT__FLT;
83 a->f32.f32__f32 = truncf;
84 a->f64.f64__f64 = trunc;
85 } else {
86 fprintf(stderr, "impl-libc: unknown function \"%s\"\n", f);
87 _exit(1);
91 void read_buf(char *b, ssize_t len)
93 ssize_t r;
94 ssize_t total = 0;
96 while (total < len) {
97 r = read(0, (b + total), (len - total));
99 if (!r) {
100 /* EOF */
101 _exit(0);
102 } else if (r == -1) {
103 perror("impl-libc: read");
104 _exit(1);
105 } else {
106 total += r;
111 void write_buf(const char *b, ssize_t len)
113 ssize_t r;
114 ssize_t total = 0;
116 while (total < len) {
117 r = write(1, (b + total), (len - total));
119 if (r == -1) {
120 perror("impl-libc: write");
121 _exit(1);
122 } else {
123 total += r;
128 size_t input_width(argtype a, precision p)
130 size_t w = (p == P_SINGLE) ? 4 : 8;
132 switch (a) {
133 case A_UNKNOWN:
134 break;
135 case A__FLT__FLT:
137 return 1 * w;
140 return (size_t) -1;
143 size_t output_width(argtype a, precision p)
145 size_t w = (p == P_SINGLE) ? 4 : 8;
147 switch (a) {
148 case A_UNKNOWN:
149 break;
150 case A__FLT__FLT:
152 return 1 * w;
155 return (size_t) -1;
158 void io_loop(action a, size_t n)
160 char *in_buf = 0;
161 char *out_buf = 0;
162 size_t in_sz = input_width(a.a, a.p);
163 size_t out_sz = output_width(a.a, a.p);
165 if ((in_sz * n) / n != in_sz) {
166 fprintf(stderr, "impl-libc: input length overflow\n");
167 _exit(1);
170 if ((out_sz * n) / n != out_sz) {
171 fprintf(stderr, "impl-libc: output length overflow\n");
172 _exit(1);
175 if (!(in_buf = malloc(in_sz * n))) {
176 perror("impl-libc: malloc");
177 _exit(1);
180 if (!(out_buf = malloc(out_sz * n))) {
181 perror("impl-libc: malloc");
182 _exit(1);
185 while (1) {
186 read_buf(in_buf, in_sz * n);
188 switch (a.a) {
189 case A_UNKNOWN:
190 fprintf(stderr, "impl-libc: impossible\n");
191 _exit(1);
192 break;
193 case A__FLT__FLT:
195 switch (a.p) {
196 case P_SINGLE:
198 for (size_t j = 0; j < n; ++j) {
199 float *x = (float *) (in_buf + (in_sz *
200 j));
201 float *y = (float *) (out_buf +
202 (out_sz * j));
204 *y = a.f32.f32__f32(*x);
207 break;
208 case P_DOUBLE:
210 for (size_t j = 0; j < n; ++j) {
211 double *x = (double *) (in_buf +
212 (in_sz * j));
213 double *y = (double *) (out_buf +
214 (out_sz * j));
216 *y = a.f64.f64__f64(*x);
219 break;
222 break;
225 write_buf(out_buf, out_sz * n);
229 int main(int argc, char **argv)
231 int c = 0;
232 action a = { .p = P_SINGLE };
233 long long n = 0;
235 while ((c = getopt(argc, argv, "sdf:n:")) != -1) {
236 switch (c) {
237 case 's':
238 a.p = P_SINGLE;
239 break;
240 case 'd':
241 a.p = P_DOUBLE;
242 break;
243 case 'f':
244 determine_function(optarg, &a);
245 break;
246 case 'n':
247 errno = 0;
248 n = strtoll(optarg, 0, 0);
250 if (errno) {
251 perror("impl-libc: unparsable");
253 return 1;
256 break;
257 default:
258 usage();
259 break;
263 if (a.a == A_UNKNOWN) {
264 usage();
267 io_loop(a, n);