compiler_builtins/float/
cmp.rs1#![allow(unreachable_code)]
2
3use crate::float::Float;
4use crate::int::MinInt;
5use crate::support::cfg_if;
6
7cfg_if! {
10 if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
11 pub type CmpResult = i32;
13 } else if #[cfg(target_arch = "avr")] {
14 pub type CmpResult = i8;
16 } else {
17 pub type CmpResult = isize;
20 }
21}
22
23#[derive(Clone, Copy)]
24enum Result {
25 Less,
26 Equal,
27 Greater,
28 Unordered,
29}
30
31impl Result {
32 fn to_le_abi(self) -> CmpResult {
33 match self {
34 Result::Less => -1,
35 Result::Equal => 0,
36 Result::Greater => 1,
37 Result::Unordered => 1,
38 }
39 }
40
41 fn to_ge_abi(self) -> CmpResult {
42 match self {
43 Result::Less => -1,
44 Result::Equal => 0,
45 Result::Greater => 1,
46 Result::Unordered => -1,
47 }
48 }
49}
50
51fn cmp<F: Float>(a: F, b: F) -> Result {
52 let one = F::Int::ONE;
53 let zero = F::Int::ZERO;
54 let szero = F::SignedInt::ZERO;
55
56 let sign_bit = F::SIGN_MASK as F::Int;
57 let abs_mask = sign_bit - one;
58 let exponent_mask = F::EXP_MASK;
59 let inf_rep = exponent_mask;
60
61 let a_rep = a.to_bits();
62 let b_rep = b.to_bits();
63 let a_abs = a_rep & abs_mask;
64 let b_abs = b_rep & abs_mask;
65
66 if a_abs > inf_rep || b_abs > inf_rep {
68 return Result::Unordered;
69 }
70
71 if a_abs | b_abs == zero {
73 return Result::Equal;
74 }
75
76 let a_srep = a.to_bits_signed();
77 let b_srep = b.to_bits_signed();
78
79 if a_srep & b_srep >= szero {
82 if a_srep < b_srep {
83 Result::Less
84 } else if a_srep == b_srep {
85 Result::Equal
86 } else {
87 Result::Greater
88 }
89 } else if a_srep > b_srep {
94 Result::Less
95 } else if a_srep == b_srep {
96 Result::Equal
97 } else {
98 Result::Greater
99 }
100}
101
102fn unord<F: Float>(a: F, b: F) -> bool {
103 let one = F::Int::ONE;
104
105 let sign_bit = F::SIGN_MASK as F::Int;
106 let abs_mask = sign_bit - one;
107 let exponent_mask = F::EXP_MASK;
108 let inf_rep = exponent_mask;
109
110 let a_rep = a.to_bits();
111 let b_rep = b.to_bits();
112 let a_abs = a_rep & abs_mask;
113 let b_abs = b_rep & abs_mask;
114
115 a_abs > inf_rep || b_abs > inf_rep
116}
117
118intrinsics! {
119 pub extern "C" fn __lesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
120 cmp(a, b).to_le_abi()
121 }
122
123 pub extern "C" fn __gesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
124 cmp(a, b).to_ge_abi()
125 }
126
127 #[arm_aeabi_alias = __aeabi_fcmpun]
128 pub extern "C" fn __unordsf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
129 unord(a, b) as crate::float::cmp::CmpResult
130 }
131
132 pub extern "C" fn __eqsf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
133 cmp(a, b).to_le_abi()
134 }
135
136 pub extern "C" fn __ltsf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
137 cmp(a, b).to_le_abi()
138 }
139
140 pub extern "C" fn __nesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
141 cmp(a, b).to_le_abi()
142 }
143
144 pub extern "C" fn __gtsf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
145 cmp(a, b).to_ge_abi()
146 }
147
148 pub extern "C" fn __ledf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
149 cmp(a, b).to_le_abi()
150 }
151
152 pub extern "C" fn __gedf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
153 cmp(a, b).to_ge_abi()
154 }
155
156 #[arm_aeabi_alias = __aeabi_dcmpun]
157 pub extern "C" fn __unorddf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
158 unord(a, b) as crate::float::cmp::CmpResult
159 }
160
161 pub extern "C" fn __eqdf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
162 cmp(a, b).to_le_abi()
163 }
164
165 pub extern "C" fn __ltdf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
166 cmp(a, b).to_le_abi()
167 }
168
169 pub extern "C" fn __nedf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
170 cmp(a, b).to_le_abi()
171 }
172
173 pub extern "C" fn __gtdf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
174 cmp(a, b).to_ge_abi()
175 }
176}
177
178#[cfg(f128_enabled)]
179intrinsics! {
180 #[ppc_alias = __lekf2]
181 pub extern "C" fn __letf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
182 cmp(a, b).to_le_abi()
183 }
184
185 #[ppc_alias = __gekf2]
186 pub extern "C" fn __getf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
187 cmp(a, b).to_ge_abi()
188 }
189
190 #[ppc_alias = __unordkf2]
191 pub extern "C" fn __unordtf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
192 unord(a, b) as crate::float::cmp::CmpResult
193 }
194
195 #[ppc_alias = __eqkf2]
196 pub extern "C" fn __eqtf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
197 cmp(a, b).to_le_abi()
198 }
199
200 #[ppc_alias = __ltkf2]
201 pub extern "C" fn __lttf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
202 cmp(a, b).to_le_abi()
203 }
204
205 #[ppc_alias = __nekf2]
206 pub extern "C" fn __netf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
207 cmp(a, b).to_le_abi()
208 }
209
210 #[ppc_alias = __gtkf2]
211 pub extern "C" fn __gttf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
212 cmp(a, b).to_ge_abi()
213 }
214}
215
216#[cfg(target_arch = "arm")]
217intrinsics! {
218 pub extern "aapcs" fn __aeabi_fcmple(a: f32, b: f32) -> i32 {
219 (__lesf2(a, b) <= 0) as i32
220 }
221
222 pub extern "aapcs" fn __aeabi_fcmpge(a: f32, b: f32) -> i32 {
223 (__gesf2(a, b) >= 0) as i32
224 }
225
226 pub extern "aapcs" fn __aeabi_fcmpeq(a: f32, b: f32) -> i32 {
227 (__eqsf2(a, b) == 0) as i32
228 }
229
230 pub extern "aapcs" fn __aeabi_fcmplt(a: f32, b: f32) -> i32 {
231 (__ltsf2(a, b) < 0) as i32
232 }
233
234 pub extern "aapcs" fn __aeabi_fcmpgt(a: f32, b: f32) -> i32 {
235 (__gtsf2(a, b) > 0) as i32
236 }
237
238 pub extern "aapcs" fn __aeabi_dcmple(a: f64, b: f64) -> i32 {
239 (__ledf2(a, b) <= 0) as i32
240 }
241
242 pub extern "aapcs" fn __aeabi_dcmpge(a: f64, b: f64) -> i32 {
243 (__gedf2(a, b) >= 0) as i32
244 }
245
246 pub extern "aapcs" fn __aeabi_dcmpeq(a: f64, b: f64) -> i32 {
247 (__eqdf2(a, b) == 0) as i32
248 }
249
250 pub extern "aapcs" fn __aeabi_dcmplt(a: f64, b: f64) -> i32 {
251 (__ltdf2(a, b) < 0) as i32
252 }
253
254 pub extern "aapcs" fn __aeabi_dcmpgt(a: f64, b: f64) -> i32 {
255 (__gtdf2(a, b) > 0) as i32
256 }
257}