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. */
21 /* Types of functions we could call */
22 typedef float (*f__f32__f32
)(float);
23 typedef float (*f__f32_f32__f32
)(float, float);
24 typedef float (*f__f32_f32_f32__f32
)(float, float, float);
25 typedef double (*f__f64__f64
)(double);
26 typedef double (*f__f64_f64__f64
)(double, double);
27 typedef double (*f__f64_f64_f64__f64
)(double, double, double);
29 /* Wrapper around a function pointer */
38 f__f32_f32__f32 f32_f32__f32
;
39 f__f32_f32_f32__f32 f32_f32_f32__f32
;
45 f__f64_f64__f64 f64_f64__f64
;
46 f__f64_f64_f64__f64 f64_f64_f64__f64
;
54 "usage: impl-libc [-s|-d] -f <function_name> -n <num_inputs>\n");
68 void determine_function(const char *f
, action
*a
)
70 if (!strcmp(f
, "zzzzzz")) {
72 } else if (!strcmp(f
, "id")) {
74 a
->f32
.f32__f32
= idf
;
75 a
->f64
.f64__f64
= idd
;
76 } else if (!strcmp(f
, "atan")) {
78 a
->f32
.f32__f32
= atanf
;
79 a
->f64
.f64__f64
= atan
;
80 } else if (!strcmp(f
, "atan2")) {
81 a
->a
= A__FLT_FLT__FLT
;
82 a
->f32
.f32_f32__f32
= atan2f
;
83 a
->f64
.f64_f64__f64
= atan2
;
84 } else if (!strcmp(f
, "ceil")) {
86 a
->f32
.f32__f32
= ceilf
;
87 a
->f64
.f64__f64
= ceil
;
88 } else if (!strcmp(f
, "cos")) {
90 a
->f32
.f32__f32
= cosf
;
91 a
->f64
.f64__f64
= cos
;
92 } else if (!strcmp(f
, "cot")) {
94 } else if (!strcmp(f
, "floor")) {
96 a
->f32
.f32__f32
= floorf
;
97 a
->f64
.f64__f64
= floor
;
98 } else if (!strcmp(f
, "fma")) {
99 a
->a
= A__FLT_FLT_FLT__FLT
;
100 a
->f32
.f32_f32_f32__f32
= fmaf
;
101 a
->f64
.f64_f64_f64__f64
= fma
;
102 } else if (!strcmp(f
, "exp")) {
104 a
->f32
.f32__f32
= expf
;
105 a
->f64
.f64__f64
= exp
;
106 } else if (!strcmp(f
, "expm1")) {
108 a
->f32
.f32__f32
= expm1f
;
109 a
->f64
.f64__f64
= expm1
;
110 } else if (!strcmp(f
, "log")) {
112 a
->f32
.f32__f32
= logf
;
113 a
->f64
.f64__f64
= log
;
114 } else if (!strcmp(f
, "log1p")) {
116 a
->f32
.f32__f32
= log1pf
;
117 a
->f64
.f64__f64
= log1p
;
118 } else if (!strcmp(f
, "powr")) {
119 /* libcs don't seem to have powr (yet?), just pow */
121 } else if (!strcmp(f
, "sin")) {
123 a
->f32
.f32__f32
= sinf
;
124 a
->f64
.f64__f64
= sin
;
125 } else if (!strcmp(f
, "sqrt")) {
127 a
->f32
.f32__f32
= sqrtf
;
128 a
->f64
.f64__f64
= sqrt
;
129 } else if (!strcmp(f
, "tan")) {
131 a
->f32
.f32__f32
= tanf
;
132 a
->f64
.f64__f64
= tan
;
133 } else if (!strcmp(f
, "trunc")) {
135 a
->f32
.f32__f32
= truncf
;
136 a
->f64
.f64__f64
= trunc
;
138 fprintf(stderr
, "impl-libc: unknown function \"%s\"\n", f
);
143 void read_buf(char *b
, ssize_t len
)
148 while (total
< len
) {
149 r
= read(0, (b
+ total
), (len
- total
));
154 } else if (r
== -1) {
155 perror("impl-libc: read");
163 void write_buf(const char *b
, ssize_t len
)
168 while (total
< len
) {
169 r
= write(1, (b
+ total
), (len
- total
));
172 perror("impl-libc: write");
180 size_t input_width(argtype a
, precision p
)
182 size_t w
= (p
== P_SINGLE
) ? 4 : 8;
190 case A__FLT_FLT__FLT
:
193 case A__FLT_FLT_FLT__FLT
:
201 size_t output_width(argtype a
, precision p
)
203 size_t w
= (p
== P_SINGLE
) ? 4 : 8;
211 case A__FLT_FLT__FLT
:
214 case A__FLT_FLT_FLT__FLT
:
222 void io_loop(action a
, size_t n
)
226 size_t in_sz
= input_width(a
.a
, a
.p
);
227 size_t out_sz
= output_width(a
.a
, a
.p
);
229 if ((in_sz
* n
) / n
!= in_sz
) {
230 fprintf(stderr
, "impl-libc: input length overflow\n");
234 if ((out_sz
* n
) / n
!= out_sz
) {
235 fprintf(stderr
, "impl-libc: output length overflow\n");
239 if (!(in_buf
= malloc(in_sz
* n
))) {
240 perror("impl-libc: malloc");
244 if (!(out_buf
= malloc(out_sz
* n
))) {
245 perror("impl-libc: malloc");
250 read_buf(in_buf
, in_sz
* n
);
254 fprintf(stderr
, "impl-libc: impossible\n");
262 for (size_t j
= 0; j
< n
; ++j
) {
263 float *x
= (float *) (in_buf
+ (in_sz
*
265 float *y
= (float *) (out_buf
+
268 *y
= a
.f32
.f32__f32(*x
);
274 for (size_t j
= 0; j
< n
; ++j
) {
275 double *x
= (double *) (in_buf
+
277 double *y
= (double *) (out_buf
+
280 *y
= a
.f64
.f64__f64(*x
);
287 case A__FLT_FLT__FLT
:
292 for (size_t j
= 0; j
< n
; ++j
) {
293 float *x1
= (float *) (in_buf
+ (in_sz
*
295 float *x2
= (float *) (in_buf
+ (in_sz
*
298 float *y
= (float *) (out_buf
+
301 *y
= a
.f32
.f32_f32__f32(*x1
, *x2
);
307 for (size_t j
= 0; j
< n
; ++j
) {
308 double *x1
= (double *) (in_buf
+
310 double *x2
= (double *) (in_buf
+
313 double *y
= (double *) (out_buf
+
316 *y
= a
.f64
.f64_f64__f64(*x1
, *x2
);
323 case A__FLT_FLT_FLT__FLT
:
328 for (size_t j
= 0; j
< n
; ++j
) {
329 float *x1
= (float *) (in_buf
+ (in_sz
*
331 float *x2
= (float *) (in_buf
+ (in_sz
*
334 float *x3
= (float *) (in_buf
+ (in_sz
*
337 float *y
= (float *) (out_buf
+
340 *y
= a
.f32
.f32_f32_f32__f32(*x1
, *x2
,
347 for (size_t j
= 0; j
< n
; ++j
) {
348 double *x1
= (double *) (in_buf
+
350 double *x2
= (double *) (in_buf
+
353 double *x3
= (double *) (in_buf
+
356 double *y
= (double *) (out_buf
+
359 *y
= a
.f64
.f64_f64_f64__f64(*x1
, *x2
,
369 write_buf(out_buf
, out_sz
* n
);
373 int main(int argc
, char **argv
)
376 action a
= { .p
= P_SINGLE
};
379 while ((c
= getopt(argc
, argv
, "sdf:n:")) != -1) {
388 determine_function(optarg
, &a
);
392 n
= strtoll(optarg
, 0, 0);
395 perror("impl-libc: unparsable");
407 if (a
.a
== A_UNKNOWN
) {