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