1 /*
2  * semi.c: test implementations of mathlib seminumerical functions
3  *
4  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5  * See https://llvm.org/LICENSE.txt for license information.
6  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7  */
8 
9 #include <stdio.h>
10 #include "semi.h"
11 
test_rint(uint32 * in,uint32 * out,int isfloor,int isceil)12 static void test_rint(uint32 *in, uint32 *out,
13                        int isfloor, int isceil) {
14     int sign = in[0] & 0x80000000;
15     int roundup = (isfloor && sign) || (isceil && !sign);
16     uint32 xh, xl, roundword;
17     int ex = (in[0] >> 20) & 0x7FF;    /* exponent */
18     int i;
19 
20     if ((ex > 0x3ff + 52 - 1) ||     /* things this big can't be fractional */
21         ((in[0] & 0x7FFFFFFF) == 0 && in[1] == 0)) {   /* zero */
22         /* NaN, Inf, a large integer, or zero: just return the input */
23         out[0] = in[0];
24         out[1] = in[1];
25         return;
26     }
27 
28     /*
29      * Special case: ex < 0x3ff, ie our number is in (0,1). Return
30      * 1 or 0 according to roundup.
31      */
32     if (ex < 0x3ff) {
33         out[0] = sign | (roundup ? 0x3FF00000 : 0);
34         out[1] = 0;
35         return;
36     }
37 
38     /*
39      * We're not short of time here, so we'll do this the hideously
40      * inefficient way. Shift bit by bit so that the units place is
41      * somewhere predictable, round, and shift back again.
42      */
43     xh = in[0];
44     xl = in[1];
45     roundword = 0;
46     for (i = ex; i < 0x3ff + 52; i++) {
47         if (roundword & 1)
48             roundword |= 2;            /* preserve sticky bit */
49         roundword = (roundword >> 1) | ((xl & 1) << 31);
50         xl = (xl >> 1) | ((xh & 1) << 31);
51         xh = xh >> 1;
52     }
53     if (roundword && roundup) {
54         xl++;
55         xh += (xl==0);
56     }
57     for (i = ex; i < 0x3ff + 52; i++) {
58         xh = (xh << 1) | ((xl >> 31) & 1);
59         xl = (xl & 0x7FFFFFFF) << 1;
60     }
61     out[0] = xh;
62     out[1] = xl;
63 }
64 
test_ceil(uint32 * in,uint32 * out)65 char *test_ceil(uint32 *in, uint32 *out) {
66     test_rint(in, out, 0, 1);
67     return NULL;
68 }
69 
test_floor(uint32 * in,uint32 * out)70 char *test_floor(uint32 *in, uint32 *out) {
71     test_rint(in, out, 1, 0);
72     return NULL;
73 }
74 
test_rintf(uint32 * in,uint32 * out,int isfloor,int isceil)75 static void test_rintf(uint32 *in, uint32 *out,
76                        int isfloor, int isceil) {
77     int sign = *in & 0x80000000;
78     int roundup = (isfloor && sign) || (isceil && !sign);
79     uint32 x, roundword;
80     int ex = (*in >> 23) & 0xFF;       /* exponent */
81     int i;
82 
83     if ((ex > 0x7f + 23 - 1) ||      /* things this big can't be fractional */
84         (*in & 0x7FFFFFFF) == 0) {     /* zero */
85         /* NaN, Inf, a large integer, or zero: just return the input */
86         *out = *in;
87         return;
88     }
89 
90     /*
91      * Special case: ex < 0x7f, ie our number is in (0,1). Return
92      * 1 or 0 according to roundup.
93      */
94     if (ex < 0x7f) {
95         *out = sign | (roundup ? 0x3F800000 : 0);
96         return;
97     }
98 
99     /*
100      * We're not short of time here, so we'll do this the hideously
101      * inefficient way. Shift bit by bit so that the units place is
102      * somewhere predictable, round, and shift back again.
103      */
104     x = *in;
105     roundword = 0;
106     for (i = ex; i < 0x7F + 23; i++) {
107         if (roundword & 1)
108             roundword |= 2;            /* preserve sticky bit */
109         roundword = (roundword >> 1) | ((x & 1) << 31);
110         x = x >> 1;
111     }
112     if (roundword && roundup) {
113         x++;
114     }
115     for (i = ex; i < 0x7F + 23; i++) {
116         x = x << 1;
117     }
118     *out = x;
119 }
120 
test_ceilf(uint32 * in,uint32 * out)121 char *test_ceilf(uint32 *in, uint32 *out) {
122     test_rintf(in, out, 0, 1);
123     return NULL;
124 }
125 
test_floorf(uint32 * in,uint32 * out)126 char *test_floorf(uint32 *in, uint32 *out) {
127     test_rintf(in, out, 1, 0);
128     return NULL;
129 }
130 
test_fmod(uint32 * a,uint32 * b,uint32 * out)131 char *test_fmod(uint32 *a, uint32 *b, uint32 *out) {
132     int sign;
133     int32 aex, bex;
134     uint32 am[2], bm[2];
135 
136     if (((a[0] & 0x7FFFFFFF) << 1) + !!a[1] > 0xFFE00000 ||
137         ((b[0] & 0x7FFFFFFF) << 1) + !!b[1] > 0xFFE00000) {
138         /* a or b is NaN: return QNaN, optionally with IVO */
139         uint32 an, bn;
140         out[0] = 0x7ff80000;
141         out[1] = 1;
142         an = ((a[0] & 0x7FFFFFFF) << 1) + !!a[1];
143         bn = ((b[0] & 0x7FFFFFFF) << 1) + !!b[1];
144         if ((an > 0xFFE00000 && an < 0xFFF00000) ||
145             (bn > 0xFFE00000 && bn < 0xFFF00000))
146             return "i";                /* at least one SNaN: IVO */
147         else
148             return NULL;               /* no SNaNs, but at least 1 QNaN */
149     }
150     if ((b[0] & 0x7FFFFFFF) == 0 && b[1] == 0) {   /* b==0: EDOM */
151         out[0] = 0x7ff80000;
152         out[1] = 1;
153         return "EDOM status=i";
154     }
155     if ((a[0] & 0x7FF00000) == 0x7FF00000) {   /* a==Inf: EDOM */
156         out[0] = 0x7ff80000;
157         out[1] = 1;
158         return "EDOM status=i";
159     }
160     if ((b[0] & 0x7FF00000) == 0x7FF00000) {   /* b==Inf: return a */
161         out[0] = a[0];
162         out[1] = a[1];
163         return NULL;
164     }
165     if ((a[0] & 0x7FFFFFFF) == 0 && a[1] == 0) {   /* a==0: return a */
166         out[0] = a[0];
167         out[1] = a[1];
168         return NULL;
169     }
170 
171     /*
172      * OK. That's the special cases cleared out of the way. Now we
173      * have finite (though not necessarily normal) a and b.
174      */
175     sign = a[0] & 0x80000000;          /* we discard sign of b */
176     test_frexp(a, am, (uint32 *)&aex);
177     test_frexp(b, bm, (uint32 *)&bex);
178     am[0] &= 0xFFFFF, am[0] |= 0x100000;
179     bm[0] &= 0xFFFFF, bm[0] |= 0x100000;
180 
181     while (aex >= bex) {
182         if (am[0] > bm[0] || (am[0] == bm[0] && am[1] >= bm[1])) {
183             am[1] -= bm[1];
184             am[0] = am[0] - bm[0] - (am[1] > ~bm[1]);
185         }
186         if (aex > bex) {
187             am[0] = (am[0] << 1) | ((am[1] & 0x80000000) >> 31);
188             am[1] <<= 1;
189             aex--;
190         } else
191             break;
192     }
193 
194     /*
195      * Renormalise final result; this can be cunningly done by
196      * passing a denormal to ldexp.
197      */
198     aex += 0x3fd;
199     am[0] |= sign;
200     test_ldexp(am, (uint32 *)&aex, out);
201 
202     return NULL;                       /* FIXME */
203 }
204 
test_fmodf(uint32 * a,uint32 * b,uint32 * out)205 char *test_fmodf(uint32 *a, uint32 *b, uint32 *out) {
206     int sign;
207     int32 aex, bex;
208     uint32 am, bm;
209 
210     if ((*a & 0x7FFFFFFF) > 0x7F800000 ||
211         (*b & 0x7FFFFFFF) > 0x7F800000) {
212         /* a or b is NaN: return QNaN, optionally with IVO */
213         uint32 an, bn;
214         *out = 0x7fc00001;
215         an = *a & 0x7FFFFFFF;
216         bn = *b & 0x7FFFFFFF;
217         if ((an > 0x7f800000 && an < 0x7fc00000) ||
218             (bn > 0x7f800000 && bn < 0x7fc00000))
219             return "i";                /* at least one SNaN: IVO */
220         else
221             return NULL;               /* no SNaNs, but at least 1 QNaN */
222     }
223     if ((*b & 0x7FFFFFFF) == 0) {      /* b==0: EDOM */
224         *out = 0x7fc00001;
225         return "EDOM status=i";
226     }
227     if ((*a & 0x7F800000) == 0x7F800000) {   /* a==Inf: EDOM */
228         *out = 0x7fc00001;
229         return "EDOM status=i";
230     }
231     if ((*b & 0x7F800000) == 0x7F800000) {   /* b==Inf: return a */
232         *out = *a;
233         return NULL;
234     }
235     if ((*a & 0x7FFFFFFF) == 0) {      /* a==0: return a */
236         *out = *a;
237         return NULL;
238     }
239 
240     /*
241      * OK. That's the special cases cleared out of the way. Now we
242      * have finite (though not necessarily normal) a and b.
243      */
244     sign = a[0] & 0x80000000;          /* we discard sign of b */
245     test_frexpf(a, &am, (uint32 *)&aex);
246     test_frexpf(b, &bm, (uint32 *)&bex);
247     am &= 0x7FFFFF, am |= 0x800000;
248     bm &= 0x7FFFFF, bm |= 0x800000;
249 
250     while (aex >= bex) {
251         if (am >= bm) {
252             am -= bm;
253         }
254         if (aex > bex) {
255             am <<= 1;
256             aex--;
257         } else
258             break;
259     }
260 
261     /*
262      * Renormalise final result; this can be cunningly done by
263      * passing a denormal to ldexp.
264      */
265     aex += 0x7d;
266     am |= sign;
267     test_ldexpf(&am, (uint32 *)&aex, out);
268 
269     return NULL;                       /* FIXME */
270 }
271 
test_ldexp(uint32 * x,uint32 * np,uint32 * out)272 char *test_ldexp(uint32 *x, uint32 *np, uint32 *out) {
273     int n = *np;
274     int32 n2;
275     uint32 y[2];
276     int ex = (x[0] >> 20) & 0x7FF;     /* exponent */
277     int sign = x[0] & 0x80000000;
278 
279     if (ex == 0x7FF) {                 /* inf/NaN; just return x */
280         out[0] = x[0];
281         out[1] = x[1];
282         return NULL;
283     }
284     if ((x[0] & 0x7FFFFFFF) == 0 && x[1] == 0) {   /* zero: return x */
285         out[0] = x[0];
286         out[1] = x[1];
287         return NULL;
288     }
289 
290     test_frexp(x, y, (uint32 *)&n2);
291     ex = n + n2;
292     if (ex > 0x400) {                  /* overflow */
293         out[0] = sign | 0x7FF00000;
294         out[1] = 0;
295         return "overflow";
296     }
297     /*
298      * Underflow. 2^-1074 is 00000000.00000001; so if ex == -1074
299      * then we have something [2^-1075,2^-1074). Under round-to-
300      * nearest-even, this whole interval rounds up to 2^-1074,
301      * except for the bottom endpoint which rounds to even and is
302      * an underflow condition.
303      *
304      * So, ex < -1074 is definite underflow, and ex == -1074 is
305      * underflow iff all mantissa bits are zero.
306      */
307     if (ex < -1074 || (ex == -1074 && (y[0] & 0xFFFFF) == 0 && y[1] == 0)) {
308         out[0] = sign;                 /* underflow: correctly signed zero */
309         out[1] = 0;
310         return "underflow";
311     }
312 
313     /*
314      * No overflow or underflow; should be nice and simple, unless
315      * we have to denormalise and round the result.
316      */
317     if (ex < -1021) {                  /* denormalise and round */
318         uint32 roundword;
319         y[0] &= 0x000FFFFF;
320         y[0] |= 0x00100000;            /* set leading bit */
321         roundword = 0;
322         while (ex < -1021) {
323             if (roundword & 1)
324                 roundword |= 2;        /* preserve sticky bit */
325             roundword = (roundword >> 1) | ((y[1] & 1) << 31);
326             y[1] = (y[1] >> 1) | ((y[0] & 1) << 31);
327             y[0] = y[0] >> 1;
328             ex++;
329         }
330         if (roundword > 0x80000000 ||  /* round up */
331             (roundword == 0x80000000 && (y[1] & 1))) {  /* round up to even */
332             y[1]++;
333             y[0] += (y[1] == 0);
334         }
335         out[0] = sign | y[0];
336         out[1] = y[1];
337         /* Proper ERANGE underflow was handled earlier, but we still
338          * expect an IEEE Underflow exception if this partially
339          * underflowed result is not exact. */
340         if (roundword)
341             return "u";
342         return NULL;                   /* underflow was handled earlier */
343     } else {
344         out[0] = y[0] + (ex << 20);
345         out[1] = y[1];
346         return NULL;
347     }
348 }
349 
test_ldexpf(uint32 * x,uint32 * np,uint32 * out)350 char *test_ldexpf(uint32 *x, uint32 *np, uint32 *out) {
351     int n = *np;
352     int32 n2;
353     uint32 y;
354     int ex = (*x >> 23) & 0xFF;     /* exponent */
355     int sign = *x & 0x80000000;
356 
357     if (ex == 0xFF) {                 /* inf/NaN; just return x */
358         *out = *x;
359         return NULL;
360     }
361     if ((*x & 0x7FFFFFFF) == 0) {      /* zero: return x */
362         *out = *x;
363         return NULL;
364     }
365 
366     test_frexpf(x, &y, (uint32 *)&n2);
367     ex = n + n2;
368     if (ex > 0x80) {                  /* overflow */
369         *out = sign | 0x7F800000;
370         return "overflow";
371     }
372     /*
373      * Underflow. 2^-149 is 00000001; so if ex == -149 then we have
374      * something [2^-150,2^-149). Under round-to- nearest-even,
375      * this whole interval rounds up to 2^-149, except for the
376      * bottom endpoint which rounds to even and is an underflow
377      * condition.
378      *
379      * So, ex < -149 is definite underflow, and ex == -149 is
380      * underflow iff all mantissa bits are zero.
381      */
382     if (ex < -149 || (ex == -149 && (y & 0x7FFFFF) == 0)) {
383         *out = sign;                 /* underflow: correctly signed zero */
384         return "underflow";
385     }
386 
387     /*
388      * No overflow or underflow; should be nice and simple, unless
389      * we have to denormalise and round the result.
390      */
391     if (ex < -125) {                  /* denormalise and round */
392         uint32 roundword;
393         y &= 0x007FFFFF;
394         y |= 0x00800000;               /* set leading bit */
395         roundword = 0;
396         while (ex < -125) {
397             if (roundword & 1)
398                 roundword |= 2;        /* preserve sticky bit */
399             roundword = (roundword >> 1) | ((y & 1) << 31);
400             y = y >> 1;
401             ex++;
402         }
403         if (roundword > 0x80000000 ||  /* round up */
404             (roundword == 0x80000000 && (y & 1))) {  /* round up to even */
405             y++;
406         }
407         *out = sign | y;
408         /* Proper ERANGE underflow was handled earlier, but we still
409          * expect an IEEE Underflow exception if this partially
410          * underflowed result is not exact. */
411         if (roundword)
412             return "u";
413         return NULL;                   /* underflow was handled earlier */
414     } else {
415         *out = y + (ex << 23);
416         return NULL;
417     }
418 }
419 
test_frexp(uint32 * x,uint32 * out,uint32 * nout)420 char *test_frexp(uint32 *x, uint32 *out, uint32 *nout) {
421     int ex = (x[0] >> 20) & 0x7FF;     /* exponent */
422     if (ex == 0x7FF) {                 /* inf/NaN; return x/0 */
423         out[0] = x[0];
424         out[1] = x[1];
425         nout[0] = 0;
426         return NULL;
427     }
428     if (ex == 0) {                     /* denormals/zeros */
429         int sign;
430         uint32 xh, xl;
431         if ((x[0] & 0x7FFFFFFF) == 0 && x[1] == 0) {
432             /* zero: return x/0 */
433             out[0] = x[0];
434             out[1] = x[1];
435             nout[0] = 0;
436             return NULL;
437         }
438         sign = x[0] & 0x80000000;
439         xh = x[0] & 0x7FFFFFFF;
440         xl = x[1];
441         ex = 1;
442         while (!(xh & 0x100000)) {
443             ex--;
444             xh = (xh << 1) | ((xl >> 31) & 1);
445             xl = (xl & 0x7FFFFFFF) << 1;
446         }
447         out[0] = sign | 0x3FE00000 | (xh & 0xFFFFF);
448         out[1] = xl;
449         nout[0] = ex - 0x3FE;
450         return NULL;
451     }
452     out[0] = 0x3FE00000 | (x[0] & 0x800FFFFF);
453     out[1] = x[1];
454     nout[0] = ex - 0x3FE;
455     return NULL;                       /* ordinary number; no error */
456 }
457 
test_frexpf(uint32 * x,uint32 * out,uint32 * nout)458 char *test_frexpf(uint32 *x, uint32 *out, uint32 *nout) {
459     int ex = (*x >> 23) & 0xFF;        /* exponent */
460     if (ex == 0xFF) {                  /* inf/NaN; return x/0 */
461         *out = *x;
462         nout[0] = 0;
463         return NULL;
464     }
465     if (ex == 0) {                     /* denormals/zeros */
466         int sign;
467         uint32 xv;
468         if ((*x & 0x7FFFFFFF) == 0) {
469             /* zero: return x/0 */
470             *out = *x;
471             nout[0] = 0;
472             return NULL;
473         }
474         sign = *x & 0x80000000;
475         xv = *x & 0x7FFFFFFF;
476         ex = 1;
477         while (!(xv & 0x800000)) {
478             ex--;
479             xv = xv << 1;
480         }
481         *out = sign | 0x3F000000 | (xv & 0x7FFFFF);
482         nout[0] = ex - 0x7E;
483         return NULL;
484     }
485     *out = 0x3F000000 | (*x & 0x807FFFFF);
486     nout[0] = ex - 0x7E;
487     return NULL;                       /* ordinary number; no error */
488 }
489 
test_modf(uint32 * x,uint32 * fout,uint32 * iout)490 char *test_modf(uint32 *x, uint32 *fout, uint32 *iout) {
491     int ex = (x[0] >> 20) & 0x7FF;     /* exponent */
492     int sign = x[0] & 0x80000000;
493     uint32 fh, fl;
494 
495     if (((x[0] & 0x7FFFFFFF) | (!!x[1])) > 0x7FF00000) {
496         /*
497          * NaN input: return the same in _both_ outputs.
498          */
499         fout[0] = iout[0] = x[0];
500         fout[1] = iout[1] = x[1];
501         return NULL;
502     }
503 
504     test_rint(x, iout, 0, 0);
505     fh = x[0] - iout[0];
506     fl = x[1] - iout[1];
507     if (!fh && !fl) {                  /* no fraction part */
508         fout[0] = sign;
509         fout[1] = 0;
510         return NULL;
511     }
512     if (!(iout[0] & 0x7FFFFFFF) && !iout[1]) {   /* no integer part */
513         fout[0] = x[0];
514         fout[1] = x[1];
515         return NULL;
516     }
517     while (!(fh & 0x100000)) {
518         ex--;
519         fh = (fh << 1) | ((fl >> 31) & 1);
520         fl = (fl & 0x7FFFFFFF) << 1;
521     }
522     fout[0] = sign | (ex << 20) | (fh & 0xFFFFF);
523     fout[1] = fl;
524     return NULL;
525 }
526 
test_modff(uint32 * x,uint32 * fout,uint32 * iout)527 char *test_modff(uint32 *x, uint32 *fout, uint32 *iout) {
528     int ex = (*x >> 23) & 0xFF;        /* exponent */
529     int sign = *x & 0x80000000;
530     uint32 f;
531 
532     if ((*x & 0x7FFFFFFF) > 0x7F800000) {
533         /*
534          * NaN input: return the same in _both_ outputs.
535          */
536         *fout = *iout = *x;
537         return NULL;
538     }
539 
540     test_rintf(x, iout, 0, 0);
541     f = *x - *iout;
542     if (!f) {                          /* no fraction part */
543         *fout = sign;
544         return NULL;
545     }
546     if (!(*iout & 0x7FFFFFFF)) {       /* no integer part */
547         *fout = *x;
548         return NULL;
549     }
550     while (!(f & 0x800000)) {
551         ex--;
552         f = f << 1;
553     }
554     *fout = sign | (ex << 23) | (f & 0x7FFFFF);
555     return NULL;
556 }
557 
test_copysign(uint32 * x,uint32 * y,uint32 * out)558 char *test_copysign(uint32 *x, uint32 *y, uint32 *out)
559 {
560     int ysign = y[0] & 0x80000000;
561     int xhigh = x[0] & 0x7fffffff;
562 
563     out[0] = ysign | xhigh;
564     out[1] = x[1];
565 
566     /* There can be no error */
567     return NULL;
568 }
569 
test_copysignf(uint32 * x,uint32 * y,uint32 * out)570 char *test_copysignf(uint32 *x, uint32 *y, uint32 *out)
571 {
572     int ysign = y[0] & 0x80000000;
573     int xhigh = x[0] & 0x7fffffff;
574 
575     out[0] = ysign | xhigh;
576 
577     /* There can be no error */
578     return NULL;
579 }
580 
test_isfinite(uint32 * x,uint32 * out)581 char *test_isfinite(uint32 *x, uint32 *out)
582 {
583     int xhigh = x[0];
584     /* Being finite means that the exponent is not 0x7ff */
585     if ((xhigh & 0x7ff00000) == 0x7ff00000) out[0] = 0;
586     else out[0] = 1;
587     return NULL;
588 }
589 
test_isfinitef(uint32 * x,uint32 * out)590 char *test_isfinitef(uint32 *x, uint32 *out)
591 {
592     /* Being finite means that the exponent is not 0xff */
593     if ((x[0] & 0x7f800000) == 0x7f800000) out[0] = 0;
594     else out[0] = 1;
595     return NULL;
596 }
597 
test_isinff(uint32 * x,uint32 * out)598 char *test_isinff(uint32 *x, uint32 *out)
599 {
600     /* Being infinite means that our bottom 30 bits equate to 0x7f800000 */
601     if ((x[0] & 0x7fffffff) == 0x7f800000) out[0] = 1;
602     else out[0] = 0;
603     return NULL;
604 }
605 
test_isinf(uint32 * x,uint32 * out)606 char *test_isinf(uint32 *x, uint32 *out)
607 {
608     int xhigh = x[0];
609     int xlow = x[1];
610     /* Being infinite means that our fraction is zero and exponent is 0x7ff */
611     if (((xhigh & 0x7fffffff) == 0x7ff00000) && (xlow == 0)) out[0] = 1;
612     else out[0] = 0;
613     return NULL;
614 }
615 
test_isnanf(uint32 * x,uint32 * out)616 char *test_isnanf(uint32 *x, uint32 *out)
617 {
618     /* Being NaN means that our exponent is 0xff and non-0 fraction */
619     int exponent = x[0] & 0x7f800000;
620     int fraction = x[0] & 0x007fffff;
621     if ((exponent == 0x7f800000) && (fraction != 0)) out[0] = 1;
622     else out[0] = 0;
623     return NULL;
624 }
625 
test_isnan(uint32 * x,uint32 * out)626 char *test_isnan(uint32 *x, uint32 *out)
627 {
628     /* Being NaN means that our exponent is 0x7ff and non-0 fraction */
629     int exponent = x[0] & 0x7ff00000;
630     int fractionhigh = x[0] & 0x000fffff;
631     if ((exponent == 0x7ff00000) && ((fractionhigh != 0) || x[1] != 0))
632         out[0] = 1;
633     else out[0] = 0;
634     return NULL;
635 }
636 
test_isnormalf(uint32 * x,uint32 * out)637 char *test_isnormalf(uint32 *x, uint32 *out)
638 {
639     /* Being normal means exponent is not 0 and is not 0xff */
640     int exponent = x[0] & 0x7f800000;
641     if (exponent == 0x7f800000) out[0] = 0;
642     else if (exponent == 0) out[0] = 0;
643     else out[0] = 1;
644     return NULL;
645 }
646 
test_isnormal(uint32 * x,uint32 * out)647 char *test_isnormal(uint32 *x, uint32 *out)
648 {
649     /* Being normal means exponent is not 0 and is not 0x7ff */
650     int exponent = x[0] & 0x7ff00000;
651     if (exponent == 0x7ff00000) out[0] = 0;
652     else if (exponent == 0) out[0] = 0;
653     else out[0] = 1;
654     return NULL;
655 }
656 
test_signbitf(uint32 * x,uint32 * out)657 char *test_signbitf(uint32 *x, uint32 *out)
658 {
659     /* Sign bit is bit 31 */
660     out[0] = (x[0] >> 31) & 1;
661     return NULL;
662 }
663 
test_signbit(uint32 * x,uint32 * out)664 char *test_signbit(uint32 *x, uint32 *out)
665 {
666     /* Sign bit is bit 31 */
667     out[0] = (x[0] >> 31) & 1;
668     return NULL;
669 }
670 
test_fpclassify(uint32 * x,uint32 * out)671 char *test_fpclassify(uint32 *x, uint32 *out)
672 {
673     int exponent = (x[0] & 0x7ff00000) >> 20;
674     int fraction = (x[0] & 0x000fffff) | x[1];
675 
676     if ((exponent == 0x00) && (fraction == 0)) out[0] = 0;
677     else if ((exponent == 0x00) && (fraction != 0)) out[0] = 4;
678     else if ((exponent == 0x7ff) && (fraction == 0)) out[0] = 3;
679     else if ((exponent == 0x7ff) && (fraction != 0)) out[0] = 7;
680     else out[0] = 5;
681     return NULL;
682 }
683 
test_fpclassifyf(uint32 * x,uint32 * out)684 char *test_fpclassifyf(uint32 *x, uint32 *out)
685 {
686     int exponent = (x[0] & 0x7f800000) >> 23;
687     int fraction = x[0] & 0x007fffff;
688 
689     if ((exponent == 0x000) && (fraction == 0)) out[0] = 0;
690     else if ((exponent == 0x000) && (fraction != 0)) out[0] = 4;
691     else if ((exponent == 0xff) && (fraction == 0)) out[0] = 3;
692     else if ((exponent == 0xff) && (fraction != 0)) out[0] = 7;
693     else out[0] = 5;
694     return NULL;
695 }
696 
697 /*
698  * Internal function that compares doubles in x & y and returns -3, -2, -1, 0,
699  * 1 if they compare to be signaling, unordered, less than, equal or greater
700  * than.
701  */
fpcmp4(uint32 * x,uint32 * y)702 static int fpcmp4(uint32 *x, uint32 *y)
703 {
704     int result = 0;
705 
706     /*
707      * Sort out whether results are ordered or not to begin with
708      * NaNs have exponent 0x7ff, and non-zero fraction. Signaling NaNs take
709      * higher priority than quiet ones.
710      */
711     if ((x[0] & 0x7fffffff) >= 0x7ff80000) result = -2;
712     else if ((x[0] & 0x7fffffff) > 0x7ff00000) result = -3;
713     else if (((x[0] & 0x7fffffff) == 0x7ff00000) && (x[1] != 0)) result = -3;
714     if ((y[0] & 0x7fffffff) >= 0x7ff80000 && result != -3) result = -2;
715     else if ((y[0] & 0x7fffffff) > 0x7ff00000) result = -3;
716     else if (((y[0] & 0x7fffffff) == 0x7ff00000) && (y[1] != 0)) result = -3;
717     if (result != 0) return result;
718 
719     /*
720      * The two forms of zero are equal
721      */
722     if (((x[0] & 0x7fffffff) == 0) && x[1] == 0 &&
723         ((y[0] & 0x7fffffff) == 0) && y[1] == 0)
724         return 0;
725 
726     /*
727      * If x and y have different signs we can tell that they're not equal
728      * If x is +ve we have x > y return 1 - otherwise y is +ve return -1
729      */
730     if ((x[0] >> 31) != (y[0] >> 31))
731         return ((x[0] >> 31) == 0) - ((y[0] >> 31) == 0);
732 
733     /*
734      * Now we have both signs the same, let's do an initial compare of the
735      * values.
736      *
737      * Whoever designed IEEE754's floating point formats is very clever and
738      * earns my undying admiration.  Once you remove the sign-bit, the
739      * floating point numbers can be ordered using the standard <, ==, >
740      * operators will treating the fp-numbers as integers with that bit-
741      * pattern.
742      */
743     if ((x[0] & 0x7fffffff) < (y[0] & 0x7fffffff)) result = -1;
744     else if ((x[0] & 0x7fffffff) > (y[0] & 0x7fffffff)) result = 1;
745     else if (x[1] < y[1]) result = -1;
746     else if (x[1] > y[1]) result = 1;
747     else result = 0;
748 
749     /*
750      * Now we return the result - is x is positive (and therefore so is y) we
751      * return the plain result - otherwise we negate it and return.
752      */
753     if ((x[0] >> 31) == 0) return result;
754     else return -result;
755 }
756 
757 /*
758  * Internal function that compares floats in x & y and returns -3, -2, -1, 0,
759  * 1 if they compare to be signaling, unordered, less than, equal or greater
760  * than.
761  */
fpcmp4f(uint32 * x,uint32 * y)762 static int fpcmp4f(uint32 *x, uint32 *y)
763 {
764     int result = 0;
765 
766     /*
767      * Sort out whether results are ordered or not to begin with
768      * NaNs have exponent 0xff, and non-zero fraction - we have to handle all
769      * signaling cases over the quiet ones
770      */
771     if ((x[0] & 0x7fffffff) >= 0x7fc00000) result = -2;
772     else if ((x[0] & 0x7fffffff) > 0x7f800000) result = -3;
773     if ((y[0] & 0x7fffffff) >= 0x7fc00000 && result != -3) result = -2;
774     else if ((y[0] & 0x7fffffff) > 0x7f800000) result = -3;
775     if (result != 0) return result;
776 
777     /*
778      * The two forms of zero are equal
779      */
780     if (((x[0] & 0x7fffffff) == 0) && ((y[0] & 0x7fffffff) == 0))
781         return 0;
782 
783     /*
784      * If x and y have different signs we can tell that they're not equal
785      * If x is +ve we have x > y return 1 - otherwise y is +ve return -1
786      */
787     if ((x[0] >> 31) != (y[0] >> 31))
788         return ((x[0] >> 31) == 0) - ((y[0] >> 31) == 0);
789 
790     /*
791      * Now we have both signs the same, let's do an initial compare of the
792      * values.
793      *
794      * Whoever designed IEEE754's floating point formats is very clever and
795      * earns my undying admiration.  Once you remove the sign-bit, the
796      * floating point numbers can be ordered using the standard <, ==, >
797      * operators will treating the fp-numbers as integers with that bit-
798      * pattern.
799      */
800     if ((x[0] & 0x7fffffff) < (y[0] & 0x7fffffff)) result = -1;
801     else if ((x[0] & 0x7fffffff) > (y[0] & 0x7fffffff)) result = 1;
802     else result = 0;
803 
804     /*
805      * Now we return the result - is x is positive (and therefore so is y) we
806      * return the plain result - otherwise we negate it and return.
807      */
808     if ((x[0] >> 31) == 0) return result;
809     else return -result;
810 }
811 
test_isgreater(uint32 * x,uint32 * y,uint32 * out)812 char *test_isgreater(uint32 *x, uint32 *y, uint32 *out)
813 {
814     int result = fpcmp4(x, y);
815     *out = (result == 1);
816     return result == -3 ? "i" : NULL;
817 }
818 
test_isgreaterequal(uint32 * x,uint32 * y,uint32 * out)819 char *test_isgreaterequal(uint32 *x, uint32 *y, uint32 *out)
820 {
821     int result = fpcmp4(x, y);
822     *out = (result >= 0);
823     return result == -3 ? "i" : NULL;
824 }
825 
test_isless(uint32 * x,uint32 * y,uint32 * out)826 char *test_isless(uint32 *x, uint32 *y, uint32 *out)
827 {
828     int result = fpcmp4(x, y);
829     *out = (result == -1);
830     return result == -3 ? "i" : NULL;
831 }
832 
test_islessequal(uint32 * x,uint32 * y,uint32 * out)833 char *test_islessequal(uint32 *x, uint32 *y, uint32 *out)
834 {
835     int result = fpcmp4(x, y);
836     *out = (result == -1) || (result == 0);
837     return result == -3 ? "i" : NULL;
838 }
839 
test_islessgreater(uint32 * x,uint32 * y,uint32 * out)840 char *test_islessgreater(uint32 *x, uint32 *y, uint32 *out)
841 {
842     int result = fpcmp4(x, y);
843     *out = (result == -1) || (result == 1);
844     return result == -3 ? "i" : NULL;
845 }
846 
test_isunordered(uint32 * x,uint32 * y,uint32 * out)847 char *test_isunordered(uint32 *x, uint32 *y, uint32 *out)
848 {
849     int normal = 0;
850     int result = fpcmp4(x, y);
851 
852     test_isnormal(x, out);
853     normal |= *out;
854     test_isnormal(y, out);
855     normal |= *out;
856     *out = (result == -2) || (result == -3);
857     return result == -3 ? "i" : NULL;
858 }
859 
test_isgreaterf(uint32 * x,uint32 * y,uint32 * out)860 char *test_isgreaterf(uint32 *x, uint32 *y, uint32 *out)
861 {
862     int result = fpcmp4f(x, y);
863     *out = (result == 1);
864     return result == -3 ? "i" : NULL;
865 }
866 
test_isgreaterequalf(uint32 * x,uint32 * y,uint32 * out)867 char *test_isgreaterequalf(uint32 *x, uint32 *y, uint32 *out)
868 {
869     int result = fpcmp4f(x, y);
870     *out = (result >= 0);
871     return result == -3 ? "i" : NULL;
872 }
873 
test_islessf(uint32 * x,uint32 * y,uint32 * out)874 char *test_islessf(uint32 *x, uint32 *y, uint32 *out)
875 {
876     int result = fpcmp4f(x, y);
877     *out = (result == -1);
878     return result == -3 ? "i" : NULL;
879 }
880 
test_islessequalf(uint32 * x,uint32 * y,uint32 * out)881 char *test_islessequalf(uint32 *x, uint32 *y, uint32 *out)
882 {
883     int result = fpcmp4f(x, y);
884     *out = (result == -1) || (result == 0);
885     return result == -3 ? "i" : NULL;
886 }
887 
test_islessgreaterf(uint32 * x,uint32 * y,uint32 * out)888 char *test_islessgreaterf(uint32 *x, uint32 *y, uint32 *out)
889 {
890     int result = fpcmp4f(x, y);
891     *out = (result == -1) || (result == 1);
892     return result == -3 ? "i" : NULL;
893 }
894 
test_isunorderedf(uint32 * x,uint32 * y,uint32 * out)895 char *test_isunorderedf(uint32 *x, uint32 *y, uint32 *out)
896 {
897     int normal = 0;
898     int result = fpcmp4f(x, y);
899 
900     test_isnormalf(x, out);
901     normal |= *out;
902     test_isnormalf(y, out);
903     normal |= *out;
904     *out = (result == -2) || (result == -3);
905     return result == -3 ? "i" : NULL;
906 }
907