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