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