xref: /minix3/sys/external/bsd/compiler_rt/dist/lib/builtins/comparesf2.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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