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
__letf2(fp_t a,fp_t b)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
__getf2(fp_t a,fp_t b)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
COMPILER_RT_ALIAS(__getf2,__gttf2)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