Implement comparesf2/comparedf2 intrinsics.

master
whitequark 2017-12-28 03:41:14 +00:00
parent 82ee1dd760
commit f5d86476a8
3 changed files with 169 additions and 2 deletions

View File

@ -133,8 +133,8 @@ features = ["c"]
- [ ] arm/unordsf2vfp.S
- [x] ashldi3.c
- [x] ashrdi3.c
- [ ] comparedf2.c
- [ ] comparesf2.c
- [x] comparedf2.c
- [x] comparesf2.c
- [x] divdf3.c
- [x] divdi3.c
- [x] divmoddi4.c

166
src/float/cmp.rs Normal file
View File

@ -0,0 +1,166 @@
use int::{Int, CastInto};
use float::Float;
#[derive(Clone, Copy)]
enum Result {
Less,
Equal,
Greater,
Unordered
}
impl Result {
fn to_le_abi(self) -> i32 {
match self {
Result::Less => -1,
Result::Equal => 0,
Result::Greater => 1,
Result::Unordered => 1
}
}
fn to_ge_abi(self) -> i32 {
match self {
Result::Less => -1,
Result::Equal => 0,
Result::Greater => 1,
Result::Unordered => -1
}
}
}
fn cmp<F: Float>(a: F, b: F) -> Result where
u32: CastInto<F::Int>,
F::Int: CastInto<u32>,
i32: CastInto<F::Int>,
F::Int: CastInto<i32>,
{
let one = F::Int::ONE;
let zero = F::Int::ZERO;
let sign_bit = F::SIGN_MASK as F::Int;
let abs_mask = sign_bit - one;
let exponent_mask = F::EXPONENT_MASK;
let inf_rep = exponent_mask;
let a_rep = a.repr();
let b_rep = b.repr();
let a_abs = a_rep & abs_mask;
let b_abs = b_rep & abs_mask;
// If either a or b is NaN, they are unordered.
if a_abs > inf_rep || b_abs > inf_rep {
return Result::Unordered
}
// If a and b are both zeros, they are equal.
if a_abs | b_abs == zero {
return Result::Equal
}
// If at least one of a and b is positive, we get the same result comparing
// a and b as signed integers as we would with a fp_ting-point compare.
if a_rep & b_rep >= zero {
if a_rep < b_rep {
return Result::Less
} else if a_rep == b_rep {
return Result::Equal
} else {
return Result::Greater
}
}
// Otherwise, both are negative, so we need to flip the sense of the
// comparison to get the correct result. (This assumes a twos- or ones-
// complement integer representation; if integers are represented in a
// sign-magnitude representation, then this flip is incorrect).
else {
if a_rep > b_rep {
return Result::Less
} else if a_rep == b_rep {
return Result::Equal
} else {
return Result::Greater
}
}
}
fn unord<F: Float>(a: F, b: F) -> bool where
u32: CastInto<F::Int>,
F::Int: CastInto<u32>,
i32: CastInto<F::Int>,
F::Int: CastInto<i32>,
{
let one = F::Int::ONE;
let sign_bit = F::SIGN_MASK as F::Int;
let abs_mask = sign_bit - one;
let exponent_mask = F::EXPONENT_MASK;
let inf_rep = exponent_mask;
let a_rep = a.repr();
let b_rep = b.repr();
let a_abs = a_rep & abs_mask;
let b_abs = b_rep & abs_mask;
a_abs > inf_rep || b_abs > inf_rep
}
intrinsics! {
pub extern "C" fn __lesf2(a: f32, b: f32) -> i32 {
cmp(a, b).to_le_abi()
}
pub extern "C" fn __gesf2(a: f32, b: f32) -> i32 {
cmp(a, b).to_ge_abi()
}
#[arm_aeabi_alias = fcmpun]
pub extern "C" fn __unordsf2(a: f32, b: f32) -> bool {
unord(a, b)
}
pub extern "C" fn __eqsf2(a: f32, b: f32) -> bool {
cmp(a, b).to_le_abi() != 0
}
pub extern "C" fn __ltsf2(a: f32, b: f32) -> bool {
cmp(a, b).to_le_abi() != 0
}
pub extern "C" fn __nesf2(a: f32, b: f32) -> bool {
cmp(a, b).to_le_abi() != 0
}
pub extern "C" fn __gtsf2(a: f32, b: f32) -> bool {
cmp(a, b).to_ge_abi() != 0
}
pub extern "C" fn __ledf2(a: f64, b: f64) -> i32 {
cmp(a, b).to_le_abi()
}
pub extern "C" fn __gedf2(a: f64, b: f64) -> i32 {
cmp(a, b).to_ge_abi()
}
#[arm_aeabi_alias = dcmpun]
pub extern "C" fn __unorddf2(a: f64, b: f64) -> bool {
unord(a, b)
}
pub extern "C" fn __eqdf2(a: f64, b: f64) -> bool {
cmp(a, b).to_le_abi() != 0
}
pub extern "C" fn __ltdf2(a: f64, b: f64) -> bool {
cmp(a, b).to_le_abi() != 0
}
pub extern "C" fn __nedf2(a: f64, b: f64) -> bool {
cmp(a, b).to_le_abi() != 0
}
pub extern "C" fn __gtdf2(a: f32, b: f32) -> bool {
cmp(a, b).to_ge_abi() != 0
}
}

View File

@ -4,6 +4,7 @@ use core::ops;
use super::int::Int;
pub mod conv;
pub mod cmp;
pub mod add;
pub mod pow;
pub mod sub;