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(&quotient, &remainder, &x, &y);
484   wrap_i128(result, &quotient);
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