comparedf2.c revision 276851
1214571Sdim//===-- lib/comparedf2.c - Double-precision comparisons -----------*- C -*-===//
2214571Sdim//
3214571Sdim//                     The LLVM Compiler Infrastructure
4214571Sdim//
5214571Sdim// This file is dual licensed under the MIT and the University of Illinois Open
6214571Sdim// Source Licenses. See LICENSE.TXT for details.
7214571Sdim//
8214571Sdim//===----------------------------------------------------------------------===//
9214571Sdim//
10214571Sdim// // This file implements the following soft-float comparison routines:
11214571Sdim//
12214571Sdim//   __eqdf2   __gedf2   __unorddf2
13214571Sdim//   __ledf2   __gtdf2
14214571Sdim//   __ltdf2
15214571Sdim//   __nedf2
16214571Sdim//
17214571Sdim// The semantics of the routines grouped in each column are identical, so there
18214571Sdim// is a single implementation for each, and wrappers to provide the other names.
19214571Sdim//
20214571Sdim// The main routines behave as follows:
21214571Sdim//
22214571Sdim//   __ledf2(a,b) returns -1 if a < b
23214571Sdim//                         0 if a == b
24214571Sdim//                         1 if a > b
25214571Sdim//                         1 if either a or b is NaN
26214571Sdim//
27214571Sdim//   __gedf2(a,b) returns -1 if a < b
28214571Sdim//                         0 if a == b
29214571Sdim//                         1 if a > b
30214571Sdim//                        -1 if either a or b is NaN
31214571Sdim//
32214571Sdim//   __unorddf2(a,b) returns 0 if both a and b are numbers
33214571Sdim//                           1 if either a or b is NaN
34214571Sdim//
35214571Sdim// Note that __ledf2( ) and __gedf2( ) are identical except in their handling of
36214571Sdim// NaN values.
37214571Sdim//
38214571Sdim//===----------------------------------------------------------------------===//
39214571Sdim
40214571Sdim#define DOUBLE_PRECISION
41214571Sdim#include "fp_lib.h"
42214571Sdim
43214571Sdimenum LE_RESULT {
44214571Sdim    LE_LESS      = -1,
45214571Sdim    LE_EQUAL     =  0,
46214571Sdim    LE_GREATER   =  1,
47214571Sdim    LE_UNORDERED =  1
48214571Sdim};
49214571Sdim
50214571SdimCOMPILER_RT_ABI enum LE_RESULT
51214571Sdim__ledf2(fp_t a, fp_t b) {
52214571Sdim
53214571Sdim    const srep_t aInt = toRep(a);
54214571Sdim    const srep_t bInt = toRep(b);
55214571Sdim    const rep_t aAbs = aInt & absMask;
56214571Sdim    const rep_t bAbs = bInt & absMask;
57214571Sdim
58214571Sdim    // If either a or b is NaN, they are unordered.
59214571Sdim    if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
60214571Sdim
61214571Sdim    // If a and b are both zeros, they are equal.
62214571Sdim    if ((aAbs | bAbs) == 0) return LE_EQUAL;
63214571Sdim
64214571Sdim    // If at least one of a and b is positive, we get the same result comparing
65214571Sdim    // a and b as signed integers as we would with a floating-point compare.
66214571Sdim    if ((aInt & bInt) >= 0) {
67214571Sdim        if (aInt < bInt) return LE_LESS;
68214571Sdim        else if (aInt == bInt) return LE_EQUAL;
69214571Sdim        else return LE_GREATER;
70214571Sdim    }
71214571Sdim
72214571Sdim    // Otherwise, both are negative, so we need to flip the sense of the
73214571Sdim    // comparison to get the correct result.  (This assumes a twos- or ones-
74214571Sdim    // complement integer representation; if integers are represented in a
75214571Sdim    // sign-magnitude representation, then this flip is incorrect).
76214571Sdim    else {
77214571Sdim        if (aInt > bInt) return LE_LESS;
78214571Sdim        else if (aInt == bInt) return LE_EQUAL;
79214571Sdim        else return LE_GREATER;
80214571Sdim    }
81214571Sdim}
82
83enum GE_RESULT {
84    GE_LESS      = -1,
85    GE_EQUAL     =  0,
86    GE_GREATER   =  1,
87    GE_UNORDERED = -1   // Note: different from LE_UNORDERED
88};
89
90COMPILER_RT_ABI enum GE_RESULT
91__gedf2(fp_t a, fp_t b) {
92
93    const srep_t aInt = toRep(a);
94    const srep_t bInt = toRep(b);
95    const rep_t aAbs = aInt & absMask;
96    const rep_t bAbs = bInt & absMask;
97
98    if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
99    if ((aAbs | bAbs) == 0) return GE_EQUAL;
100    if ((aInt & bInt) >= 0) {
101        if (aInt < bInt) return GE_LESS;
102        else if (aInt == bInt) return GE_EQUAL;
103        else return GE_GREATER;
104    } else {
105        if (aInt > bInt) return GE_LESS;
106        else if (aInt == bInt) return GE_EQUAL;
107        else return GE_GREATER;
108    }
109}
110
111ARM_EABI_FNALIAS(dcmpun, unorddf2)
112
113COMPILER_RT_ABI int
114__unorddf2(fp_t a, fp_t b) {
115    const rep_t aAbs = toRep(a) & absMask;
116    const rep_t bAbs = toRep(b) & absMask;
117    return aAbs > infRep || bAbs > infRep;
118}
119
120// The following are alternative names for the preceding routines.
121
122COMPILER_RT_ABI enum LE_RESULT
123__eqdf2(fp_t a, fp_t b) {
124    return __ledf2(a, b);
125}
126
127COMPILER_RT_ABI enum LE_RESULT
128__ltdf2(fp_t a, fp_t b) {
129    return __ledf2(a, b);
130}
131
132COMPILER_RT_ABI enum LE_RESULT
133__nedf2(fp_t a, fp_t b) {
134    return __ledf2(a, b);
135}
136
137COMPILER_RT_ABI enum GE_RESULT
138__gtdf2(fp_t a, fp_t b) {
139    return __gedf2(a, b);
140}
141
142