xref: /minix3/sys/external/bsd/compiler_rt/dist/lib/builtins/comparetf2.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //===-- lib/comparetf2.c - Quad-precision comparisons -------------*- C -*-===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6*0a6a1f1dSLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // // This file implements the following soft-float comparison routines:
11*0a6a1f1dSLionel Sambuc //
12*0a6a1f1dSLionel Sambuc //   __eqtf2   __getf2   __unordtf2
13*0a6a1f1dSLionel Sambuc //   __letf2   __gttf2
14*0a6a1f1dSLionel Sambuc //   __lttf2
15*0a6a1f1dSLionel Sambuc //   __netf2
16*0a6a1f1dSLionel Sambuc //
17*0a6a1f1dSLionel Sambuc // The semantics of the routines grouped in each column are identical, so there
18*0a6a1f1dSLionel Sambuc // is a single implementation for each, and wrappers to provide the other names.
19*0a6a1f1dSLionel Sambuc //
20*0a6a1f1dSLionel Sambuc // The main routines behave as follows:
21*0a6a1f1dSLionel Sambuc //
22*0a6a1f1dSLionel Sambuc //   __letf2(a,b) returns -1 if a < b
23*0a6a1f1dSLionel Sambuc //                         0 if a == b
24*0a6a1f1dSLionel Sambuc //                         1 if a > b
25*0a6a1f1dSLionel Sambuc //                         1 if either a or b is NaN
26*0a6a1f1dSLionel Sambuc //
27*0a6a1f1dSLionel Sambuc //   __getf2(a,b) returns -1 if a < b
28*0a6a1f1dSLionel Sambuc //                         0 if a == b
29*0a6a1f1dSLionel Sambuc //                         1 if a > b
30*0a6a1f1dSLionel Sambuc //                        -1 if either a or b is NaN
31*0a6a1f1dSLionel Sambuc //
32*0a6a1f1dSLionel Sambuc //   __unordtf2(a,b) returns 0 if both a and b are numbers
33*0a6a1f1dSLionel Sambuc //                           1 if either a or b is NaN
34*0a6a1f1dSLionel Sambuc //
35*0a6a1f1dSLionel Sambuc // Note that __letf2( ) and __getf2( ) are identical except in their handling of
36*0a6a1f1dSLionel Sambuc // NaN values.
37*0a6a1f1dSLionel Sambuc //
38*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
39*0a6a1f1dSLionel Sambuc 
40*0a6a1f1dSLionel Sambuc #define QUAD_PRECISION
41*0a6a1f1dSLionel Sambuc #include "fp_lib.h"
42*0a6a1f1dSLionel Sambuc 
43*0a6a1f1dSLionel Sambuc #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
44*0a6a1f1dSLionel Sambuc enum LE_RESULT {
45*0a6a1f1dSLionel Sambuc     LE_LESS      = -1,
46*0a6a1f1dSLionel Sambuc     LE_EQUAL     =  0,
47*0a6a1f1dSLionel Sambuc     LE_GREATER   =  1,
48*0a6a1f1dSLionel Sambuc     LE_UNORDERED =  1
49*0a6a1f1dSLionel Sambuc };
50*0a6a1f1dSLionel Sambuc 
__letf2(fp_t a,fp_t b)51*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum LE_RESULT __letf2(fp_t a, fp_t b) {
52*0a6a1f1dSLionel Sambuc 
53*0a6a1f1dSLionel Sambuc     const srep_t aInt = toRep(a);
54*0a6a1f1dSLionel Sambuc     const srep_t bInt = toRep(b);
55*0a6a1f1dSLionel Sambuc     const rep_t aAbs = aInt & absMask;
56*0a6a1f1dSLionel Sambuc     const rep_t bAbs = bInt & absMask;
57*0a6a1f1dSLionel Sambuc 
58*0a6a1f1dSLionel Sambuc     // If either a or b is NaN, they are unordered.
59*0a6a1f1dSLionel Sambuc     if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
60*0a6a1f1dSLionel Sambuc 
61*0a6a1f1dSLionel Sambuc     // If a and b are both zeros, they are equal.
62*0a6a1f1dSLionel Sambuc     if ((aAbs | bAbs) == 0) return LE_EQUAL;
63*0a6a1f1dSLionel Sambuc 
64*0a6a1f1dSLionel Sambuc     // If at least one of a and b is positive, we get the same result comparing
65*0a6a1f1dSLionel Sambuc     // a and b as signed integers as we would with a floating-point compare.
66*0a6a1f1dSLionel Sambuc     if ((aInt & bInt) >= 0) {
67*0a6a1f1dSLionel Sambuc         if (aInt < bInt) return LE_LESS;
68*0a6a1f1dSLionel Sambuc         else if (aInt == bInt) return LE_EQUAL;
69*0a6a1f1dSLionel Sambuc         else return LE_GREATER;
70*0a6a1f1dSLionel Sambuc     }
71*0a6a1f1dSLionel Sambuc     else {
72*0a6a1f1dSLionel Sambuc         // Otherwise, both are negative, so we need to flip the sense of the
73*0a6a1f1dSLionel Sambuc         // comparison to get the correct result.  (This assumes a twos- or ones-
74*0a6a1f1dSLionel Sambuc         // complement integer representation; if integers are represented in a
75*0a6a1f1dSLionel Sambuc         // sign-magnitude representation, then this flip is incorrect).
76*0a6a1f1dSLionel Sambuc         if (aInt > bInt) return LE_LESS;
77*0a6a1f1dSLionel Sambuc         else if (aInt == bInt) return LE_EQUAL;
78*0a6a1f1dSLionel Sambuc         else return LE_GREATER;
79*0a6a1f1dSLionel Sambuc     }
80*0a6a1f1dSLionel Sambuc }
81*0a6a1f1dSLionel Sambuc 
82*0a6a1f1dSLionel Sambuc enum GE_RESULT {
83*0a6a1f1dSLionel Sambuc     GE_LESS      = -1,
84*0a6a1f1dSLionel Sambuc     GE_EQUAL     =  0,
85*0a6a1f1dSLionel Sambuc     GE_GREATER   =  1,
86*0a6a1f1dSLionel Sambuc     GE_UNORDERED = -1   // Note: different from LE_UNORDERED
87*0a6a1f1dSLionel Sambuc };
88*0a6a1f1dSLionel Sambuc 
__getf2(fp_t a,fp_t b)89*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum GE_RESULT __getf2(fp_t a, fp_t b) {
90*0a6a1f1dSLionel Sambuc 
91*0a6a1f1dSLionel Sambuc     const srep_t aInt = toRep(a);
92*0a6a1f1dSLionel Sambuc     const srep_t bInt = toRep(b);
93*0a6a1f1dSLionel Sambuc     const rep_t aAbs = aInt & absMask;
94*0a6a1f1dSLionel Sambuc     const rep_t bAbs = bInt & absMask;
95*0a6a1f1dSLionel Sambuc 
96*0a6a1f1dSLionel Sambuc     if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
97*0a6a1f1dSLionel Sambuc     if ((aAbs | bAbs) == 0) return GE_EQUAL;
98*0a6a1f1dSLionel Sambuc     if ((aInt & bInt) >= 0) {
99*0a6a1f1dSLionel Sambuc         if (aInt < bInt) return GE_LESS;
100*0a6a1f1dSLionel Sambuc         else if (aInt == bInt) return GE_EQUAL;
101*0a6a1f1dSLionel Sambuc         else return GE_GREATER;
102*0a6a1f1dSLionel Sambuc     } else {
103*0a6a1f1dSLionel Sambuc         if (aInt > bInt) return GE_LESS;
104*0a6a1f1dSLionel Sambuc         else if (aInt == bInt) return GE_EQUAL;
105*0a6a1f1dSLionel Sambuc         else return GE_GREATER;
106*0a6a1f1dSLionel Sambuc     }
107*0a6a1f1dSLionel Sambuc }
108*0a6a1f1dSLionel Sambuc 
__unordtf2(fp_t a,fp_t b)109*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI int __unordtf2(fp_t a, fp_t b) {
110*0a6a1f1dSLionel Sambuc     const rep_t aAbs = toRep(a) & absMask;
111*0a6a1f1dSLionel Sambuc     const rep_t bAbs = toRep(b) & absMask;
112*0a6a1f1dSLionel Sambuc     return aAbs > infRep || bAbs > infRep;
113*0a6a1f1dSLionel Sambuc }
114*0a6a1f1dSLionel Sambuc 
115*0a6a1f1dSLionel Sambuc // The following are alternative names for the preceding routines.
116*0a6a1f1dSLionel Sambuc 
__eqtf2(fp_t a,fp_t b)117*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum LE_RESULT __eqtf2(fp_t a, fp_t b) {
118*0a6a1f1dSLionel Sambuc     return __letf2(a, b);
119*0a6a1f1dSLionel Sambuc }
120*0a6a1f1dSLionel Sambuc 
__lttf2(fp_t a,fp_t b)121*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum LE_RESULT __lttf2(fp_t a, fp_t b) {
122*0a6a1f1dSLionel Sambuc     return __letf2(a, b);
123*0a6a1f1dSLionel Sambuc }
124*0a6a1f1dSLionel Sambuc 
__netf2(fp_t a,fp_t b)125*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum LE_RESULT __netf2(fp_t a, fp_t b) {
126*0a6a1f1dSLionel Sambuc     return __letf2(a, b);
127*0a6a1f1dSLionel Sambuc }
128*0a6a1f1dSLionel Sambuc 
__gttf2(fp_t a,fp_t b)129*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum GE_RESULT __gttf2(fp_t a, fp_t b) {
130*0a6a1f1dSLionel Sambuc     return __getf2(a, b);
131*0a6a1f1dSLionel Sambuc }
132*0a6a1f1dSLionel Sambuc 
133*0a6a1f1dSLionel Sambuc #endif
134