1214152Sed//===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===//
2214152Sed//
3214152Sed//                     The LLVM Compiler Infrastructure
4214152Sed//
5222656Sed// This file is dual licensed under the MIT and the University of Illinois Open
6222656Sed// Source Licenses. See LICENSE.TXT for details.
7214152Sed//
8214152Sed//===----------------------------------------------------------------------===//
9214152Sed//
10214152Sed// This file implements the following soft-fp_t comparison routines:
11214152Sed//
12214152Sed//   __eqsf2   __gesf2   __unordsf2
13214152Sed//   __lesf2   __gtsf2
14214152Sed//   __ltsf2
15214152Sed//   __nesf2
16214152Sed//
17214152Sed// The semantics of the routines grouped in each column are identical, so there
18214152Sed// is a single implementation for each, and wrappers to provide the other names.
19214152Sed//
20214152Sed// The main routines behave as follows:
21214152Sed//
22214152Sed//   __lesf2(a,b) returns -1 if a < b
23214152Sed//                         0 if a == b
24214152Sed//                         1 if a > b
25214152Sed//                         1 if either a or b is NaN
26214152Sed//
27214152Sed//   __gesf2(a,b) returns -1 if a < b
28214152Sed//                         0 if a == b
29214152Sed//                         1 if a > b
30214152Sed//                        -1 if either a or b is NaN
31214152Sed//
32214152Sed//   __unordsf2(a,b) returns 0 if both a and b are numbers
33214152Sed//                           1 if either a or b is NaN
34214152Sed//
35214152Sed// Note that __lesf2( ) and __gesf2( ) are identical except in their handling of
36214152Sed// NaN values.
37214152Sed//
38214152Sed//===----------------------------------------------------------------------===//
39214152Sed
40214152Sed#define SINGLE_PRECISION
41214152Sed#include "fp_lib.h"
42214152Sed
43214152Sedenum LE_RESULT {
44214152Sed    LE_LESS      = -1,
45214152Sed    LE_EQUAL     =  0,
46214152Sed    LE_GREATER   =  1,
47214152Sed    LE_UNORDERED =  1
48214152Sed};
49214152Sed
50214152Sedenum LE_RESULT __lesf2(fp_t a, fp_t b) {
51214152Sed
52214152Sed    const srep_t aInt = toRep(a);
53214152Sed    const srep_t bInt = toRep(b);
54214152Sed    const rep_t aAbs = aInt & absMask;
55214152Sed    const rep_t bAbs = bInt & absMask;
56214152Sed
57214152Sed    // If either a or b is NaN, they are unordered.
58214152Sed    if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
59214152Sed
60214152Sed    // If a and b are both zeros, they are equal.
61214152Sed    if ((aAbs | bAbs) == 0) return LE_EQUAL;
62214152Sed
63214152Sed    // If at least one of a and b is positive, we get the same result comparing
64214152Sed    // a and b as signed integers as we would with a fp_ting-point compare.
65214152Sed    if ((aInt & bInt) >= 0) {
66214152Sed        if (aInt < bInt) return LE_LESS;
67214152Sed        else if (aInt == bInt) return LE_EQUAL;
68214152Sed        else return LE_GREATER;
69214152Sed    }
70214152Sed
71214152Sed    // Otherwise, both are negative, so we need to flip the sense of the
72214152Sed    // comparison to get the correct result.  (This assumes a twos- or ones-
73214152Sed    // complement integer representation; if integers are represented in a
74214152Sed    // sign-magnitude representation, then this flip is incorrect).
75214152Sed    else {
76214152Sed        if (aInt > bInt) return LE_LESS;
77214152Sed        else if (aInt == bInt) return LE_EQUAL;
78214152Sed        else return LE_GREATER;
79214152Sed    }
80214152Sed}
81214152Sed
82214152Sedenum GE_RESULT {
83214152Sed    GE_LESS      = -1,
84214152Sed    GE_EQUAL     =  0,
85214152Sed    GE_GREATER   =  1,
86214152Sed    GE_UNORDERED = -1   // Note: different from LE_UNORDERED
87214152Sed};
88214152Sed
89214152Sedenum GE_RESULT __gesf2(fp_t a, fp_t b) {
90214152Sed
91214152Sed    const srep_t aInt = toRep(a);
92214152Sed    const srep_t bInt = toRep(b);
93214152Sed    const rep_t aAbs = aInt & absMask;
94214152Sed    const rep_t bAbs = bInt & absMask;
95214152Sed
96214152Sed    if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
97214152Sed    if ((aAbs | bAbs) == 0) return GE_EQUAL;
98214152Sed    if ((aInt & bInt) >= 0) {
99214152Sed        if (aInt < bInt) return GE_LESS;
100214152Sed        else if (aInt == bInt) return GE_EQUAL;
101214152Sed        else return GE_GREATER;
102214152Sed    } else {
103214152Sed        if (aInt > bInt) return GE_LESS;
104214152Sed        else if (aInt == bInt) return GE_EQUAL;
105214152Sed        else return GE_GREATER;
106214152Sed    }
107214152Sed}
108214152Sed
109214152Sedint __unordsf2(fp_t a, fp_t b) {
110214152Sed    const rep_t aAbs = toRep(a) & absMask;
111214152Sed    const rep_t bAbs = toRep(b) & absMask;
112214152Sed    return aAbs > infRep || bAbs > infRep;
113214152Sed}
114214152Sed
115214152Sed// The following are alternative names for the preceeding routines.
116214152Sed
117214152Sedenum LE_RESULT __eqsf2(fp_t a, fp_t b) {
118214152Sed    return __lesf2(a, b);
119214152Sed}
120214152Sed
121214152Sedenum LE_RESULT __ltsf2(fp_t a, fp_t b) {
122214152Sed    return __lesf2(a, b);
123214152Sed}
124214152Sed
125214152Sedenum LE_RESULT __nesf2(fp_t a, fp_t b) {
126214152Sed    return __lesf2(a, b);
127214152Sed}
128214152Sed
129214152Sedenum GE_RESULT __gtsf2(fp_t a, fp_t b) {
130214152Sed    return __gesf2(a, b);
131214152Sed}
132