10 /* Whether we're looking at 32-bit or 64-bit floats */
11 typedef enum { P_SINGLE
, P_DOUBLE
} precision
;
13 /* What type of arguments we expect, and what we'll give back. */
19 A__FLT_FLT_FLT_RND__FLT
,
23 /* Types of functions we could call */
24 typedef int (*f__flt_flt_flt_rnd__flt
)(mpfr_ptr
, mpfr_srcptr
, mpfr_srcptr
,
25 mpfr_srcptr
, mpfr_rnd_t
);
26 typedef int (*f__flt__flt
)(mpfr_ptr
, mpfr_srcptr
);
27 typedef int (*f__flt_flt_rnd__flt
)(mpfr_ptr
, mpfr_srcptr
, mpfr_srcptr
,
29 typedef int (*f__flt_rnd__flt
)(mpfr_ptr
, mpfr_srcptr
, mpfr_rnd_t
);
31 /* Wrapper around a function pointer */
40 f__flt_flt_rnd__flt flt_flt_rnd__flt
;
41 f__flt_flt_flt_rnd__flt flt_flt_flt_rnd__flt
;
42 f__flt_rnd__flt flt_rnd__flt
;
49 "usage: impl-mpfr [-s|-d] -f <function_name> -n <num_inputs>\n");
53 void determine_function(const char *f
, action
*a
)
55 if (!strcmp(f
, "zzzzzzzzz")) {
57 } else if (!strcmp(f
, "id")) {
58 a
->a
= A__FLT_RND__FLT
;
59 a
->f
.flt_rnd__flt
= mpfr_set
;
60 } else if (!strcmp(f
, "ceil")) {
62 a
->f
.flt__flt
= mpfr_ceil
;
63 } else if (!strcmp(f
, "cos")) {
64 a
->a
= A__FLT_RND__FLT
;
65 a
->f
.flt_rnd__flt
= mpfr_cos
;
66 } else if (!strcmp(f
, "cot")) {
67 a
->a
= A__FLT_RND__FLT
;
68 a
->f
.flt_rnd__flt
= mpfr_cot
;
69 } else if (!strcmp(f
, "floor")) {
71 a
->f
.flt__flt
= mpfr_floor
;
72 } else if (!strcmp(f
, "exp")) {
73 a
->a
= A__FLT_RND__FLT
;
74 a
->f
.flt_rnd__flt
= mpfr_exp
;
75 } else if (!strcmp(f
, "expm1")) {
76 a
->a
= A__FLT_RND__FLT
;
77 a
->f
.flt_rnd__flt
= mpfr_expm1
;
78 } else if (!strcmp(f
, "fma")) {
79 a
->a
= A__FLT_FLT_FLT_RND__FLT
;
80 a
->f
.flt_flt_flt_rnd__flt
= mpfr_fma
;
81 } else if (!strcmp(f
, "log")) {
82 a
->a
= A__FLT_RND__FLT
;
83 a
->f
.flt_rnd__flt
= mpfr_log
;
84 } else if (!strcmp(f
, "log1p")) {
85 a
->a
= A__FLT_RND__FLT
;
86 a
->f
.flt_rnd__flt
= mpfr_log1p
;
87 } else if (!strcmp(f
, "powr")) {
88 a
->a
= A__FLT_FLT_RND__FLT
;
89 a
->f
.flt_flt_rnd__flt
= mpfr_pow
;
90 } else if (!strcmp(f
, "sin")) {
91 a
->a
= A__FLT_RND__FLT
;
92 a
->f
.flt_rnd__flt
= mpfr_sin
;
93 } else if (!strcmp(f
, "sqrt")) {
94 a
->a
= A__FLT_RND__FLT
;
95 a
->f
.flt_rnd__flt
= mpfr_sqrt
;
96 } else if (!strcmp(f
, "tan")) {
97 a
->a
= A__FLT_RND__FLT
;
98 a
->f
.flt_rnd__flt
= mpfr_tan
;
99 } else if (!strcmp(f
, "trunc")) {
101 a
->f
.flt__flt
= mpfr_trunc
;
103 fprintf(stderr
, "impl-mpfr: unknown function \"%s\"\n", f
);
108 void read_buf(char *b
, ssize_t len
)
113 while (total
< len
) {
114 r
= read(0, (b
+ total
), (len
- total
));
119 } else if (r
== -1) {
120 perror("impl-mpfr: read");
128 void write_buf(const char *b
, ssize_t len
)
133 while (total
< len
) {
134 r
= write(1, (b
+ total
), (len
- total
));
137 perror("impl-mpfr: write");
145 size_t input_width(argtype a
, precision p
)
147 size_t w
= (p
== P_SINGLE
) ? 4 : 8;
155 case A__FLT_FLT_RND__FLT
:
158 case A__FLT_FLT_FLT_RND__FLT
:
161 case A__FLT_RND__FLT
:
169 size_t output_width(argtype a
, precision p
)
171 size_t w
= (p
== P_SINGLE
) ? 4 : 8;
179 case A__FLT_FLT_RND__FLT
:
182 case A__FLT_FLT_FLT_RND__FLT
:
185 case A__FLT_RND__FLT
:
193 void io_loop(action a
, size_t n
)
197 size_t in_sz
= input_width(a
.a
, a
.p
);
198 size_t out_sz
= output_width(a
.a
, a
.p
);
204 if ((in_sz
* n
) / n
!= in_sz
) {
205 fprintf(stderr
, "impl-libc: input length overflow\n");
209 if ((out_sz
* n
) / n
!= out_sz
) {
210 fprintf(stderr
, "impl-libc: output length overflow\n");
214 if (!(in_buf
= malloc(in_sz
* n
))) {
215 perror("impl-libc: malloc");
219 if (!(out_buf
= malloc(out_sz
* n
))) {
220 perror("impl-libc: malloc");
224 /* I'm pretty sure 53 precision would be enough */
231 read_buf(in_buf
, in_sz
* n
);
235 fprintf(stderr
, "impl-libc: impossible\n");
243 for (size_t j
= 0; j
< n
; ++j
) {
244 float *xf1
= (float *) (in_buf
+
246 float *yf
= (float *) (out_buf
+
249 mpfr_set_flt(x1
, *xf1
, MPFR_RNDN
);
251 *yf
= mpfr_get_flt(y
, MPFR_RNDN
);
257 for (size_t j
= 0; j
< n
; ++j
) {
258 double *xf1
= (double *) (in_buf
+
260 double *yf
= (double *) (out_buf
+
263 mpfr_set_d(x1
, *xf1
, MPFR_RNDN
);
265 *yf
= mpfr_get_d(y
, MPFR_RNDN
);
272 case A__FLT_FLT_RND__FLT
:
277 for (size_t j
= 0; j
< n
; ++j
) {
278 float *xf1
= (float *) (in_buf
+
280 float *xf2
= (float *) (in_buf
+
283 float *yf
= (float *) (out_buf
+
286 mpfr_set_flt(x1
, *xf1
, MPFR_RNDN
);
287 mpfr_set_flt(x2
, *xf2
, MPFR_RNDN
);
288 a
.f
.flt_flt_rnd__flt(y
, x1
, x2
,
290 *yf
= mpfr_get_flt(y
, MPFR_RNDN
);
296 for (size_t j
= 0; j
< n
; ++j
) {
297 double *xf1
= (double *) (in_buf
+
299 double *xf2
= (double *) (in_buf
+
302 double *yf
= (double *) (out_buf
+
305 mpfr_set_d(x1
, *xf1
, MPFR_RNDN
);
306 mpfr_set_d(x2
, *xf2
, MPFR_RNDN
);
307 a
.f
.flt_flt_rnd__flt(y
, x1
, x2
,
309 *yf
= mpfr_get_d(y
, MPFR_RNDN
);
316 case A__FLT_FLT_FLT_RND__FLT
:
321 for (size_t j
= 0; j
< n
; ++j
) {
322 float *xf1
= (float *) (in_buf
+
324 float *xf2
= (float *) (in_buf
+
327 float *xf3
= (float *) (in_buf
+
330 float *yf
= (float *) (out_buf
+
333 mpfr_set_flt(x1
, *xf1
, MPFR_RNDN
);
334 mpfr_set_flt(x2
, *xf2
, MPFR_RNDN
);
335 mpfr_set_flt(x3
, *xf3
, MPFR_RNDN
);
336 a
.f
.flt_flt_flt_rnd__flt(y
, x1
, x2
, x3
,
338 *yf
= mpfr_get_flt(y
, MPFR_RNDN
);
344 for (size_t j
= 0; j
< n
; ++j
) {
345 double *xf1
= (double *) (in_buf
+
347 double *xf2
= (double *) (in_buf
+
350 double *xf3
= (double *) (in_buf
+
353 double *yf
= (double *) (out_buf
+
356 mpfr_set_d(x1
, *xf1
, MPFR_RNDN
);
357 mpfr_set_d(x2
, *xf2
, MPFR_RNDN
);
358 mpfr_set_d(x3
, *xf3
, MPFR_RNDN
);
359 a
.f
.flt_flt_flt_rnd__flt(y
, x1
, x2
, x3
,
361 *yf
= mpfr_get_d(y
, MPFR_RNDN
);
368 case A__FLT_RND__FLT
:
373 for (size_t j
= 0; j
< n
; ++j
) {
374 float *xf1
= (float *) (in_buf
+
376 float *yf
= (float *) (out_buf
+
379 mpfr_set_flt(x1
, *xf1
, MPFR_RNDN
);
380 a
.f
.flt_rnd__flt(y
, x1
, MPFR_RNDN
);
381 *yf
= mpfr_get_flt(y
, MPFR_RNDN
);
387 for (size_t j
= 0; j
< n
; ++j
) {
388 double *xf1
= (double *) (in_buf
+
390 double *yf
= (double *) (out_buf
+
393 mpfr_set_d(x1
, *xf1
, MPFR_RNDN
);
394 a
.f
.flt_rnd__flt(y
, x1
, MPFR_RNDN
);
395 *yf
= mpfr_get_d(y
, MPFR_RNDN
);
404 write_buf(out_buf
, out_sz
* n
);
408 int main(int argc
, char **argv
)
411 action a
= { .p
= P_SINGLE
};
414 while ((c
= getopt(argc
, argv
, "sdf:n:")) != -1) {
423 determine_function(optarg
, &a
);
427 n
= strtoll(optarg
, 0, 0);
430 perror("impl-libc: unparsable");
442 if (a
.a
== A_UNKNOWN
) {