1*0a6a1f1dSLionel Sambuc //===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc // The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6*0a6a1f1dSLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // This file implements the following soft-fp_t comparison routines:
11*0a6a1f1dSLionel Sambuc //
12*0a6a1f1dSLionel Sambuc // __eqsf2 __gesf2 __unordsf2
13*0a6a1f1dSLionel Sambuc // __lesf2 __gtsf2
14*0a6a1f1dSLionel Sambuc // __ltsf2
15*0a6a1f1dSLionel Sambuc // __nesf2
16*0a6a1f1dSLionel Sambuc //
17*0a6a1f1dSLionel Sambuc // The semantics of the routines grouped in each column are identical, so there
18*0a6a1f1dSLionel Sambuc // is a single implementation for each, and wrappers to provide the other names.
19*0a6a1f1dSLionel Sambuc //
20*0a6a1f1dSLionel Sambuc // The main routines behave as follows:
21*0a6a1f1dSLionel Sambuc //
22*0a6a1f1dSLionel Sambuc // __lesf2(a,b) returns -1 if a < b
23*0a6a1f1dSLionel Sambuc // 0 if a == b
24*0a6a1f1dSLionel Sambuc // 1 if a > b
25*0a6a1f1dSLionel Sambuc // 1 if either a or b is NaN
26*0a6a1f1dSLionel Sambuc //
27*0a6a1f1dSLionel Sambuc // __gesf2(a,b) returns -1 if a < b
28*0a6a1f1dSLionel Sambuc // 0 if a == b
29*0a6a1f1dSLionel Sambuc // 1 if a > b
30*0a6a1f1dSLionel Sambuc // -1 if either a or b is NaN
31*0a6a1f1dSLionel Sambuc //
32*0a6a1f1dSLionel Sambuc // __unordsf2(a,b) returns 0 if both a and b are numbers
33*0a6a1f1dSLionel Sambuc // 1 if either a or b is NaN
34*0a6a1f1dSLionel Sambuc //
35*0a6a1f1dSLionel Sambuc // Note that __lesf2( ) and __gesf2( ) are identical except in their handling of
36*0a6a1f1dSLionel Sambuc // NaN values.
37*0a6a1f1dSLionel Sambuc //
38*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
39*0a6a1f1dSLionel Sambuc
40*0a6a1f1dSLionel Sambuc #define SINGLE_PRECISION
41*0a6a1f1dSLionel Sambuc #include "fp_lib.h"
42*0a6a1f1dSLionel Sambuc
43*0a6a1f1dSLionel Sambuc enum LE_RESULT {
44*0a6a1f1dSLionel Sambuc LE_LESS = -1,
45*0a6a1f1dSLionel Sambuc LE_EQUAL = 0,
46*0a6a1f1dSLionel Sambuc LE_GREATER = 1,
47*0a6a1f1dSLionel Sambuc LE_UNORDERED = 1
48*0a6a1f1dSLionel Sambuc };
49*0a6a1f1dSLionel Sambuc
50*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum LE_RESULT
__lesf2(fp_t a,fp_t b)51*0a6a1f1dSLionel Sambuc __lesf2(fp_t a, fp_t b) {
52*0a6a1f1dSLionel Sambuc
53*0a6a1f1dSLionel Sambuc const srep_t aInt = toRep(a);
54*0a6a1f1dSLionel Sambuc const srep_t bInt = toRep(b);
55*0a6a1f1dSLionel Sambuc const rep_t aAbs = aInt & absMask;
56*0a6a1f1dSLionel Sambuc const rep_t bAbs = bInt & absMask;
57*0a6a1f1dSLionel Sambuc
58*0a6a1f1dSLionel Sambuc // If either a or b is NaN, they are unordered.
59*0a6a1f1dSLionel Sambuc if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
60*0a6a1f1dSLionel Sambuc
61*0a6a1f1dSLionel Sambuc // If a and b are both zeros, they are equal.
62*0a6a1f1dSLionel Sambuc if ((aAbs | bAbs) == 0) return LE_EQUAL;
63*0a6a1f1dSLionel Sambuc
64*0a6a1f1dSLionel Sambuc // If at least one of a and b is positive, we get the same result comparing
65*0a6a1f1dSLionel Sambuc // a and b as signed integers as we would with a fp_ting-point compare.
66*0a6a1f1dSLionel Sambuc if ((aInt & bInt) >= 0) {
67*0a6a1f1dSLionel Sambuc if (aInt < bInt) return LE_LESS;
68*0a6a1f1dSLionel Sambuc else if (aInt == bInt) return LE_EQUAL;
69*0a6a1f1dSLionel Sambuc else return LE_GREATER;
70*0a6a1f1dSLionel Sambuc }
71*0a6a1f1dSLionel Sambuc
72*0a6a1f1dSLionel Sambuc // Otherwise, both are negative, so we need to flip the sense of the
73*0a6a1f1dSLionel Sambuc // comparison to get the correct result. (This assumes a twos- or ones-
74*0a6a1f1dSLionel Sambuc // complement integer representation; if integers are represented in a
75*0a6a1f1dSLionel Sambuc // sign-magnitude representation, then this flip is incorrect).
76*0a6a1f1dSLionel Sambuc else {
77*0a6a1f1dSLionel Sambuc if (aInt > bInt) return LE_LESS;
78*0a6a1f1dSLionel Sambuc else if (aInt == bInt) return LE_EQUAL;
79*0a6a1f1dSLionel Sambuc else return LE_GREATER;
80*0a6a1f1dSLionel Sambuc }
81*0a6a1f1dSLionel Sambuc }
82*0a6a1f1dSLionel Sambuc
83*0a6a1f1dSLionel Sambuc enum GE_RESULT {
84*0a6a1f1dSLionel Sambuc GE_LESS = -1,
85*0a6a1f1dSLionel Sambuc GE_EQUAL = 0,
86*0a6a1f1dSLionel Sambuc GE_GREATER = 1,
87*0a6a1f1dSLionel Sambuc GE_UNORDERED = -1 // Note: different from LE_UNORDERED
88*0a6a1f1dSLionel Sambuc };
89*0a6a1f1dSLionel Sambuc
90*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum GE_RESULT
__gesf2(fp_t a,fp_t b)91*0a6a1f1dSLionel Sambuc __gesf2(fp_t a, fp_t b) {
92*0a6a1f1dSLionel Sambuc
93*0a6a1f1dSLionel Sambuc const srep_t aInt = toRep(a);
94*0a6a1f1dSLionel Sambuc const srep_t bInt = toRep(b);
95*0a6a1f1dSLionel Sambuc const rep_t aAbs = aInt & absMask;
96*0a6a1f1dSLionel Sambuc const rep_t bAbs = bInt & absMask;
97*0a6a1f1dSLionel Sambuc
98*0a6a1f1dSLionel Sambuc if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
99*0a6a1f1dSLionel Sambuc if ((aAbs | bAbs) == 0) return GE_EQUAL;
100*0a6a1f1dSLionel Sambuc if ((aInt & bInt) >= 0) {
101*0a6a1f1dSLionel Sambuc if (aInt < bInt) return GE_LESS;
102*0a6a1f1dSLionel Sambuc else if (aInt == bInt) return GE_EQUAL;
103*0a6a1f1dSLionel Sambuc else return GE_GREATER;
104*0a6a1f1dSLionel Sambuc } else {
105*0a6a1f1dSLionel Sambuc if (aInt > bInt) return GE_LESS;
106*0a6a1f1dSLionel Sambuc else if (aInt == bInt) return GE_EQUAL;
107*0a6a1f1dSLionel Sambuc else return GE_GREATER;
108*0a6a1f1dSLionel Sambuc }
109*0a6a1f1dSLionel Sambuc }
110*0a6a1f1dSLionel Sambuc
ARM_EABI_FNALIAS(fcmpun,unordsf2)111*0a6a1f1dSLionel Sambuc ARM_EABI_FNALIAS(fcmpun, unordsf2)
112*0a6a1f1dSLionel Sambuc
113*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI int
114*0a6a1f1dSLionel Sambuc __unordsf2(fp_t a, fp_t b) {
115*0a6a1f1dSLionel Sambuc const rep_t aAbs = toRep(a) & absMask;
116*0a6a1f1dSLionel Sambuc const rep_t bAbs = toRep(b) & absMask;
117*0a6a1f1dSLionel Sambuc return aAbs > infRep || bAbs > infRep;
118*0a6a1f1dSLionel Sambuc }
119*0a6a1f1dSLionel Sambuc
120*0a6a1f1dSLionel Sambuc // The following are alternative names for the preceding routines.
121*0a6a1f1dSLionel Sambuc
122*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum LE_RESULT
__eqsf2(fp_t a,fp_t b)123*0a6a1f1dSLionel Sambuc __eqsf2(fp_t a, fp_t b) {
124*0a6a1f1dSLionel Sambuc return __lesf2(a, b);
125*0a6a1f1dSLionel Sambuc }
126*0a6a1f1dSLionel Sambuc
127*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum LE_RESULT
__ltsf2(fp_t a,fp_t b)128*0a6a1f1dSLionel Sambuc __ltsf2(fp_t a, fp_t b) {
129*0a6a1f1dSLionel Sambuc return __lesf2(a, b);
130*0a6a1f1dSLionel Sambuc }
131*0a6a1f1dSLionel Sambuc
132*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum LE_RESULT
__nesf2(fp_t a,fp_t b)133*0a6a1f1dSLionel Sambuc __nesf2(fp_t a, fp_t b) {
134*0a6a1f1dSLionel Sambuc return __lesf2(a, b);
135*0a6a1f1dSLionel Sambuc }
136*0a6a1f1dSLionel Sambuc
137*0a6a1f1dSLionel Sambuc COMPILER_RT_ABI enum GE_RESULT
__gtsf2(fp_t a,fp_t b)138*0a6a1f1dSLionel Sambuc __gtsf2(fp_t a, fp_t b) {
139*0a6a1f1dSLionel Sambuc return __gesf2(a, b);
140*0a6a1f1dSLionel Sambuc }
141