Skip to content

Commit f5d8647

Browse files
committed
Implement comparesf2/comparedf2 intrinsics.
1 parent 82ee1dd commit f5d8647

File tree

3 files changed

+169
-2
lines changed

3 files changed

+169
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ features = ["c"]
133133
- [ ] arm/unordsf2vfp.S
134134
- [x] ashldi3.c
135135
- [x] ashrdi3.c
136-
- [ ] comparedf2.c
137-
- [ ] comparesf2.c
136+
- [x] comparedf2.c
137+
- [x] comparesf2.c
138138
- [x] divdf3.c
139139
- [x] divdi3.c
140140
- [x] divmoddi4.c

src/float/cmp.rs

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
use int::{Int, CastInto};
2+
use float::Float;
3+
4+
#[derive(Clone, Copy)]
5+
enum Result {
6+
Less,
7+
Equal,
8+
Greater,
9+
Unordered
10+
}
11+
12+
impl Result {
13+
fn to_le_abi(self) -> i32 {
14+
match self {
15+
Result::Less => -1,
16+
Result::Equal => 0,
17+
Result::Greater => 1,
18+
Result::Unordered => 1
19+
}
20+
}
21+
22+
fn to_ge_abi(self) -> i32 {
23+
match self {
24+
Result::Less => -1,
25+
Result::Equal => 0,
26+
Result::Greater => 1,
27+
Result::Unordered => -1
28+
}
29+
}
30+
}
31+
32+
fn cmp<F: Float>(a: F, b: F) -> Result where
33+
u32: CastInto<F::Int>,
34+
F::Int: CastInto<u32>,
35+
i32: CastInto<F::Int>,
36+
F::Int: CastInto<i32>,
37+
{
38+
let one = F::Int::ONE;
39+
let zero = F::Int::ZERO;
40+
41+
let sign_bit = F::SIGN_MASK as F::Int;
42+
let abs_mask = sign_bit - one;
43+
let exponent_mask = F::EXPONENT_MASK;
44+
let inf_rep = exponent_mask;
45+
46+
let a_rep = a.repr();
47+
let b_rep = b.repr();
48+
let a_abs = a_rep & abs_mask;
49+
let b_abs = b_rep & abs_mask;
50+
51+
// If either a or b is NaN, they are unordered.
52+
if a_abs > inf_rep || b_abs > inf_rep {
53+
return Result::Unordered
54+
}
55+
56+
// If a and b are both zeros, they are equal.
57+
if a_abs | b_abs == zero {
58+
return Result::Equal
59+
}
60+
61+
// If at least one of a and b is positive, we get the same result comparing
62+
// a and b as signed integers as we would with a fp_ting-point compare.
63+
if a_rep & b_rep >= zero {
64+
if a_rep < b_rep {
65+
return Result::Less
66+
} else if a_rep == b_rep {
67+
return Result::Equal
68+
} else {
69+
return Result::Greater
70+
}
71+
}
72+
73+
// Otherwise, both are negative, so we need to flip the sense of the
74+
// comparison to get the correct result. (This assumes a twos- or ones-
75+
// complement integer representation; if integers are represented in a
76+
// sign-magnitude representation, then this flip is incorrect).
77+
else {
78+
if a_rep > b_rep {
79+
return Result::Less
80+
} else if a_rep == b_rep {
81+
return Result::Equal
82+
} else {
83+
return Result::Greater
84+
}
85+
}
86+
}
87+
fn unord<F: Float>(a: F, b: F) -> bool where
88+
u32: CastInto<F::Int>,
89+
F::Int: CastInto<u32>,
90+
i32: CastInto<F::Int>,
91+
F::Int: CastInto<i32>,
92+
{
93+
let one = F::Int::ONE;
94+
95+
let sign_bit = F::SIGN_MASK as F::Int;
96+
let abs_mask = sign_bit - one;
97+
let exponent_mask = F::EXPONENT_MASK;
98+
let inf_rep = exponent_mask;
99+
100+
let a_rep = a.repr();
101+
let b_rep = b.repr();
102+
let a_abs = a_rep & abs_mask;
103+
let b_abs = b_rep & abs_mask;
104+
105+
a_abs > inf_rep || b_abs > inf_rep
106+
}
107+
108+
intrinsics! {
109+
pub extern "C" fn __lesf2(a: f32, b: f32) -> i32 {
110+
cmp(a, b).to_le_abi()
111+
}
112+
113+
pub extern "C" fn __gesf2(a: f32, b: f32) -> i32 {
114+
cmp(a, b).to_ge_abi()
115+
}
116+
117+
#[arm_aeabi_alias = fcmpun]
118+
pub extern "C" fn __unordsf2(a: f32, b: f32) -> bool {
119+
unord(a, b)
120+
}
121+
122+
pub extern "C" fn __eqsf2(a: f32, b: f32) -> bool {
123+
cmp(a, b).to_le_abi() != 0
124+
}
125+
126+
pub extern "C" fn __ltsf2(a: f32, b: f32) -> bool {
127+
cmp(a, b).to_le_abi() != 0
128+
}
129+
130+
pub extern "C" fn __nesf2(a: f32, b: f32) -> bool {
131+
cmp(a, b).to_le_abi() != 0
132+
}
133+
134+
pub extern "C" fn __gtsf2(a: f32, b: f32) -> bool {
135+
cmp(a, b).to_ge_abi() != 0
136+
}
137+
138+
pub extern "C" fn __ledf2(a: f64, b: f64) -> i32 {
139+
cmp(a, b).to_le_abi()
140+
}
141+
142+
pub extern "C" fn __gedf2(a: f64, b: f64) -> i32 {
143+
cmp(a, b).to_ge_abi()
144+
}
145+
146+
#[arm_aeabi_alias = dcmpun]
147+
pub extern "C" fn __unorddf2(a: f64, b: f64) -> bool {
148+
unord(a, b)
149+
}
150+
151+
pub extern "C" fn __eqdf2(a: f64, b: f64) -> bool {
152+
cmp(a, b).to_le_abi() != 0
153+
}
154+
155+
pub extern "C" fn __ltdf2(a: f64, b: f64) -> bool {
156+
cmp(a, b).to_le_abi() != 0
157+
}
158+
159+
pub extern "C" fn __nedf2(a: f64, b: f64) -> bool {
160+
cmp(a, b).to_le_abi() != 0
161+
}
162+
163+
pub extern "C" fn __gtdf2(a: f32, b: f32) -> bool {
164+
cmp(a, b).to_ge_abi() != 0
165+
}
166+
}

src/float/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use core::ops;
44
use super::int::Int;
55

66
pub mod conv;
7+
pub mod cmp;
78
pub mod add;
89
pub mod pow;
910
pub mod sub;

0 commit comments

Comments
 (0)