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