]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- lib/comparedf2.c - Double-precision comparisons -----------*- C -*-===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is dual licensed under the MIT and the University of Illinois Open | |
6 | // Source Licenses. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // // This file implements the following soft-float comparison routines: | |
11 | // | |
12 | // __eqdf2 __gedf2 __unorddf2 | |
13 | // __ledf2 __gtdf2 | |
14 | // __ltdf2 | |
15 | // __nedf2 | |
16 | // | |
17 | // The semantics of the routines grouped in each column are identical, so there | |
18 | // is a single implementation for each, and wrappers to provide the other names. | |
19 | // | |
20 | // The main routines behave as follows: | |
21 | // | |
22 | // __ledf2(a,b) returns -1 if a < b | |
23 | // 0 if a == b | |
24 | // 1 if a > b | |
25 | // 1 if either a or b is NaN | |
26 | // | |
27 | // __gedf2(a,b) returns -1 if a < b | |
28 | // 0 if a == b | |
29 | // 1 if a > b | |
30 | // -1 if either a or b is NaN | |
31 | // | |
32 | // __unorddf2(a,b) returns 0 if both a and b are numbers | |
33 | // 1 if either a or b is NaN | |
34 | // | |
35 | // Note that __ledf2( ) and __gedf2( ) are identical except in their handling of | |
36 | // NaN values. | |
37 | // | |
38 | //===----------------------------------------------------------------------===// | |
39 | ||
40 | #define DOUBLE_PRECISION | |
41 | #include "fp_lib.h" | |
42 | ||
43 | enum LE_RESULT { | |
44 | LE_LESS = -1, | |
45 | LE_EQUAL = 0, | |
46 | LE_GREATER = 1, | |
47 | LE_UNORDERED = 1 | |
48 | }; | |
49 | ||
50 | enum LE_RESULT __ledf2(fp_t a, fp_t b) { | |
51 | ||
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 | } | |
81 | ||
82 | enum GE_RESULT { | |
83 | GE_LESS = -1, | |
84 | GE_EQUAL = 0, | |
85 | GE_GREATER = 1, | |
86 | GE_UNORDERED = -1 // Note: different from LE_UNORDERED | |
87 | }; | |
88 | ||
89 | enum GE_RESULT __gedf2(fp_t a, fp_t b) { | |
90 | ||
91 | const srep_t aInt = toRep(a); | |
92 | const srep_t bInt = toRep(b); | |
93 | const rep_t aAbs = aInt & absMask; | |
94 | const rep_t bAbs = bInt & absMask; | |
95 | ||
96 | if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED; | |
97 | if ((aAbs | bAbs) == 0) return GE_EQUAL; | |
98 | if ((aInt & bInt) >= 0) { | |
99 | if (aInt < bInt) return GE_LESS; | |
100 | else if (aInt == bInt) return GE_EQUAL; | |
101 | else return GE_GREATER; | |
102 | } else { | |
103 | if (aInt > bInt) return GE_LESS; | |
104 | else if (aInt == bInt) return GE_EQUAL; | |
105 | else return GE_GREATER; | |
106 | } | |
107 | } | |
108 | ||
109 | int __unorddf2(fp_t a, fp_t b) { | |
110 | const rep_t aAbs = toRep(a) & absMask; | |
111 | const rep_t bAbs = toRep(b) & absMask; | |
112 | return aAbs > infRep || bAbs > infRep; | |
113 | } | |
114 | ||
115 | // The following are alternative names for the preceeding routines. | |
116 | ||
117 | enum LE_RESULT __eqdf2(fp_t a, fp_t b) { | |
118 | return __ledf2(a, b); | |
119 | } | |
120 | ||
121 | enum LE_RESULT __ltdf2(fp_t a, fp_t b) { | |
122 | return __ledf2(a, b); | |
123 | } | |
124 | ||
125 | enum LE_RESULT __nedf2(fp_t a, fp_t b) { | |
126 | return __ledf2(a, b); | |
127 | } | |
128 | ||
129 | enum GE_RESULT __gtdf2(fp_t a, fp_t b) { | |
130 | return __gedf2(a, b); | |
131 | } | |
132 |