1 /*
2 * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17 /** \file
18 * \brief Implement legacy folding interfaces
19 *
20 * Implement the legacy compile-time evaluation library atop
21 * native host integer arithmetic, the floating-point
22 * folding package, and whatever 128-bit integer support
23 * has been supplied in int128.h.
24 *
25 * These interfaces date back to the days when IEEE-754 floating-point
26 * arithmetic was a novelty and cross-compilation was a common practice.
27 * They were formerly implemented with an IEEE-754 arithmetic emulation
28 * software package that had been translated into C from its original
29 * PDP-11 assembly language. These interfaces have been cleaned up
30 * to some degree, though more work remains to be done. This particular
31 * implementation is new, and comprises mostly conversions between
32 * the operand and result types of these legacy interfaces and those
33 * of the underlying integer and floating-point folding packages.
34 */
35
36 #include "legacy-folding-api.h"
37 #include "fp-folding.h"
38 #include "int128.h"
39 #include <assert.h>
40 #include <ctype.h>
41 #include <errno.h>
42 #include <inttypes.h>
43 #include <limits.h>
44 #include <math.h>
45 #include <stdbool.h>
46 #include <stdint.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <time.h>
51
52 static bool
is_host_little_endian(void)53 is_host_little_endian(void)
54 {
55 static const int one = 1;
56 return *(const char *) &one != 0;
57 }
58
59 /*
60 * Conversions between legacy scutil API types and the standard C
61 * fixed-size integer types and the types of the floating-point
62 * folding package.
63 *
64 * Pointer arguments are used here to enforce type safety and avoid
65 * silent conversions.
66 */
67
68 static void
unwrap_l(int64_t * x,const DBLINT64 y)69 unwrap_l(int64_t *x, const DBLINT64 y)
70 {
71 *x = (int64_t) y[0] << 32 | (int64_t) (uint32_t) y[1];
72 }
73
74 static void
unwrap_u(uint64_t * x,const DBLUINT64 y)75 unwrap_u(uint64_t *x, const DBLUINT64 y)
76 {
77 *x = (uint64_t) y[0] << 32 | (uint64_t) (uint32_t) y[1];
78 }
79
80 static void
wrap_l(DBLINT64 res,int64_t * x)81 wrap_l(DBLINT64 res, int64_t *x)
82 {
83 res[0] = *x >> 32; /* big end */
84 res[1] = *x;
85 }
86
87 static void
wrap_u(DBLUINT64 res,uint64_t * x)88 wrap_u(DBLUINT64 res, uint64_t *x)
89 {
90 res[0] = *x >> 32; /* big end */
91 res[1] = *x;
92 }
93
94 static void
unwrap_f(float32_t * f,IEEE32 * x)95 unwrap_f(float32_t *f, IEEE32 *x)
96 {
97 *f = *(float32_t *) x;
98 }
99
100 static void
wrap_f(IEEE32 * f,float32_t * x)101 wrap_f(IEEE32 *f, float32_t *x)
102 {
103 *f = *(IEEE32 *) x;
104 }
105
106 static void
unwrap_d(float64_t * x,const IEEE64 d)107 unwrap_d(float64_t *x, const IEEE64 d)
108 {
109 union {
110 float64_t x;
111 uint32_t i[2];
112 } u;
113 int le = is_host_little_endian();
114 u.i[le] = d[0]; /* big end */
115 u.i[le ^ 1] = d[1];
116 *x = u.x;
117 }
118
119 static void
wrap_d(IEEE64 res,const float64_t * x)120 wrap_d(IEEE64 res, const float64_t *x)
121 {
122 union {
123 float64_t d;
124 uint32_t i[2];
125 } u;
126 u.d = *x;
127 int le = is_host_little_endian();
128 res[0] = u.i[le]; /* big end */
129 res[1] = u.i[le ^ 1];
130 }
131
132 /*
133 * Legacy conversion interfaces
134 */
135
136 void
xdtomd(IEEE64 d,double * md)137 xdtomd(IEEE64 d, double *md)
138 {
139 unwrap_d(md, d);
140 }
141
142 void
xmdtod(double md,IEEE64 d)143 xmdtod(double md, IEEE64 d)
144 {
145 wrap_d(d, &md);
146 }
147
148 /*
149 * 64-bit integer operations
150 */
151
152 int
cmp64(DBLINT64 arg1,DBLINT64 arg2)153 cmp64(DBLINT64 arg1, DBLINT64 arg2)
154 {
155 int64_t y, z;
156 unwrap_l(&y, arg1);
157 unwrap_l(&z, arg2);
158 return y < z ? -1 : y > z;
159 }
160
161 int
ucmp64(DBLUINT64 arg1,DBLUINT64 arg2)162 ucmp64(DBLUINT64 arg1, DBLUINT64 arg2)
163 {
164 uint64_t y, z;
165 unwrap_u(&y, arg1);
166 unwrap_u(&z, arg2);
167 return y < z ? -1 : y > z;
168 }
169
170 void
add64(DBLINT64 arg1,DBLINT64 arg2,DBLINT64 result)171 add64(DBLINT64 arg1, DBLINT64 arg2, DBLINT64 result)
172 {
173 int64_t i1, i2, res;
174 unwrap_l(&i1, arg1);
175 unwrap_l(&i2, arg2);
176 res = i1 + i2;
177 wrap_l(result, &res);
178 }
179
180 void
div64(DBLINT64 arg1,DBLINT64 arg2,DBLINT64 result)181 div64(DBLINT64 arg1, DBLINT64 arg2, DBLINT64 result)
182 {
183 int64_t num, den, res;
184 unwrap_l(&num, arg1);
185 unwrap_l(&den, arg2);
186 res = den == 0 ? 0 : num / den;
187 wrap_l(result, &res);
188 }
189
190 void
exp64(DBLINT64 arg,INT exp,DBLINT64 result)191 exp64(DBLINT64 arg, INT exp, DBLINT64 result)
192 {
193 int64_t base, x = exp >= 0;
194 unwrap_l(&base, arg);
195 while (exp-- > 0)
196 x *= base;
197 wrap_l(result, &x);
198 }
199
200 void
mul64(DBLINT64 arg1,DBLINT64 arg2,DBLINT64 result)201 mul64(DBLINT64 arg1, DBLINT64 arg2, DBLINT64 result)
202 {
203 int64_t i1, i2, res;
204 unwrap_l(&i1, arg1);
205 unwrap_l(&i2, arg2);
206 res = i1 * i2;
207 wrap_l(result, &res);
208 }
209
210 void
mul64_10(DBLINT64 arg,DBLINT64 result)211 mul64_10(DBLINT64 arg, DBLINT64 result)
212 {
213 int64_t i;
214 unwrap_l(&i, arg);
215 i *= 10;
216 wrap_l(result, &i);
217 }
218
219 void
neg64(DBLINT64 arg,DBLINT64 result)220 neg64(DBLINT64 arg, DBLINT64 result)
221 {
222 int64_t i;
223 unwrap_l(&i, arg);
224 i = -i;
225 wrap_l(result, &i);
226 }
227
228 void
shf64(DBLINT64 arg,int count,DBLINT64 result)229 shf64(DBLINT64 arg, int count, DBLINT64 result)
230 {
231 int64_t x;
232 unwrap_l(&x, arg);
233 if (count < -63 || count > 63)
234 x = 0;
235 else if (count <= 0)
236 x >>= -count;
237 else
238 x <<= count;
239 wrap_l(result, &x);
240 }
241
242 void
sub64(DBLINT64 arg1,DBLINT64 arg2,DBLINT64 result)243 sub64(DBLINT64 arg1, DBLINT64 arg2, DBLINT64 result)
244 {
245 int64_t i1, i2, res;
246 unwrap_l(&i1, arg1);
247 unwrap_l(&i2, arg2);
248 res = i1 - i2;
249 wrap_l(result, &res);
250 }
251
252 void
uadd64(DBLUINT64 arg1,DBLUINT64 arg2,DBLUINT64 result)253 uadd64(DBLUINT64 arg1, DBLUINT64 arg2, DBLUINT64 result)
254 {
255 uint64_t u1, u2, res;
256 unwrap_u(&u1, arg1);
257 unwrap_u(&u2, arg2);
258 res = u1 + u2;
259 wrap_u(result, &res);
260 }
261
262 void
uneg64(DBLUINT64 arg,DBLUINT64 result)263 uneg64(DBLUINT64 arg, DBLUINT64 result)
264 {
265 uint64_t u;
266 unwrap_u(&u, arg);
267 u = -u;
268 wrap_u(result, &u);
269 }
270
271 void
ushf64(DBLUINT64 arg,int count,DBLUINT64 result)272 ushf64(DBLUINT64 arg, int count, DBLUINT64 result)
273 {
274 uint64_t u;
275 unwrap_u(&u, arg);
276 if (count < -63 || count > 63)
277 u = 0;
278 else if (count <= 0)
279 u >>= -count;
280 else
281 u <<= count;
282 wrap_u(result, &u);
283 }
284
285 void
usub64(DBLUINT64 arg1,DBLUINT64 arg2,DBLUINT64 result)286 usub64(DBLUINT64 arg1, DBLUINT64 arg2, DBLUINT64 result)
287 {
288 uint64_t u1, u2, res;
289 unwrap_u(&u1, arg1);
290 unwrap_u(&u2, arg2);
291 res = u1 - u2;
292 wrap_u(result, &res);
293 }
294
295 void
udiv64(DBLUINT64 arg1,DBLUINT64 arg2,DBLUINT64 result)296 udiv64(DBLUINT64 arg1, DBLUINT64 arg2, DBLUINT64 result)
297 {
298 uint64_t num, den, res;
299 unwrap_u(&num, arg1);
300 unwrap_u(&den, arg2);
301 res = den == 0 ? 0 : num / den;
302 wrap_u(result, &res);
303 }
304
305 void
umul64(DBLUINT64 arg1,DBLUINT64 arg2,DBLUINT64 result)306 umul64(DBLUINT64 arg1, DBLUINT64 arg2, DBLUINT64 result)
307 {
308 uint64_t u1, u2, res;
309 unwrap_u(&u1, arg1);
310 unwrap_u(&u2, arg2);
311 res = u1 * u2;
312 wrap_u(result, &res);
313 }
314
315 void
umul64_10(DBLUINT64 arg,DBLUINT64 result)316 umul64_10(DBLUINT64 arg, DBLUINT64 result)
317 {
318 uint64_t u;
319 unwrap_u(&u, arg);
320 u *= 10;
321 wrap_u(result, &u);
322 }
323
324 void
and64(DBLINT64 arg1,DBLINT64 arg2,DBLINT64 result)325 and64(DBLINT64 arg1, DBLINT64 arg2, DBLINT64 result)
326 {
327 int64_t i1, i2, res;
328 unwrap_l(&i1, arg1);
329 unwrap_l(&i2, arg2);
330 res = i1 & i2;
331 wrap_l(result, &res);
332 }
333
334 void
not64(DBLINT64 arg,DBLINT64 result)335 not64(DBLINT64 arg, DBLINT64 result)
336 {
337 int64_t i;
338 unwrap_l(&i, arg);
339 i = ~i;
340 wrap_l(result, &i);
341 }
342
343 void
or64(DBLINT64 arg1,DBLINT64 arg2,DBLINT64 result)344 or64(DBLINT64 arg1, DBLINT64 arg2, DBLINT64 result)
345 {
346 int64_t i1, i2, res;
347 unwrap_l(&i1, arg1);
348 unwrap_l(&i2, arg2);
349 res = i1 | i2;
350 wrap_l(result, &res);
351 }
352
353 void
xor64(DBLINT64 arg1,DBLINT64 arg2,DBLINT64 result)354 xor64(DBLINT64 arg1, DBLINT64 arg2, DBLINT64 result)
355 {
356 int64_t i1, i2, res;
357 unwrap_l(&i1, arg1);
358 unwrap_l(&i2, arg2);
359 res = i1 ^ i2;
360 wrap_l(result, &res);
361 }
362
363 void
ui64toax(DBLINT64 from,char * to,int size,int is_unsigned,int radix)364 ui64toax(DBLINT64 from, char *to, int size, int is_unsigned, int radix)
365 {
366 int64_t x;
367 unwrap_l(&x, from);
368 if (!is_unsigned && x < 0) {
369 *to++ = '-';
370 --size;
371 x = -x;
372 }
373 switch (radix) {
374 case 8:
375 snprintf(to, size, "%" PRIo64, x);
376 break;
377 case 10:
378 snprintf(to, size, "%" PRIu64, x);
379 break;
380 case 16:
381 snprintf(to, size, "%" PRIx64, x);
382 break;
383 default:
384 assert(!"bad radix");
385 }
386 }
387
388 /*
389 * 128-bit integer routines
390 *
391 * Note: if GCC >= 4.8 were guaranteed to be available, its
392 * built-in __int128 type could be used here explicitly.
393 * For flexibility, the wrapper API in int128.h is used.
394 */
395
396 static void
unwrap_i128(int128_t * result,const INT128 i)397 unwrap_i128(int128_t *result, const INT128 i /* big-endian */)
398 {
399 int j;
400 int128_from_int64(result, 0);
401 for (j = 0; j < 4; ++j) {
402 int128_t part, shifted;
403 int128_from_uint64(&part, (uint32_t) i[j ^ 3]);
404 int128_shift_left(&shifted, &part, 32 * j);
405 int128_or(result, result, &shifted);
406 }
407 }
408
409 static void
wrap_i128(INT128 i,const int128_t * x)410 wrap_i128(INT128 i, const int128_t *x)
411 {
412 int j;
413 for (j = 0; j < 4; ++j) {
414 int128_t t;
415 int64_t least;
416 int128_shift_right_logical(&t, x, 32 * j);
417 int128_to_int64(&least, &t);
418 i[j ^ 3] = least;
419 }
420 }
421
422 void
shf128(INT128 arg,int count,INT128 result)423 shf128(INT128 arg, int count, INT128 result)
424 {
425 int128_t x, res;
426 unwrap_i128(&x, arg);
427 if (count < 0) {
428 /* negative count means right shift */
429 int128_shift_right_logical(&res, &x, -count);
430 } else {
431 int128_shift_left(&res, &x, count);
432 }
433 wrap_i128(result, &res);
434 }
435
436 void
add128(INT128 arg1,INT128 arg2,INT128 result)437 add128(INT128 arg1, INT128 arg2, INT128 result)
438 {
439 int128_t x, y, z;
440 unwrap_i128(&x, arg1);
441 unwrap_i128(&y, arg2);
442 int128_unsigned_add(&z, &x, &y);
443 wrap_i128(result, &z);
444 }
445
446 void
sub128(INT128 arg1,INT128 arg2,INT128 result)447 sub128(INT128 arg1, INT128 arg2, INT128 result)
448 {
449 int128_t x, y, z;
450 unwrap_i128(&x, arg1);
451 unwrap_i128(&y, arg2);
452 int128_signed_subtract(&z, &x, &y);
453 wrap_i128(result, &z);
454 }
455
456 int
cmp128(INT128 arg1,INT128 arg2)457 cmp128(INT128 arg1, INT128 arg2)
458 {
459 int128_t x, y;
460 unwrap_i128(&x, arg1);
461 unwrap_i128(&y, arg2);
462 return int128_signed_compare(&x, &y);
463 }
464
465 /* omitted: ucmp128, mul256, negN, shfN et al. */
466
467 void
mul128l(INT128 arg1,INT128 arg2,INT128 result)468 mul128l(INT128 arg1, INT128 arg2, INT128 result)
469 {
470 int128_t x, y, high, low;
471 unwrap_i128(&x, arg1);
472 unwrap_i128(&y, arg2);
473 int128_signed_multiply(&high, &low, &x, &y);
474 wrap_i128(result, &low);
475 }
476
477 void
div128(INT128 arg1,INT128 arg2,INT128 result)478 div128(INT128 arg1, INT128 arg2, INT128 result)
479 {
480 int128_t x, y, quotient, remainder;
481 unwrap_i128(&x, arg1);
482 unwrap_i128(&y, arg2);
483 int128_signed_divide("ient, &remainder, &x, &y);
484 wrap_i128(result, "ient);
485 }
486
487 /*
488 * 32-bit floating-point
489 */
490
491 /* Check any error result from a fold_... routine and pass it on to
492 * the user's fperror() if needed.
493 */
494 static void
check(enum fold_status status)495 check(enum fold_status status)
496 {
497 switch (status) {
498 case FOLD_OK:
499 case FOLD_INEXACT:
500 break;
501 case FOLD_INVALID:
502 fperror(FPE_INVOP);
503 break;
504 case FOLD_OVERFLOW:
505 fperror(FPE_FPOVF);
506 break;
507 case FOLD_UNDERFLOW:
508 fperror(FPE_FPUNF);
509 break;
510 default:
511 assert(!"scutil-api.c:check:unknown status");
512 }
513 }
514
515 void
xfix(IEEE32 f,INT * i)516 xfix(IEEE32 f, INT *i)
517 {
518 float32_t x;
519 unwrap_f(&x, &f);
520 check(fold_int32_from_real32(i, &x));
521 }
522
523 void
xfixu(IEEE32 f,UINT * u)524 xfixu(IEEE32 f, UINT *u)
525 {
526 float32_t x;
527 unwrap_f(&x, &f);
528 check(fold_uint32_from_real32(u, &x));
529 }
530
531 void
xffixu(IEEE32 f,UINT * u)532 xffixu(IEEE32 f, UINT *u)
533 {
534 xfixu(f, u); /* are both xfixu and xffixu actually used? */
535 }
536
537 void
xfix64(IEEE32 f,DBLINT64 l)538 xfix64(IEEE32 f, DBLINT64 l)
539 {
540 int64_t x;
541 float32_t y;
542 unwrap_f(&y, &f);
543 check(fold_int64_from_real32(&x, &y));
544 wrap_l(l, &x);
545 }
546
547 void
xfixu64(IEEE32 f,DBLUINT64 u)548 xfixu64(IEEE32 f, DBLUINT64 u)
549 {
550 int64_t x;
551 float32_t y;
552 uint64_t xu;
553 unwrap_f(&y, &f);
554 check(fold_int64_from_real32(&x, &y));
555 xu = x;
556 wrap_u(u, &xu);
557 }
558
559 void
xffloat(INT i,IEEE32 * f)560 xffloat(INT i, IEEE32 *f)
561 {
562 float32_t x;
563 int64_t li = i;
564 check(fold_real32_from_int64(&x, &li));
565 wrap_f(f, &x);
566 }
567
568 void
xffloatu(UINT u,IEEE32 * f)569 xffloatu(UINT u, IEEE32 *f)
570 {
571 float32_t x;
572 int64_t li = u;
573 check(fold_real32_from_int64(&x, &li));
574 wrap_f(f, &x);
575 }
576
577 void
xflt64(DBLINT64 l,IEEE32 * f)578 xflt64(DBLINT64 l, IEEE32 *f)
579 {
580 float32_t x;
581 int64_t y;
582 unwrap_l(&y, l);
583 check(fold_real32_from_int64(&x, &y));
584 wrap_f(f, &x);
585 }
586
587 void
xfltu64(DBLUINT64 u,IEEE32 * f)588 xfltu64(DBLUINT64 u, IEEE32 *f)
589 {
590 float32_t x;
591 uint64_t y;
592 unwrap_u(&y, u);
593 check(fold_real32_from_uint64(&x, &y));
594 wrap_f(f, &x);
595 }
596
597 void
xfadd(IEEE32 f1,IEEE32 f2,IEEE32 * r)598 xfadd(IEEE32 f1, IEEE32 f2, IEEE32 *r)
599 {
600 float32_t x, y, z;
601 unwrap_f(&y, &f1);
602 unwrap_f(&z, &f2);
603 check(fold_real32_add(&x, &y, &z));
604 wrap_f(r, &x);
605 }
606
607 void
xfsub(IEEE32 f1,IEEE32 f2,IEEE32 * r)608 xfsub(IEEE32 f1, IEEE32 f2, IEEE32 *r)
609 {
610 float32_t x, y, z;
611 unwrap_f(&y, &f1);
612 unwrap_f(&z, &f2);
613 check(fold_real32_subtract(&x, &y, &z));
614 wrap_f(r, &x);
615 }
616
617 void
xfneg(IEEE32 f,IEEE32 * r)618 xfneg(IEEE32 f, IEEE32 *r)
619 {
620 float32_t x, y;
621 unwrap_f(&y, &f);
622 check(fold_real32_negate(&x, &y));
623 wrap_f(r, &x);
624 }
625
626 void
xfmul(IEEE32 f1,IEEE32 f2,IEEE32 * r)627 xfmul(IEEE32 f1, IEEE32 f2, IEEE32 *r)
628 {
629 float32_t x, y, z;
630 unwrap_f(&y, &f1);
631 unwrap_f(&z, &f2);
632 check(fold_real32_multiply(&x, &y, &z));
633 wrap_f(r, &x);
634 }
635
636 void
xfdiv(IEEE32 f1,IEEE32 f2,IEEE32 * r)637 xfdiv(IEEE32 f1, IEEE32 f2, IEEE32 *r)
638 {
639 float32_t x, y, z;
640 unwrap_f(&y, &f1);
641 unwrap_f(&z, &f2);
642 check(fold_real32_divide(&x, &y, &z));
643 wrap_f(r, &x);
644 }
645
646 void
xfrcp(IEEE32 f,IEEE32 * r)647 xfrcp(IEEE32 f, IEEE32 *r)
648 {
649 float32_t x, one, y;
650 int64_t ione = 1;
651 check(fold_real32_from_int64(&one, &ione));
652 unwrap_f(&y, &f);
653 check(fold_real32_divide(&x, &one, &y));
654 wrap_f(r, &x);
655 }
656
657 void
xfabsv(IEEE32 f,IEEE32 * r)658 xfabsv(IEEE32 f, IEEE32 *r)
659 {
660 float32_t x, y;
661 unwrap_f(&y, &f);
662 check(fold_real32_abs(&x, &y));
663 wrap_f(r, &x);
664 }
665
666 void
xfsqrt(IEEE32 f,IEEE32 * r)667 xfsqrt(IEEE32 f, IEEE32 *r)
668 {
669 float32_t x, y;
670 unwrap_f(&y, &f);
671 check(fold_real32_sqrt(&x, &y));
672 wrap_f(r, &x);
673 }
674
675 void
xfpow(IEEE32 f1,IEEE32 f2,IEEE32 * r)676 xfpow(IEEE32 f1, IEEE32 f2, IEEE32 *r)
677 {
678 float32_t x, y, z;
679 unwrap_f(&y, &f1);
680 unwrap_f(&z, &f2);
681 check(fold_real32_pow(&x, &y, &z));
682 wrap_f(r, &x);
683 }
684
685 void
xfsin(IEEE32 f,IEEE32 * r)686 xfsin(IEEE32 f, IEEE32 *r)
687 {
688 float32_t x, y;
689 unwrap_f(&y, &f);
690 check(fold_real32_sin(&x, &y));
691 wrap_f(r, &x);
692 }
693
694 void
xfcos(IEEE32 f,IEEE32 * r)695 xfcos(IEEE32 f, IEEE32 *r)
696 {
697 float32_t x, y;
698 unwrap_f(&y, &f);
699 check(fold_real32_cos(&x, &y));
700 wrap_f(r, &x);
701 }
702
703 void
xftan(IEEE32 f,IEEE32 * r)704 xftan(IEEE32 f, IEEE32 *r)
705 {
706 float32_t x, y;
707 unwrap_f(&y, &f);
708 check(fold_real32_tan(&x, &y));
709 wrap_f(r, &x);
710 }
711
712 void
xfasin(IEEE32 f,IEEE32 * r)713 xfasin(IEEE32 f, IEEE32 *r)
714 {
715 float32_t x, y;
716 unwrap_f(&y, &f);
717 check(fold_real32_asin(&x, &y));
718 wrap_f(r, &x);
719 }
720
721 void
xfacos(IEEE32 f,IEEE32 * r)722 xfacos(IEEE32 f, IEEE32 *r)
723 {
724 float32_t x, y;
725 unwrap_f(&y, &f);
726 check(fold_real32_acos(&x, &y));
727 wrap_f(r, &x);
728 }
729
730 void
xfatan(IEEE32 f,IEEE32 * r)731 xfatan(IEEE32 f, IEEE32 *r)
732 {
733 float32_t x, y;
734 unwrap_f(&y, &f);
735 check(fold_real32_atan(&x, &y));
736 wrap_f(r, &x);
737 }
738
739 void
xfatan2(IEEE32 f1,IEEE32 f2,IEEE32 * r)740 xfatan2(IEEE32 f1, IEEE32 f2, IEEE32 *r)
741 {
742 float32_t x, y, z;
743 unwrap_f(&y, &f1);
744 unwrap_f(&z, &f2);
745 check(fold_real32_atan2(&x, &y, &z));
746 wrap_f(r, &x);
747 }
748
749 void
xfexp(IEEE32 f,IEEE32 * r)750 xfexp(IEEE32 f, IEEE32 *r)
751 {
752 float32_t x, y;
753 unwrap_f(&y, &f);
754 check(fold_real32_exp(&x, &y));
755 wrap_f(r, &x);
756 }
757
758 void
xflog(IEEE32 f,IEEE32 * r)759 xflog(IEEE32 f, IEEE32 *r)
760 {
761 float32_t x, y;
762 unwrap_f(&y, &f);
763 check(fold_real32_log(&x, &y));
764 wrap_f(r, &x);
765 }
766
767 void
xflog10(IEEE32 f,IEEE32 * r)768 xflog10(IEEE32 f, IEEE32 *r)
769 {
770 float32_t x, y;
771 unwrap_f(&y, &f);
772 check(fold_real32_log10(&x, &y));
773 wrap_f(r, &x);
774 }
775
776 int
xfcmp(IEEE32 f1,IEEE32 f2)777 xfcmp(IEEE32 f1, IEEE32 f2)
778 {
779 float32_t y, z;
780 unwrap_f(&y, &f1);
781 unwrap_f(&z, &f2);
782 return fold_real32_compare(&y, &z);
783 }
784
785 int
xfisint(IEEE32 f,int * i)786 xfisint(IEEE32 f, int *i)
787 {
788 float32_t x, y;
789 int64_t k;
790 unwrap_f(&x, &f);
791 check(fold_int32_from_real32(i, &x));
792 k = *i;
793 check(fold_real32_from_int64(&y, &k));
794 return fold_real32_compare(&x, &y) == FOLD_EQ;
795 }
796
797 /*
798 * Copy a floating-point literal into a null-terminated buffer
799 * so that it may be passed to strtod() et al. Insert a leading "0x"
800 * after the sign, if requested; also transform a Fortran double-precision
801 * exponent character 'd'/'D' into 'e'.
802 */
803 static void
get_literal(char * buffer,size_t length,const char * s,int n,bool is_hex)804 get_literal(char *buffer, size_t length, const char *s, int n, bool is_hex)
805 {
806 char *p = buffer;
807 assert(length > 0);
808 while (n > 0 && isspace(*s)) {
809 ++s;
810 --n;
811 }
812 if (n > 0 && (*s == '-' || *s == '+') && length > 1) {
813 *p++ = *s++;
814 --n;
815 --length;
816 }
817 if (is_hex && length > 3) {
818 *p++ = '0';
819 *p++ = 'x';
820 length -= 2;
821 }
822 while (n > 0 && *s && length > 1) {
823 char ch = *s++;
824 --n;
825 if (!is_hex && (ch == 'd' || ch == 'D'))
826 ch = 'e';
827 *p++ = ch;
828 --length;
829 }
830 *p = '\0';
831 }
832
833 static int
handle_parsing_errors(const char * buffer,const char * end,int errno_capture,bool iszero)834 handle_parsing_errors(const char *buffer, const char *end,
835 int errno_capture, bool iszero) {
836 if (end != buffer + strlen(buffer))
837 return -1; /* format error */
838 /* The only error value documented for strtod() is ERANGE,
839 * but let's be defensive and produce at least a warning
840 * if some other error condition was raised.
841 */
842 if (errno_capture == ERANGE && iszero)
843 return iszero ? -3 /* underflow */ : -2 /* overflow */;
844 return errno_capture == 0 ? 0 : -2 /* overflow */;
845 }
846
847 static int
parse_f(const char * s,IEEE32 * f,int n,bool is_hex)848 parse_f(const char *s, IEEE32 *f, int n, bool is_hex)
849 {
850 float32_t x;
851 char buffer[256], *end;
852 int errno_capture;
853 get_literal(buffer, sizeof buffer, s, n, is_hex);
854 errno = 0;
855 x = strtof(buffer, &end);
856 errno_capture = errno;
857 wrap_f(f, &x);
858 return handle_parsing_errors(buffer, end, errno_capture, x == 0);
859 }
860
861 int
atoxf(const char * s,IEEE32 * f,int n)862 atoxf(const char *s, IEEE32 *f, int n)
863 {
864 return parse_f(s, f, n, false);
865 }
866
867 int
hxatoxf(const char * s,IEEE32 * f,int n)868 hxatoxf(const char *s, IEEE32 *f, int n)
869 {
870 return parse_f(s, f, n, true);
871 }
872
873 /*
874 * 64-bit floating-point
875 */
876
877 void
xdfix(IEEE64 d,INT * i)878 xdfix(IEEE64 d, INT *i)
879 {
880 float64_t x;
881 unwrap_d(&x, d);
882 check(fold_int32_from_real64(i, &x));
883 }
884
885 void
xdfixu(IEEE64 d,UINT * u)886 xdfixu(IEEE64 d, UINT *u)
887 {
888 float64_t x;
889 unwrap_d(&x, d);
890 check(fold_uint32_from_real64(u, &x));
891 }
892
893 void
xdfix64(IEEE64 d,DBLINT64 l)894 xdfix64(IEEE64 d, DBLINT64 l)
895 {
896 int64_t x;
897 float64_t y;
898 unwrap_d(&y, d);
899 check(fold_int64_from_real64(&x, &y));
900 wrap_l(l, &x);
901 }
902
903 void
xdfixu64(IEEE64 d,DBLUINT64 u)904 xdfixu64(IEEE64 d, DBLUINT64 u)
905 {
906 int64_t x;
907 float64_t y;
908 uint64_t xu;
909 unwrap_d(&y, d);
910 check(fold_int64_from_real64(&x, &y));
911 xu = x;
912 wrap_u(u, &xu);
913 }
914
915 void
xdfloat(INT i,IEEE64 d)916 xdfloat(INT i, IEEE64 d)
917 {
918 float64_t x;
919 int64_t li = i;
920 check(fold_real64_from_int64(&x, &li));
921 wrap_d(d, &x);
922 }
923
924 void
xdfloatu(UINT u,IEEE64 d)925 xdfloatu(UINT u, IEEE64 d)
926 {
927 float64_t x;
928 int64_t li = u;
929 check(fold_real64_from_int64(&x, &li));
930 wrap_d(d, &x);
931 }
932
933 void
xdflt64(DBLINT64 l,IEEE64 d)934 xdflt64(DBLINT64 l, IEEE64 d)
935 {
936 float64_t x;
937 int64_t y;
938 unwrap_l(&y, l);
939 check(fold_real64_from_int64(&x, &y));
940 wrap_d(d, &x);
941 }
942
943 void
xdfltu64(DBLUINT64 u,IEEE64 d)944 xdfltu64(DBLUINT64 u, IEEE64 d)
945 {
946 uint64_t y;
947 float64_t x;
948 unwrap_u(&y, u);
949 check(fold_real64_from_uint64(&x, &y));
950 wrap_d(d, &x);
951 }
952
953 void
xdble(IEEE32 f,IEEE64 r)954 xdble(IEEE32 f, IEEE64 r)
955 {
956 float64_t x;
957 float32_t y;
958 unwrap_f(&y, &f);
959 check(fold_real64_from_real32(&x, &y));
960 wrap_d(r, &x);
961 }
962
963 void
xsngl(IEEE64 d,IEEE32 * r)964 xsngl(IEEE64 d, IEEE32 *r)
965 {
966 float32_t x;
967 float64_t y;
968 unwrap_d(&y, d);
969 check(fold_real32_from_real64(&x, &y));
970 wrap_f(r, &x);
971 }
972
973 void
xdadd(IEEE64 d1,IEEE64 d2,IEEE64 r)974 xdadd(IEEE64 d1, IEEE64 d2, IEEE64 r)
975 {
976 float64_t x, y, z;
977 unwrap_d(&y, d1);
978 unwrap_d(&z, d2);
979 check(fold_real64_add(&x, &y, &z));
980 wrap_d(r, &x);
981 }
982
983 void
xdsub(IEEE64 d1,IEEE64 d2,IEEE64 r)984 xdsub(IEEE64 d1, IEEE64 d2, IEEE64 r)
985 {
986 float64_t x, y, z;
987 unwrap_d(&y, d1);
988 unwrap_d(&z, d2);
989 check(fold_real64_subtract(&x, &y, &z));
990 wrap_d(r, &x);
991 }
992
993 void
xdneg(IEEE64 d,IEEE64 r)994 xdneg(IEEE64 d, IEEE64 r)
995 {
996 float64_t x, y;
997 unwrap_d(&y, d);
998 check(fold_real64_negate(&x, &y));
999 wrap_d(r, &x);
1000 }
1001
1002 void
xdmul(IEEE64 d1,IEEE64 d2,IEEE64 r)1003 xdmul(IEEE64 d1, IEEE64 d2, IEEE64 r)
1004 {
1005 float64_t x, y, z;
1006 unwrap_d(&y, d1);
1007 unwrap_d(&z, d2);
1008 check(fold_real64_multiply(&x, &y, &z));
1009 wrap_d(r, &x);
1010 }
1011
1012 void
xddiv(IEEE64 d1,IEEE64 d2,IEEE64 r)1013 xddiv(IEEE64 d1, IEEE64 d2, IEEE64 r)
1014 {
1015 float64_t x, y, z;
1016 unwrap_d(&y, d1);
1017 unwrap_d(&z, d2);
1018 check(fold_real64_divide(&x, &y, &z));
1019 wrap_d(r, &x);
1020 }
1021
1022 void
xdrcp(IEEE64 d,IEEE64 r)1023 xdrcp(IEEE64 d, IEEE64 r)
1024 {
1025 float64_t x, one, y;
1026 int64_t ione = 1;
1027 unwrap_d(&y, d);
1028 check(fold_real64_from_int64(&one, &ione));
1029 check(fold_real64_divide(&x, &one, &y));
1030 wrap_d(r, &x);
1031 }
1032
1033 void
xdabsv(IEEE64 d,IEEE64 r)1034 xdabsv(IEEE64 d, IEEE64 r)
1035 {
1036 float64_t x, y;
1037 unwrap_d(&y, d);
1038 check(fold_real64_abs(&x, &y));
1039 wrap_d(r, &x);
1040 }
1041
1042 void
xdsqrt(IEEE64 d,IEEE64 r)1043 xdsqrt(IEEE64 d, IEEE64 r)
1044 {
1045 float64_t x, y;
1046 unwrap_d(&y, d);
1047 check(fold_real64_sqrt(&x, &y));
1048 wrap_d(r, &x);
1049 }
1050
1051 void
xdpow(IEEE64 d1,IEEE64 d2,IEEE64 r)1052 xdpow(IEEE64 d1, IEEE64 d2, IEEE64 r)
1053 {
1054 float64_t x, y, z;
1055 unwrap_d(&y, d1);
1056 unwrap_d(&z, d2);
1057 check(fold_real64_pow(&x, &y, &z));
1058 wrap_d(r, &x);
1059 }
1060
1061 void
xdsin(IEEE64 d,IEEE64 r)1062 xdsin(IEEE64 d, IEEE64 r)
1063 {
1064 float64_t x, y;
1065 unwrap_d(&y, d);
1066 check(fold_real64_sin(&x, &y));
1067 wrap_d(r, &x);
1068 }
1069
1070 void
xdcos(IEEE64 d,IEEE64 r)1071 xdcos(IEEE64 d, IEEE64 r)
1072 {
1073 float64_t x, y;
1074 unwrap_d(&y, d);
1075 check(fold_real64_cos(&x, &y));
1076 wrap_d(r, &x);
1077 }
1078
1079 void
xdtan(IEEE64 d,IEEE64 r)1080 xdtan(IEEE64 d, IEEE64 r)
1081 {
1082 float64_t x, y;
1083 unwrap_d(&y, d);
1084 check(fold_real64_tan(&x, &y));
1085 wrap_d(r, &x);
1086 }
1087
1088 void
xdasin(IEEE64 d,IEEE64 r)1089 xdasin(IEEE64 d, IEEE64 r)
1090 {
1091 float64_t x, y;
1092 unwrap_d(&y, d);
1093 check(fold_real64_asin(&x, &y));
1094 wrap_d(r, &x);
1095 }
1096
1097 void
xdacos(IEEE64 d,IEEE64 r)1098 xdacos(IEEE64 d, IEEE64 r)
1099 {
1100 float64_t x, y;
1101 unwrap_d(&y, d);
1102 check(fold_real64_acos(&x, &y));
1103 wrap_d(r, &x);
1104 }
1105
1106 void
xdatan(IEEE64 d,IEEE64 r)1107 xdatan(IEEE64 d, IEEE64 r)
1108 {
1109 float64_t x, y;
1110 unwrap_d(&y, d);
1111 check(fold_real64_atan(&x, &y));
1112 wrap_d(r, &x);
1113 }
1114
1115 void
xdatan2(IEEE64 d1,IEEE64 d2,IEEE64 r)1116 xdatan2(IEEE64 d1, IEEE64 d2, IEEE64 r)
1117 {
1118 float64_t x, y, z;
1119 unwrap_d(&y, d1);
1120 unwrap_d(&z, d2);
1121 check(fold_real64_atan2(&x, &y, &z));
1122 wrap_d(r, &x);
1123 }
1124
1125 void
xdexp(IEEE64 d,IEEE64 r)1126 xdexp(IEEE64 d, IEEE64 r)
1127 {
1128 float64_t x, y;
1129 unwrap_d(&y, d);
1130 check(fold_real64_exp(&x, &y));
1131 wrap_d(r, &x);
1132 }
1133
1134 void
xdlog(IEEE64 d,IEEE64 r)1135 xdlog(IEEE64 d, IEEE64 r)
1136 {
1137 float64_t x, y;
1138 unwrap_d(&y, d);
1139 check(fold_real64_log(&x, &y));
1140 wrap_d(r, &x);
1141 }
1142
1143 void
xdlog10(IEEE64 d,IEEE64 r)1144 xdlog10(IEEE64 d, IEEE64 r)
1145 {
1146 float64_t x, y;
1147 unwrap_d(&y, d);
1148 check(fold_real64_log10(&x, &y));
1149 wrap_d(r, &x);
1150 }
1151
1152 int
xdcmp(IEEE64 d1,IEEE64 d2)1153 xdcmp(IEEE64 d1, IEEE64 d2)
1154 {
1155 float64_t y, z;
1156 unwrap_d(&y, d1);
1157 unwrap_d(&z, d2);
1158 return fold_real64_compare(&y, &z);
1159 }
1160
1161 int
xdisint(IEEE64 d,int * i)1162 xdisint(IEEE64 d, int *i)
1163 {
1164 float64_t x, y;
1165 int64_t k;
1166 unwrap_d(&x, d);
1167 check(fold_int32_from_real64(i, &x));
1168 k = *i;
1169 check(fold_real64_from_int64(&y, &k));
1170 return fold_real64_compare(&x, &y) == FOLD_EQ;
1171 }
1172
1173 static int
parse_d(const char * s,IEEE64 d,int n,bool is_hex)1174 parse_d(const char *s, IEEE64 d, int n, bool is_hex)
1175 {
1176 float64_t x;
1177 char buffer[256], *end;
1178 int errno_capture;
1179 get_literal(buffer, sizeof buffer, s, n, is_hex);
1180 errno = 0;
1181 x = strtod(buffer, &end);
1182 errno_capture = errno;
1183 wrap_d(d, &x);
1184 return handle_parsing_errors(buffer, end, errno_capture, x == 0);
1185 }
1186
1187 int
atoxd(const char * s,IEEE64 d,int n)1188 atoxd(const char *s, IEEE64 d, int n)
1189 {
1190 return parse_d(s, d, n, false);
1191 }
1192
1193 int
hxatoxd(const char * s,IEEE64 d,int n)1194 hxatoxd(const char *s, IEEE64 d, int n)
1195 {
1196 return parse_d(s, d, n, true);
1197 }
1198
1199 #ifdef FOLD_LDBL_X87
1200 static void
unwrap_e(float128_t * x,IEEE80 e)1201 unwrap_e(float128_t *x, IEEE80 e)
1202 {
1203 union {
1204 float128_t x;
1205 uint32_t i[3];
1206 } u;
1207 assert(is_host_little_endian());
1208 u.i[2] = (uint32_t) e[0] >> 16; /* big end */
1209 u.i[1] = (e[0] << 16) | ((uint32_t) e[1] >> 16);
1210 u.i[0] = (e[1] << 16) | ((uint32_t) e[2] >> 16);
1211 *x = u.x;
1212 }
1213
1214 static void
wrap_e(IEEE80 res,float128_t * x)1215 wrap_e(IEEE80 res, float128_t *x)
1216 {
1217 union {
1218 float128_t e;
1219 uint32_t i[3];
1220 } u;
1221 assert(is_host_little_endian());
1222 u.e = *x;
1223 res[0] = (u.i[2] << 16) | (u.i[1] >> 16); /* big end */
1224 res[1] = (u.i[1] << 16) | (u.i[0] >> 16);
1225 res[2] = u.i[0] << 16;
1226 }
1227
1228 void
xefix(IEEE80 e,INT * i)1229 xefix(IEEE80 e, INT *i)
1230 {
1231 float128_t x;
1232 unwrap_e(&x, e);
1233 check(fold_int32_from_real128(i, &x));
1234 }
1235
1236 void
xefixu(IEEE80 e,UINT * u)1237 xefixu(IEEE80 e, UINT *u)
1238 {
1239 float128_t x;
1240 unwrap_e(&x, e);
1241 check(fold_uint32_from_real128(u, &x));
1242 }
1243
1244 void
xefix64(IEEE80 e,DBLINT64 l)1245 xefix64(IEEE80 e, DBLINT64 l)
1246 {
1247 int64_t x;
1248 float128_t y;
1249 unwrap_e(&y, e);
1250 check(fold_int64_from_real128(&x, &y));
1251 wrap_l(l, &x);
1252 }
1253
1254 void
xefixu64(IEEE80 e,DBLUINT64 u)1255 xefixu64(IEEE80 e, DBLUINT64 u)
1256 {
1257 uint64_t x;
1258 float128_t y;
1259 unwrap_e(&y, e);
1260 check(fold_uint64_from_real128(&x, &y));
1261 wrap_u(u, &x);
1262 }
1263
1264 void
xefloat(INT i,IEEE80 e)1265 xefloat(INT i, IEEE80 e)
1266 {
1267 float128_t x;
1268 int64_t li = i;
1269 check(fold_real128_from_int64(&x, &li));
1270 wrap_e(e, &x);
1271 }
1272
1273 void
xefloatu(UINT u,IEEE80 e)1274 xefloatu(UINT u, IEEE80 e)
1275 {
1276 float128_t x;
1277 int64_t i = u;
1278 check(fold_real128_from_int64(&x, &i));
1279 wrap_e(e, &x);
1280 }
1281
1282 void
xeflt64(DBLINT64 l,IEEE80 e)1283 xeflt64(DBLINT64 l, IEEE80 e)
1284 {
1285 float128_t x;
1286 int64_t y;
1287 unwrap_l(&y, l);
1288 check(fold_real128_from_int64(&x, &y));
1289 wrap_e(e, &x);
1290 }
1291
1292 void
xefltu64(DBLUINT64 u,IEEE80 e)1293 xefltu64(DBLUINT64 u, IEEE80 e)
1294 {
1295 float128_t x;
1296 uint64_t y;
1297 unwrap_u(&y, u);
1298 check(fold_real128_from_uint64(&x, &y));
1299 wrap_e(e, &x);
1300 }
1301
1302 void
xftoe(IEEE32 f,IEEE80 e)1303 xftoe(IEEE32 f, IEEE80 e)
1304 {
1305 float128_t x;
1306 float32_t y;
1307 unwrap_f(&y, &f);
1308 check(fold_real128_from_real32(&x, &y));
1309 wrap_e(e, &x);
1310 }
1311
1312 void
xdtoe(IEEE64 d,IEEE80 e)1313 xdtoe(IEEE64 d, IEEE80 e)
1314 {
1315 float128_t x;
1316 float64_t y;
1317 unwrap_d(&y, d);
1318 check(fold_real128_from_real64(&x, &y));
1319 wrap_e(e, &x);
1320 }
1321
1322 void
xetof(IEEE80 e,IEEE32 * r)1323 xetof(IEEE80 e, IEEE32 *r)
1324 {
1325 float32_t x;
1326 float128_t y;
1327 unwrap_e(&y, e);
1328 check(fold_real32_from_real128(&x, &y));
1329 wrap_f(r, &x);
1330 }
1331
1332 void
xetod(IEEE80 e,IEEE64 d)1333 xetod(IEEE80 e, IEEE64 d)
1334 {
1335 float64_t x;
1336 float128_t y;
1337 unwrap_e(&y, e);
1338 check(fold_real64_from_real128(&x, &y));
1339 wrap_d(d, &x);
1340 }
1341
1342 void
xeadd(IEEE80 e1,IEEE80 e2,IEEE80 r)1343 xeadd(IEEE80 e1, IEEE80 e2, IEEE80 r)
1344 {
1345 float128_t x, y, z;
1346 unwrap_e(&y, e1);
1347 unwrap_e(&z, e2);
1348 check(fold_real128_add(&x, &y, &z));
1349 wrap_e(r, &x);
1350 }
1351
1352 void
xesub(IEEE80 e1,IEEE80 e2,IEEE80 r)1353 xesub(IEEE80 e1, IEEE80 e2, IEEE80 r)
1354 {
1355 float128_t x, y, z;
1356 unwrap_e(&y, e1);
1357 unwrap_e(&z, e2);
1358 check(fold_real128_subtract(&x, &y, &z));
1359 wrap_e(r, &x);
1360 }
1361
1362 void
xeneg(IEEE80 e,IEEE80 r)1363 xeneg(IEEE80 e, IEEE80 r)
1364 {
1365 float128_t x, y;
1366 unwrap_e(&y, e);
1367 check(fold_real128_negate(&x, &y));
1368 wrap_e(r, &x);
1369 }
1370
1371 void
xemul(IEEE80 e1,IEEE80 e2,IEEE80 r)1372 xemul(IEEE80 e1, IEEE80 e2, IEEE80 r)
1373 {
1374 float128_t x, y, z;
1375 unwrap_e(&y, e1);
1376 unwrap_e(&z, e2);
1377 check(fold_real128_multiply(&x, &y, &z));
1378 wrap_e(r, &x);
1379 }
1380
1381 void
xediv(IEEE80 e1,IEEE80 e2,IEEE80 r)1382 xediv(IEEE80 e1, IEEE80 e2, IEEE80 r)
1383 {
1384 float128_t x, y, z;
1385 unwrap_e(&y, e1);
1386 unwrap_e(&z, e2);
1387 check(fold_real128_divide(&x, &y, &z));
1388 wrap_e(r, &x);
1389 }
1390
1391 void
xeabsv(IEEE80 e,IEEE80 r)1392 xeabsv(IEEE80 e, IEEE80 r)
1393 {
1394 float128_t x, y;
1395 unwrap_e(&y, e);
1396 check(fold_real128_abs(&x, &y));
1397 wrap_e(r, &x);
1398 }
1399
1400 void
xesqrt(IEEE80 e,IEEE80 r)1401 xesqrt(IEEE80 e, IEEE80 r)
1402 {
1403 float128_t x, y;
1404 unwrap_e(&y, e);
1405 check(fold_real128_sqrt(&x, &y));
1406 wrap_e(r, &x);
1407 }
1408
1409 void
xepow(IEEE80 e1,IEEE80 e2,IEEE80 r)1410 xepow(IEEE80 e1, IEEE80 e2, IEEE80 r)
1411 {
1412 float128_t x, y, z;
1413 unwrap_e(&y, e1);
1414 unwrap_e(&z, e2);
1415 check(fold_real128_pow(&x, &y, &z));
1416 wrap_e(r, &x);
1417 }
1418
1419 void
xesin(IEEE80 e,IEEE80 r)1420 xesin(IEEE80 e, IEEE80 r)
1421 {
1422 float128_t x, y;
1423 unwrap_e(&y, e);
1424 check(fold_real128_sin(&x, &y));
1425 wrap_e(r, &x);
1426 }
1427
1428 void
xecos(IEEE80 e,IEEE80 r)1429 xecos(IEEE80 e, IEEE80 r)
1430 {
1431 float128_t x, y;
1432 unwrap_e(&y, e);
1433 check(fold_real128_cos(&x, &y));
1434 wrap_e(r, &x);
1435 }
1436
1437 void
xetan(IEEE80 e,IEEE80 r)1438 xetan(IEEE80 e, IEEE80 r)
1439 {
1440 float128_t x, y;
1441 unwrap_e(&y, e);
1442 check(fold_real128_tan(&x, &y));
1443 wrap_e(r, &x);
1444 }
1445
1446 void
xeasin(IEEE80 e,IEEE80 r)1447 xeasin(IEEE80 e, IEEE80 r)
1448 {
1449 float128_t x, y;
1450 unwrap_e(&y, e);
1451 check(fold_real128_asin(&x, &y));
1452 wrap_e(r, &x);
1453 }
1454
1455 void
xeacos(IEEE80 e,IEEE80 r)1456 xeacos(IEEE80 e, IEEE80 r)
1457 {
1458 float128_t x, y;
1459 unwrap_e(&y, e);
1460 check(fold_real128_acos(&x, &y));
1461 wrap_e(r, &x);
1462 }
1463
1464 void
xeatan(IEEE80 e,IEEE80 r)1465 xeatan(IEEE80 e, IEEE80 r)
1466 {
1467 float128_t x, y;
1468 unwrap_e(&y, e);
1469 check(fold_real128_atan(&x, &y));
1470 wrap_e(r, &x);
1471 }
1472
1473 void
xeatan2(IEEE80 e1,IEEE80 e2,IEEE80 r)1474 xeatan2(IEEE80 e1, IEEE80 e2, IEEE80 r)
1475 {
1476 float128_t x, y, z;
1477 unwrap_e(&y, e1);
1478 unwrap_e(&z, e2);
1479 check(fold_real128_atan2(&x, &y, &z));
1480 wrap_e(r, &x);
1481 }
1482
1483 void
xeexp(IEEE80 e,IEEE80 r)1484 xeexp(IEEE80 e, IEEE80 r)
1485 {
1486 float128_t x, y;
1487 unwrap_e(&y, e);
1488 check(fold_real128_exp(&x, &y));
1489 wrap_e(r, &x);
1490 }
1491
1492 void
xelog(IEEE80 e,IEEE80 r)1493 xelog(IEEE80 e, IEEE80 r)
1494 {
1495 float128_t x, y;
1496 unwrap_e(&y, e);
1497 check(fold_real128_log(&x, &y));
1498 wrap_e(r, &x);
1499 }
1500
1501 void
xelog10(IEEE80 e,IEEE80 r)1502 xelog10(IEEE80 e, IEEE80 r)
1503 {
1504 float128_t x, y;
1505 unwrap_e(&y, e);
1506 check(fold_real128_log10(&x, &y));
1507 wrap_e(r, &x);
1508 }
1509
1510 int
xecmp(IEEE80 e1,IEEE80 e2)1511 xecmp(IEEE80 e1, IEEE80 e2)
1512 {
1513 float128_t y, z;
1514 unwrap_e(&y, e1);
1515 unwrap_e(&z, e2);
1516 return fold_real128_compare(&y, &z);
1517 }
1518
1519 static int
parse_e(const char * s,IEEE80 e,int n,bool is_hex)1520 parse_e(const char *s, IEEE80 e, int n, bool is_hex)
1521 {
1522 float128_t x;
1523 char buffer[256], *end;
1524 int errno_capture;
1525 get_literal(buffer, sizeof buffer, s, n, is_hex);
1526 errno = 0;
1527 x = strtold(buffer, &end);
1528 errno_capture = errno;
1529 wrap_e(e, &x);
1530 return handle_parsing_errors(buffer, end, errno_capture, x == 0);
1531 }
1532
1533 int
atoxe(const char * s,IEEE80 e,int n)1534 atoxe(const char *s, IEEE80 e, int n)
1535 {
1536 return parse_e(s, e, n, false);
1537 }
1538
1539 int
hxatoxe(const char * s,IEEE80 e,int n)1540 hxatoxe(const char *s, IEEE80 e, int n)
1541 {
1542 return parse_e(s, e, n, true);
1543 }
1544 #endif /* FOLD_LDBL_X87 */
1545
1546 #ifdef FOLD_LDBL_DOUBLEDOUBLE
1547 static void
unwrap_dd(float128_t * x,IEEE6464 dd)1548 unwrap_dd(float128_t *x, IEEE6464 dd)
1549 {
1550 union {
1551 float128_t x;
1552 float64_t d[2];
1553 } u;
1554 unwrap_d(&u.d[0], dd[0]);
1555 unwrap_d(&u.d[1], dd[1]);
1556 *x = u.x;
1557 }
1558
1559 static void
wrap_dd(IEEE6464 res,const float128_t * x)1560 wrap_dd(IEEE6464 res, const float128_t *x)
1561 {
1562 union {
1563 float128_t dd;
1564 float64_t d[2];
1565 } u;
1566 u.dd = *x;
1567 wrap_d(res[0], &u.d[0]);
1568 wrap_d(res[1], &u.d[1]);
1569 }
1570
1571 void
xddfix(IEEE6464 dd,INT * i)1572 xddfix(IEEE6464 dd, INT *i)
1573 {
1574 float128_t y;
1575 unwrap_dd(&y, dd);
1576 check(fold_int32_from_real128(i, &y));
1577 }
1578
1579 void
xddfixu(IEEE6464 dd,UINT * u)1580 xddfixu(IEEE6464 dd, UINT *u)
1581 {
1582 float128_t y;
1583 unwrap_dd(&y, dd);
1584 check(fold_uint32_from_real128(u, &y));
1585 }
1586
1587 void
xddfix64(IEEE6464 dd,DBLINT64 l)1588 xddfix64(IEEE6464 dd, DBLINT64 l)
1589 {
1590 int64_t x;
1591 float128_t y;
1592 unwrap_dd(&y, dd);
1593 check(fold_int64_from_real128(&x, &y));
1594 wrap_l(l, &x);
1595 }
1596
1597 void
xddfixu64(IEEE6464 dd,DBLUINT64 u)1598 xddfixu64(IEEE6464 dd, DBLUINT64 u)
1599 {
1600 uint64_t x;
1601 float128_t y;
1602 unwrap_dd(&y, dd);
1603 check(fold_uint64_from_real128(&x, &y));
1604 wrap_u(u, &x);
1605 }
1606
1607 void
xddfloat(INT i,IEEE6464 dd)1608 xddfloat(INT i, IEEE6464 dd)
1609 {
1610 float128_t x;
1611 int64_t li = i;
1612 check(fold_real128_from_int64(&x, &li));
1613 wrap_dd(dd, &x);
1614 }
1615
1616 void
xddfloatu(UINT u,IEEE6464 dd)1617 xddfloatu(UINT u, IEEE6464 dd)
1618 {
1619 float128_t x;
1620 int64_t li = u;
1621 check(fold_real128_from_int64(&x, &li));
1622 wrap_dd(dd, &x);
1623 }
1624
1625 void
xddflt64(DBLINT64 l,IEEE6464 dd)1626 xddflt64(DBLINT64 l, IEEE6464 dd)
1627 {
1628 float128_t x;
1629 int64_t y;
1630 unwrap_l(&y, l);
1631 check(fold_real128_from_int64(&x, &y));
1632 wrap_dd(dd, &x);
1633 }
1634
1635 void
xddfltu64(DBLUINT64 u,IEEE6464 dd)1636 xddfltu64(DBLUINT64 u, IEEE6464 dd)
1637 {
1638 float128_t x;
1639 uint64_t y;
1640 unwrap_u(&y, u);
1641 check(fold_real128_from_uint64(&x, &y));
1642 wrap_dd(dd, &x);
1643 }
1644
1645 void
xftodd(IEEE32 f,IEEE6464 dd)1646 xftodd(IEEE32 f, IEEE6464 dd)
1647 {
1648 float128_t x;
1649 float32_t y;
1650 unwrap_f(&y, &f);
1651 check(fold_real128_from_real32(&x, &y));
1652 wrap_dd(dd, &x);
1653 }
1654
1655 void
xdtodd(IEEE64 d,IEEE6464 dd)1656 xdtodd(IEEE64 d, IEEE6464 dd)
1657 {
1658 float128_t x;
1659 float64_t y;
1660 unwrap_d(&y, d);
1661 check(fold_real128_from_real64(&x, &y));
1662 wrap_dd(dd, &x);
1663 }
1664
1665 void
xddtof(IEEE6464 dd,IEEE32 * r)1666 xddtof(IEEE6464 dd, IEEE32 *r)
1667 {
1668 float32_t x;
1669 float128_t y;
1670 unwrap_dd(&y, dd);
1671 check(fold_real32_from_real128(&x, &y));
1672 wrap_f(r, &x);
1673 }
1674
1675 void
xddtod(IEEE6464 dd,IEEE64 d)1676 xddtod(IEEE6464 dd, IEEE64 d)
1677 {
1678 float64_t x;
1679 float128_t y;
1680 unwrap_dd(&y, dd);
1681 check(fold_real64_from_real128(&x, &y));
1682 wrap_d(d, &x);
1683 }
1684
1685 void
xddadd(IEEE6464 dd1,IEEE6464 dd2,IEEE6464 r)1686 xddadd(IEEE6464 dd1, IEEE6464 dd2, IEEE6464 r)
1687 {
1688 float128_t x, y, z;
1689 unwrap_dd(&y, dd1);
1690 unwrap_dd(&z, dd2);
1691 check(fold_real128_add(&x, &y, &z));
1692 wrap_dd(r, &x);
1693 }
1694
1695 void
xddsub(IEEE6464 dd1,IEEE6464 dd2,IEEE6464 r)1696 xddsub(IEEE6464 dd1, IEEE6464 dd2, IEEE6464 r)
1697 {
1698 float128_t x, y, z;
1699 unwrap_dd(&y, dd1);
1700 unwrap_dd(&z, dd2);
1701 check(fold_real128_subtract(&x, &y, &z));
1702 wrap_dd(r, &x);
1703 }
1704
1705 void
xddneg(IEEE6464 dd,IEEE6464 r)1706 xddneg(IEEE6464 dd, IEEE6464 r)
1707 {
1708 float128_t x, y;
1709 unwrap_dd(&y, dd);
1710 check(fold_real128_negate(&x, &y));
1711 wrap_dd(r, &x);
1712 }
1713
1714 void
xddmul(IEEE6464 dd1,IEEE6464 dd2,IEEE6464 r)1715 xddmul(IEEE6464 dd1, IEEE6464 dd2, IEEE6464 r)
1716 {
1717 float128_t x, y, z;
1718 unwrap_dd(&y, dd1);
1719 unwrap_dd(&z, dd2);
1720 check(fold_real128_multiply(&x, &y, &z));
1721 wrap_dd(r, &x);
1722 }
1723
1724 void
xdddiv(IEEE6464 dd1,IEEE6464 dd2,IEEE6464 r)1725 xdddiv(IEEE6464 dd1, IEEE6464 dd2, IEEE6464 r)
1726 {
1727 float128_t x, y, z;
1728 unwrap_dd(&y, dd1);
1729 unwrap_dd(&z, dd2);
1730 check(fold_real128_divide(&x, &y, &z));
1731 wrap_dd(r, &x);
1732 }
1733
1734 void
xddabs(IEEE6464 dd,IEEE6464 r)1735 xddabs(IEEE6464 dd, IEEE6464 r)
1736 {
1737 float128_t x, y;
1738 unwrap_dd(&y, dd);
1739 check(fold_real128_abs(&x, &y));
1740 wrap_dd(r, &x);
1741 }
1742
1743 void
xddsqrt(IEEE6464 dd,IEEE6464 r)1744 xddsqrt(IEEE6464 dd, IEEE6464 r)
1745 {
1746 float128_t x, y;
1747 unwrap_dd(&y, dd);
1748 check(fold_real128_sqrt(&x, &y));
1749 wrap_dd(r, &x);
1750 }
1751
1752 void
xddpow(IEEE6464 dd1,IEEE6464 dd2,IEEE6464 r)1753 xddpow(IEEE6464 dd1, IEEE6464 dd2, IEEE6464 r)
1754 {
1755 float128_t x, y, z;
1756 unwrap_dd(&y, dd1);
1757 unwrap_dd(&z, dd2);
1758 check(fold_real128_pow(&x, &y, &z));
1759 wrap_dd(r, &x);
1760 }
1761
1762 void
xddsin(IEEE6464 dd,IEEE6464 r)1763 xddsin(IEEE6464 dd, IEEE6464 r)
1764 {
1765 float128_t x, y;
1766 unwrap_dd(&y, dd);
1767 check(fold_real128_sin(&x, &y));
1768 wrap_dd(r, &x);
1769 }
1770
1771 void
xddcos(IEEE6464 dd,IEEE6464 r)1772 xddcos(IEEE6464 dd, IEEE6464 r)
1773 {
1774 float128_t x, y;
1775 unwrap_dd(&y, dd);
1776 check(fold_real128_cos(&x, &y));
1777 wrap_dd(r, &x);
1778 }
1779
1780 void
xddtan(IEEE6464 dd,IEEE6464 r)1781 xddtan(IEEE6464 dd, IEEE6464 r)
1782 {
1783 float128_t x, y;
1784 unwrap_dd(&y, dd);
1785 check(fold_real128_tan(&x, &y));
1786 wrap_dd(r, &x);
1787 }
1788
1789 void
xddasin(IEEE6464 dd,IEEE6464 r)1790 xddasin(IEEE6464 dd, IEEE6464 r)
1791 {
1792 float128_t x, y;
1793 unwrap_dd(&y, dd);
1794 check(fold_real128_asin(&x, &y));
1795 wrap_dd(r, &x);
1796 }
1797
1798 void
xddacos(IEEE6464 dd,IEEE6464 r)1799 xddacos(IEEE6464 dd, IEEE6464 r)
1800 {
1801 float128_t x, y;
1802 unwrap_dd(&y, dd);
1803 check(fold_real128_acos(&x, &y));
1804 wrap_dd(r, &x);
1805 }
1806
1807 void
xddatan(IEEE6464 dd,IEEE6464 r)1808 xddatan(IEEE6464 dd, IEEE6464 r)
1809 {
1810 float128_t x, y;
1811 unwrap_dd(&y, dd);
1812 check(fold_real128_atan(&x, &y));
1813 wrap_dd(r, &x);
1814 }
1815
1816 void
xddatan2(IEEE6464 dd1,IEEE6464 dd2,IEEE6464 r)1817 xddatan2(IEEE6464 dd1, IEEE6464 dd2, IEEE6464 r)
1818 {
1819 float128_t x, y, z;
1820 unwrap_dd(&y, dd1);
1821 unwrap_dd(&z, dd2);
1822 check(fold_real128_atan2(&x, &y, &z));
1823 wrap_dd(r, &x);
1824 }
1825
1826 void
xddexp(IEEE6464 dd,IEEE6464 r)1827 xddexp(IEEE6464 dd, IEEE6464 r)
1828 {
1829 float128_t x, y;
1830 unwrap_dd(&y, dd);
1831 check(fold_real128_exp(&x, &y));
1832 wrap_dd(r, &x);
1833 }
1834
1835 void
xddlog(IEEE6464 dd,IEEE6464 r)1836 xddlog(IEEE6464 dd, IEEE6464 r)
1837 {
1838 float128_t x, y;
1839 unwrap_dd(&y, dd);
1840 check(fold_real128_log(&x, &y));
1841 wrap_dd(r, &x);
1842 }
1843
1844 void
xddlog10(IEEE6464 dd,IEEE6464 r)1845 xddlog10(IEEE6464 dd, IEEE6464 r)
1846 {
1847 float128_t x, y;
1848 unwrap_dd(&y, dd);
1849 check(fold_real128_log10(&x, &y));
1850 wrap_dd(r, &x);
1851 }
1852
1853 int
xddcmp(IEEE6464 dd1,IEEE6464 dd2)1854 xddcmp(IEEE6464 dd1, IEEE6464 dd2)
1855 {
1856 float128_t y, z;
1857 unwrap_dd(&y, dd1);
1858 unwrap_dd(&z, dd2);
1859 return fold_real128_compare(&y, &z);
1860 }
1861
1862 static int
parse_dd(const char * s,IEEE6464 dd,int n,bool is_hex)1863 parse_dd(const char *s, IEEE6464 dd, int n, bool is_hex)
1864 {
1865 float128_t x;
1866 char buffer[256], *end;
1867 int errno_capture;
1868 get_literal(buffer, sizeof buffer, s, n, is_hex);
1869 errno = 0;
1870 x = strtold(buffer, &end);
1871 errno_capture = errno;
1872 wrap_dd(dd, &x);
1873 return handle_parsing_errors(buffer, end, errno_capture, x == 0);
1874 }
1875
1876 int
atoxdd(const char * s,IEEE6464 dd,int n)1877 atoxdd(const char *s, IEEE6464 dd, int n)
1878 {
1879 return parse_dd(s, dd, n, false);
1880 }
1881
1882 int
hxatoxdd(const char * s,IEEE6464 dd,int n)1883 hxatoxdd(const char *s, IEEE6464 dd, int n)
1884 {
1885 return parse_dd(s, dd, n, true);
1886 }
1887 #endif /* FOLD_LDBL_DOUBLEDOUBLE */
1888
1889 #ifdef FOLD_LDBL_128BIT
1890 static void
unwrap_q(float128_t * x,IEEE128 q)1891 unwrap_q(float128_t *x, IEEE128 q)
1892 {
1893 union {
1894 float128_t x;
1895 uint32_t i[4];
1896 } u;
1897 int le = (int) is_host_little_endian() * 3;
1898 u.i[le ^ 0] = q[0]; /* big end */
1899 u.i[le ^ 1] = q[1];
1900 u.i[le ^ 2] = q[2];
1901 u.i[le ^ 3] = q[3];
1902 *x = u.x;
1903 }
1904
1905 static void
wrap_q(IEEE128 res,float128_t * x)1906 wrap_q(IEEE128 res, float128_t *x)
1907 {
1908 union {
1909 float128_t q;
1910 uint32_t i[4];
1911 } u;
1912 int le = (int) is_host_little_endian() * 3;
1913 u.q = *x;
1914 res[0] = u.i[le ^ 0]; /* big end */
1915 res[1] = u.i[le ^ 1];
1916 res[2] = u.i[le ^ 2];
1917 res[3] = u.i[le ^ 3];
1918 }
1919
1920 void
xqfix(IEEE128 q,INT * i)1921 xqfix(IEEE128 q, INT *i)
1922 {
1923 float128_t y;
1924 unwrap_q(&y, q);
1925 check(fold_int32_from_real128(i, &y));
1926 }
1927
1928 void
xqfixu(IEEE128 q,UINT * u)1929 xqfixu(IEEE128 q, UINT *u)
1930 {
1931 float128_t y;
1932 unwrap_q(&y, q);
1933 check(fold_uint32_from_real128(u, &y));
1934 }
1935
1936 void
xqfix64(IEEE128 q,DBLINT64 l)1937 xqfix64(IEEE128 q, DBLINT64 l)
1938 {
1939 int64_t x;
1940 float128_t y;
1941 unwrap_q(&y, q);
1942 check(fold_int64_from_real128(&x, &y));
1943 wrap_l(l, &x);
1944 }
1945
1946 void
xqfixu64(IEEE128 q,DBLUINT64 u)1947 xqfixu64(IEEE128 q, DBLUINT64 u)
1948 {
1949 uint64_t x;
1950 float128_t y;
1951 unwrap_q(&y, q);
1952 check(fold_uint64_from_real128(&x, &y));
1953 wrap_l(u, &x);
1954 }
1955
1956 void
xqflt64(DBLINT64 l,IEEE128 q)1957 xqflt64(DBLINT64 l, IEEE128 q)
1958 {
1959 float128_t x;
1960 int64_t y;
1961 unwrap_l(&y, l);
1962 check(fold_real128_from_int64(&x, &y));
1963 wrap_q(q, &x);
1964 }
1965
1966 void
xqfloat(INT i,IEEE128 q)1967 xqfloat(INT i, IEEE128 q)
1968 {
1969 float128_t x;
1970 int64_t li = i;
1971 check(fold_real128_from_int64(&x, &li));
1972 wrap_q(q, &x);
1973 }
1974
1975 void
xqfloatu(UINT u,IEEE128 q)1976 xqfloatu(UINT u, IEEE128 q)
1977 {
1978 float128_t x;
1979 int64_t li = u;
1980 check(fold_real128_from_int64(&x, &li));
1981 wrap_q(q, &x);
1982 }
1983
1984 void
xqfltu64(DBLUINT64 u,IEEE128 q)1985 xqfltu64(DBLUINT64 u, IEEE128 q)
1986 {
1987 float128_t x;
1988 uint64_t y;
1989 unwrap_u(&y, u);
1990 check(fold_real128_from_uint64(&x, &y));
1991 wrap_q(q, &x);
1992 }
1993
1994 void
xftoq(IEEE32 f,IEEE128 q)1995 xftoq(IEEE32 f, IEEE128 q)
1996 {
1997 float128_t x;
1998 float32_t y;
1999 unwrap_f(&y, &f);
2000 check(fold_real128_from_real32(&x, &y));
2001 wrap_q(q, &x);
2002 }
2003
2004 void
xdtoq(IEEE64 d,IEEE128 q)2005 xdtoq(IEEE64 d, IEEE128 q)
2006 {
2007 float128_t x;
2008 float64_t y;
2009 unwrap_d(&y, d);
2010 check(fold_real128_from_real64(&x, &y));
2011 wrap_q(q, &x);
2012 }
2013
2014 void
xqtof(IEEE128 q,IEEE32 * r)2015 xqtof(IEEE128 q, IEEE32 *r)
2016 {
2017 float32_t x;
2018 float128_t y;
2019 unwrap_q(&y, q);
2020 check(fold_real32_from_real128(&x, &y));
2021 wrap_f(r, &x);
2022 }
2023
2024 void
xqtod(IEEE128 q,IEEE64 d)2025 xqtod(IEEE128 q, IEEE64 d)
2026 {
2027 float64_t x;
2028 float128_t y;
2029 unwrap_q(&y, q);
2030 check(fold_real64_from_real128(&x, &y));
2031 wrap_d(d, &x);
2032 }
2033
2034 void
xqadd(IEEE128 q1,IEEE128 q2,IEEE128 r)2035 xqadd(IEEE128 q1, IEEE128 q2, IEEE128 r)
2036 {
2037 float128_t x, y, z;
2038 unwrap_q(&x, q1);
2039 unwrap_q(&y, q2);
2040 check(fold_real128_add(&x, &y, &z));
2041 wrap_q(r, &x);
2042 }
2043
2044 void
xqsub(IEEE128 q1,IEEE128 q2,IEEE128 r)2045 xqsub(IEEE128 q1, IEEE128 q2, IEEE128 r)
2046 {
2047 float128_t x, y, z;
2048 unwrap_q(&x, q1);
2049 unwrap_q(&y, q2);
2050 check(fold_real128_subtract(&x, &y, &z));
2051 wrap_q(r, &x);
2052 }
2053
2054 void
xqneg(IEEE128 q,IEEE128 r)2055 xqneg(IEEE128 q, IEEE128 r)
2056 {
2057 float128_t x, y;
2058 unwrap_q(&y, q);
2059 check(fold_real128_negate(&x, &y));
2060 wrap_q(r, &x);
2061 }
2062
2063 void
xqmul(IEEE128 q1,IEEE128 q2,IEEE128 r)2064 xqmul(IEEE128 q1, IEEE128 q2, IEEE128 r)
2065 {
2066 float128_t x, y, z;
2067 unwrap_q(&x, q1);
2068 unwrap_q(&y, q2);
2069 check(fold_real128_multiply(&x, &y, &z));
2070 wrap_q(r, &x);
2071 }
2072
2073 void
xqdiv(IEEE128 q1,IEEE128 q2,IEEE128 r)2074 xqdiv(IEEE128 q1, IEEE128 q2, IEEE128 r)
2075 {
2076 float128_t x, y, z;
2077 unwrap_q(&x, q1);
2078 unwrap_q(&y, q2);
2079 check(fold_real128_divide(&x, &y, &z));
2080 wrap_q(r, &x);
2081 }
2082
2083 void
xqabs(IEEE128 q,IEEE128 r)2084 xqabs(IEEE128 q, IEEE128 r)
2085 {
2086 float128_t x, y;
2087 unwrap_q(&y, q);
2088 check(fold_real128_abs(&x, &y));
2089 wrap_q(r, &x);
2090 }
2091
2092 void
xqsqrt(IEEE128 q,IEEE128 r)2093 xqsqrt(IEEE128 q, IEEE128 r)
2094 {
2095 float128_t x, y;
2096 unwrap_q(&y, q);
2097 check(fold_real128_sqrt(&x, &y));
2098 wrap_q(r, &x);
2099 }
2100
2101 void
xqpow(IEEE128 q1,IEEE128 q2,IEEE128 r)2102 xqpow(IEEE128 q1, IEEE128 q2, IEEE128 r)
2103 {
2104 float128_t x, y, z;
2105 unwrap_q(&x, q1);
2106 unwrap_q(&y, q2);
2107 check(fold_real128_pow(&x, &y, &z));
2108 wrap_q(r, &x);
2109 }
2110
2111 void
xqsin(IEEE128 q,IEEE128 r)2112 xqsin(IEEE128 q, IEEE128 r)
2113 {
2114 float128_t x, y;
2115 unwrap_q(&y, q);
2116 check(fold_real128_sin(&x, &y));
2117 wrap_q(r, &x);
2118 }
2119
2120 void
xqcos(IEEE128 q,IEEE128 r)2121 xqcos(IEEE128 q, IEEE128 r)
2122 {
2123 float128_t x, y;
2124 unwrap_q(&y, q);
2125 check(fold_real128_cos(&x, &y));
2126 wrap_q(r, &x);
2127 }
2128
2129 void
xqtan(IEEE128 q,IEEE128 r)2130 xqtan(IEEE128 q, IEEE128 r)
2131 {
2132 float128_t x, y;
2133 unwrap_q(&y, q);
2134 check(fold_real128_tan(&x, &y));
2135 wrap_q(r, &x);
2136 }
2137
2138 void
xqasin(IEEE128 q,IEEE128 r)2139 xqasin(IEEE128 q, IEEE128 r)
2140 {
2141 float128_t x, y;
2142 unwrap_q(&y, q);
2143 check(fold_real128_asin(&x, &y));
2144 wrap_q(r, &x);
2145 }
2146
2147 void
xqacos(IEEE128 q,IEEE128 r)2148 xqacos(IEEE128 q, IEEE128 r)
2149 {
2150 float128_t x, y;
2151 unwrap_q(&y, q);
2152 check(fold_real128_acos(&x, &y));
2153 wrap_q(r, &x);
2154 }
2155
2156 void
xqatan(IEEE128 q,IEEE128 r)2157 xqatan(IEEE128 q, IEEE128 r)
2158 {
2159 float128_t x, y;
2160 unwrap_q(&y, q);
2161 check(fold_real128_atan(&x, &y));
2162 wrap_q(r, &x);
2163 }
2164
2165 void
xqatan2(IEEE128 q1,IEEE128 q2,IEEE128 r)2166 xqatan2(IEEE128 q1, IEEE128 q2, IEEE128 r)
2167 {
2168 float128_t x, y, z;
2169 unwrap_q(&x, q1);
2170 unwrap_q(&y, q2);
2171 check(fold_real128_atan2(&x, &y, &z));
2172 wrap_q(r, &x);
2173 }
2174
2175 void
xqexp(IEEE128 q,IEEE128 r)2176 xqexp(IEEE128 q, IEEE128 r)
2177 {
2178 float128_t x, y;
2179 unwrap_q(&y, q);
2180 check(fold_real128_exp(&x, &y));
2181 wrap_q(r, &x);
2182 }
2183
2184 void
xqlog(IEEE128 q,IEEE128 r)2185 xqlog(IEEE128 q, IEEE128 r)
2186 {
2187 float128_t x, y;
2188 unwrap_q(&y, q);
2189 check(fold_real128_log(&x, &y));
2190 wrap_q(r, &x);
2191 }
2192
2193 void
xqlog10(IEEE128 q,IEEE128 r)2194 xqlog10(IEEE128 q, IEEE128 r)
2195 {
2196 float128_t x, y;
2197 unwrap_q(&y, q);
2198 check(fold_real128_log10(&x, &y));
2199 wrap_q(r, &x);
2200 }
2201
2202 int
xqcmp(IEEE128 q1,IEEE128 q2)2203 xqcmp(IEEE128 q1, IEEE128 q2)
2204 {
2205 float128_t y, z;
2206 unwrap_q(&y, q1);
2207 unwrap_q(&z, q2);
2208 return fold_real128_compare(&y, &z);
2209 }
2210
2211 static int
parse_q(const char * s,IEEE128 q,int n,bool is_hex)2212 parse_q(const char *s, IEEE128 q, int n, bool is_hex)
2213 {
2214 float128_t x;
2215 char buffer[256], *end;
2216 int errno_capture;
2217 get_literal(buffer, sizeof buffer, s, n, is_hex);
2218 errno = 0;
2219 x = strtold(buffer, &end);
2220 errno_capture = errno;
2221 wrap_q(q, &x);
2222 return handle_parsing_errors(buffer, end, errno_capture, x == 0);
2223 }
2224
2225 int
atoxq(const char * s,IEEE128 q,int n)2226 atoxq(const char *s, IEEE128 q, int n)
2227 {
2228 return parse_q(s, q, n, false);
2229 }
2230
2231 int
hxatoxq(const char * s,IEEE128 q,int n)2232 hxatoxq(const char *s, IEEE128 q, int n)
2233 {
2234 return parse_q(s, q, n, true);
2235 }
2236 #endif /* FOLD_LDBL_128BIT */
2237
2238 /*
2239 * Miscellaneous, possibly unused
2240 */
2241
2242 INT
xudiv(UINT n,UINT d,UINT * r)2243 xudiv(UINT n, UINT d, UINT *r)
2244 {
2245 if (d == 0)
2246 return -1;
2247 *r = n / d;
2248 return 0;
2249 }
2250
2251 INT
xumod(UINT n,UINT d,UINT * r)2252 xumod(UINT n, UINT d, UINT *r)
2253 {
2254 if (d == 0)
2255 return -1;
2256 *r = n % d;
2257 return 0;
2258 }
2259
2260 /* Does an unsigned comparison, but declared in scutil with signed args. */
2261 INT
xucmp(INT sa,INT sb)2262 xucmp(INT sa, INT sb)
2263 {
2264 uint32_t a = sa, b = sb;
2265 return a < b ? -1 : a > b;
2266 }
2267
2268 /*
2269 * Literal integer scanning routines
2270 */
2271
2272 /* Utility subroutine for atoxi()/atoxi64(). Ensure that the literal
2273 * is null-terminated and actually contains some digits. Recognize
2274 * any leading sign character.
2275 */
2276 static const char *
get_int_literal(const char * s,int n,char * buffer,size_t buffer_length,bool * is_negative)2277 get_int_literal(const char *s, int n, char *buffer, size_t buffer_length,
2278 bool *is_negative)
2279 {
2280 *is_negative = false;
2281
2282 while (n > 0 && isspace(*s)) {
2283 --n, ++s;
2284 }
2285 if (n > 0) {
2286 if (*s == '+') {
2287 --n, ++s; /* ignore '+' */
2288 } else if (*s == '-') {
2289 *is_negative = true;
2290 --n, ++s;
2291 }
2292 }
2293 if (n < 1)
2294 return NULL;
2295 if (!memchr(s, '\0', n)) {
2296 /* copy to ensure null termination */
2297 if (n > buffer_length + 1)
2298 return NULL;
2299 memcpy(buffer, s, n);
2300 buffer[n] = '\0';
2301 return buffer;
2302 }
2303 return s;
2304 }
2305
2306 static int
generic_atoxi(uint64_t * v,bool * is_negative,const char * s,int n,int base)2307 generic_atoxi(uint64_t *v, bool *is_negative,
2308 const char *s, int n, int base)
2309 {
2310 char buffer[64], *end;
2311 if (!(s = get_int_literal(s, n, buffer, sizeof buffer, is_negative)))
2312 return -1; /* syntax or size error */
2313 errno = 0;
2314 *v = strtoull(s, &end, abs(base));
2315 if (errno == ERANGE) {
2316 /* overflow */
2317 return base < 0 ? -3 : -2;
2318 }
2319 if (errno != 0 || *end != '\0')
2320 return -1; /* syntax */
2321 return 0;
2322 }
2323
2324 int
atoxi(const char * s,INT * i,int n,int base)2325 atoxi(const char *s, INT *i, int n, int base)
2326 {
2327 uint64_t v;
2328 bool is_negative = false;
2329 int err = generic_atoxi(&v, &is_negative, s, n, base);
2330 if (!err && v > INT32_MAX) {
2331 if (base < 0)
2332 err = -3;
2333 else if (is_negative || v > UINT32_MAX)
2334 err = -2;
2335 }
2336 *i = is_negative ? -v : v;
2337 return err;
2338 }
2339
2340 int
atoxi64(const char * s,DBLINT64 i,int n,int base)2341 atoxi64(const char *s, DBLINT64 i, int n, int base)
2342 {
2343 uint64_t v;
2344 int64_t sv;
2345 bool is_negative = false;
2346 int err = generic_atoxi(&v, &is_negative, s, n, base);
2347 if (!err && (int64_t) v < 0) {
2348 if (base < 0)
2349 err = -3;
2350 else if (is_negative)
2351 err = -2;
2352 }
2353 sv = is_negative ? -v : v;
2354 wrap_l(i, &sv);
2355 return err;
2356 }
2357
2358 /*
2359 * These two variants force a signed interpretation of decimals.
2360 */
2361
2362 int
atosi32(const char * s,INT * i,int n,int base)2363 atosi32(const char *s, INT *i, int n, int base)
2364 {
2365 return atoxi(s, i, n, base == 10 ? -10 : base);
2366 }
2367
2368 int
atosi64(const char * s,DBLINT64 i,int n,int base)2369 atosi64(const char *s, DBLINT64 i, int n, int base)
2370 {
2371 return atoxi64(s, i, n, base == 10 ? -10 : base);
2372 }
2373
2374 /*
2375 * Format a floating-point constant. The format character determines
2376 * the size/type of the constant.
2377 */
2378 void
cprintf(char * buffer,const char * format,INT * val)2379 cprintf(char *buffer, const char *format, INT *val)
2380 {
2381 size_t off = strspn(format, " %-0123456789.");
2382 float128_t x;
2383 float64_t d;
2384 float32_t f;
2385 const char *p = format + off;
2386 char nfmt[128];
2387 IEEE32 fv;
2388
2389 buffer[0] = '\0';
2390
2391 switch (*p) {
2392 case 'q':
2393 case 'L':
2394 #ifdef FOLD_LDBL_X87
2395 unwrap_e(&x, val);
2396 #elif defined FOLD_LDBL_DOUBLEDOUBLE
2397 unwrap_dd(&x, (IEEE64*) val);
2398 #elif defined FOLD_LDBL_128BIT
2399 unwrap_q(&x, val);
2400 #else
2401 return;
2402 #endif
2403 ++p;
2404 break;
2405 case 'l':
2406 unwrap_d(&d, val);
2407 x = d;
2408 ++p;
2409 break;
2410 default:
2411 fv = (intptr_t) val;
2412 unwrap_f(&f, &fv);
2413 x = f;
2414 }
2415 if (off <= sizeof nfmt - 3) {
2416 memcpy(nfmt, format, off);
2417 strcpy(nfmt + off, "LE");
2418 sprintf(buffer, nfmt, x);
2419 if (*p == 'd' || *p == 'q') {
2420 char *E = strchr(buffer, 'E');
2421 if (E != NULL)
2422 *E = 'D';
2423 }
2424 }
2425 }
2426