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