blob: 56825e4a8f4943ec9b7f24ce2143e2e6224761d3 [file] [log] [blame]
Daniel Dunbarce750fd2011-03-25 18:45:39 +00001//===-- lib/comparedf2.c - Double-precision comparisons -----------*- C -*-===//
Stephen Canone5086322010-07-01 15:52:42 +00002//
Chandler Carruth7a739a02019-01-19 10:56:40 +00003// 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
Stephen Canon5c6d2ec2010-07-01 17:58:24 +00006//
7//===----------------------------------------------------------------------===//
8//
9// // This file implements the following soft-float comparison routines:
10//
11// __eqdf2 __gedf2 __unorddf2
Stephen Canone5086322010-07-01 15:52:42 +000012// __ledf2 __gtdf2
13// __ltdf2
14// __nedf2
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// __ledf2(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// __gedf2(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// __unorddf2(a,b) returns 0 if both a and b are numbers
32// 1 if either a or b is NaN
33//
34// Note that __ledf2( ) and __gedf2( ) are identical except in their handling of
35// NaN values.
Stephen Canon5c6d2ec2010-07-01 17:58:24 +000036//
37//===----------------------------------------------------------------------===//
38
39#define DOUBLE_PRECISION
40#include "fp_lib.h"
Stephen Canone5086322010-07-01 15:52:42 +000041
Daniel Dunbarce750fd2011-03-25 18:45:39 +000042enum LE_RESULT {
43 LE_LESS = -1,
44 LE_EQUAL = 0,
45 LE_GREATER = 1,
46 LE_UNORDERED = 1
47};
48
Joerg Sonnenbergerbfbb8bb2014-03-01 15:30:50 +000049COMPILER_RT_ABI enum LE_RESULT
50__ledf2(fp_t a, fp_t b) {
Stephen Canone5086322010-07-01 15:52:42 +000051
52 const srep_t aInt = toRep(a);
53 const srep_t bInt = toRep(b);
54 const rep_t aAbs = aInt & absMask;
55 const rep_t bAbs = bInt & absMask;
56
57 // If either a or b is NaN, they are unordered.
58 if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
59
60 // If a and b are both zeros, they are equal.
61 if ((aAbs | bAbs) == 0) return LE_EQUAL;
62
63 // If at least one of a and b is positive, we get the same result comparing
64 // a and b as signed integers as we would with a floating-point compare.
65 if ((aInt & bInt) >= 0) {
66 if (aInt < bInt) return LE_LESS;
67 else if (aInt == bInt) return LE_EQUAL;
68 else return LE_GREATER;
69 }
70
71 // Otherwise, both are negative, so we need to flip the sense of the
72 // comparison to get the correct result. (This assumes a twos- or ones-
73 // complement integer representation; if integers are represented in a
74 // sign-magnitude representation, then this flip is incorrect).
75 else {
76 if (aInt > bInt) return LE_LESS;
77 else if (aInt == bInt) return LE_EQUAL;
78 else return LE_GREATER;
79 }
80}
Daniel Dunbarce750fd2011-03-25 18:45:39 +000081
Saleem Abdulrasoold3a8aba2015-08-21 04:39:52 +000082#if defined(__ELF__)
Josh Gaoc8525162015-08-21 02:51:17 +000083// Alias for libgcc compatibility
84FNALIAS(__cmpdf2, __ledf2);
Saleem Abdulrasoold3a8aba2015-08-21 04:39:52 +000085#endif
Josh Gaoc8525162015-08-21 02:51:17 +000086
Daniel Dunbarce750fd2011-03-25 18:45:39 +000087enum GE_RESULT {
88 GE_LESS = -1,
89 GE_EQUAL = 0,
90 GE_GREATER = 1,
91 GE_UNORDERED = -1 // Note: different from LE_UNORDERED
92};
93
Joerg Sonnenbergerbfbb8bb2014-03-01 15:30:50 +000094COMPILER_RT_ABI enum GE_RESULT
95__gedf2(fp_t a, fp_t b) {
Daniel Dunbarce750fd2011-03-25 18:45:39 +000096
97 const srep_t aInt = toRep(a);
98 const srep_t bInt = toRep(b);
99 const rep_t aAbs = aInt & absMask;
100 const rep_t bAbs = bInt & absMask;
101
102 if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
103 if ((aAbs | bAbs) == 0) return GE_EQUAL;
104 if ((aInt & bInt) >= 0) {
105 if (aInt < bInt) return GE_LESS;
106 else if (aInt == bInt) return GE_EQUAL;
107 else return GE_GREATER;
108 } else {
109 if (aInt > bInt) return GE_LESS;
110 else if (aInt == bInt) return GE_EQUAL;
111 else return GE_GREATER;
112 }
113}
114
Joerg Sonnenbergerbfbb8bb2014-03-01 15:30:50 +0000115COMPILER_RT_ABI int
116__unorddf2(fp_t a, fp_t b) {
Daniel Dunbarce750fd2011-03-25 18:45:39 +0000117 const rep_t aAbs = toRep(a) & absMask;
118 const rep_t bAbs = toRep(b) & absMask;
119 return aAbs > infRep || bAbs > infRep;
120}
121
Alp Tokeref90fb82014-05-15 02:22:34 +0000122// The following are alternative names for the preceding routines.
Daniel Dunbarce750fd2011-03-25 18:45:39 +0000123
Joerg Sonnenbergerbfbb8bb2014-03-01 15:30:50 +0000124COMPILER_RT_ABI enum LE_RESULT
125__eqdf2(fp_t a, fp_t b) {
Daniel Dunbarce750fd2011-03-25 18:45:39 +0000126 return __ledf2(a, b);
127}
128
Joerg Sonnenbergerbfbb8bb2014-03-01 15:30:50 +0000129COMPILER_RT_ABI enum LE_RESULT
130__ltdf2(fp_t a, fp_t b) {
Daniel Dunbarce750fd2011-03-25 18:45:39 +0000131 return __ledf2(a, b);
132}
133
Joerg Sonnenbergerbfbb8bb2014-03-01 15:30:50 +0000134COMPILER_RT_ABI enum LE_RESULT
135__nedf2(fp_t a, fp_t b) {
Daniel Dunbarce750fd2011-03-25 18:45:39 +0000136 return __ledf2(a, b);
137}
138
Joerg Sonnenbergerbfbb8bb2014-03-01 15:30:50 +0000139COMPILER_RT_ABI enum GE_RESULT
140__gtdf2(fp_t a, fp_t b) {
Daniel Dunbarce750fd2011-03-25 18:45:39 +0000141 return __gedf2(a, b);
142}
143
Saleem Abdulrasool99e2e662017-05-16 16:41:37 +0000144#if defined(__ARM_EABI__)
Eli Friedman83774b42017-10-03 21:25:07 +0000145#if defined(COMPILER_RT_ARMHF_TARGET)
Saleem Abdulrasool99e2e662017-05-16 16:41:37 +0000146AEABI_RTABI int __aeabi_dcmpun(fp_t a, fp_t b) {
147 return __unorddf2(a, b);
148}
Eli Friedman83774b42017-10-03 21:25:07 +0000149#else
150AEABI_RTABI int __aeabi_dcmpun(fp_t a, fp_t b) COMPILER_RT_ALIAS(__unorddf2);
Saleem Abdulrasool99e2e662017-05-16 16:41:37 +0000151#endif
Eli Friedman83774b42017-10-03 21:25:07 +0000152#endif