Add test cases for Mul[s/d]f3vfp and Div[s/d]f3vfp

for ARM targets only
master
Paolo Teti 2018-01-30 20:15:37 +01:00
parent f42b9e0bad
commit 9e04723812
5 changed files with 371 additions and 0 deletions

339
build.rs
View File

@ -130,10 +130,14 @@ mod tests {
// float/mul.rs
Mulsf3,
Muldf3,
Mulsf3vfp,
Muldf3vfp,
// float/div.rs
Divsf3,
Divdf3,
Divsf3vfp,
Divdf3vfp,
// int/addsub.rs
AddU128,
@ -4203,6 +4207,171 @@ fn muldf3() {
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Mulsf3vfp {
a: u32, // f32
b: u32, // f32
c: u32, // f32
}
impl TestCase for Mulsf3vfp {
fn name() -> &'static str {
"mulsf3vfp"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_large_f32(rng);
let b = gen_large_f32(rng);
let c = a * b;
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() || c.is_nan() {
return None;
}
Some(
Mulsf3vfp {
a: to_u32(a),
b: to_u32(b),
c: to_u32(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
use compiler_builtins::float::mul::__mulsf3vfp;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32, u32), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn mulsf3vfp() {
for &((a, b), c) in TEST_CASES {
let c_ = __mulsf3vfp(mk_f32(a), mk_f32(b));
assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Muldf3vfp {
a: u64, // f64
b: u64, // f64
c: u64, // f64
}
impl TestCase for Muldf3vfp {
fn name() -> &'static str {
"muldf3vfp"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_large_f64(rng);
let b = gen_large_f64(rng);
let c = a * b;
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() || c.is_nan() {
return None;
}
Some(
Muldf3vfp {
a: to_u64(a),
b: to_u64(b),
c: to_u64(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
use compiler_builtins::float::mul::__muldf3vfp;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64, u64), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn muldf3vfp() {
for &((a, b), c) in TEST_CASES {
let c_ = __muldf3vfp(mk_f64(a), mk_f64(b));
assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Divsf3 {
a: u32, // f32
@ -4384,6 +4553,176 @@ fn divdf3() {
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Divsf3vfp {
a: u32, // f32
b: u32, // f32
c: u32, // f32
}
impl TestCase for Divsf3vfp {
fn name() -> &'static str {
"divsf3vfp"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_large_f32(rng);
let b = gen_large_f32(rng);
if b == 0.0 {
return None;
}
let c = a / b;
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() || c.is_nan()|| c.abs() <= unsafe { mem::transmute(16777215u32) } {
return None;
}
Some(
Divsf3vfp {
a: to_u32(a),
b: to_u32(b),
c: to_u32(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
use compiler_builtins::float::div::__divsf3vfp;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32, u32), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn divsf3vfp() {
for &((a, b), c) in TEST_CASES {
let c_ = __divsf3vfp(mk_f32(a), mk_f32(b));
assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Divdf3vfp {
a: u64, // f64
b: u64, // f64
c: u64, // f64
}
impl TestCase for Divdf3vfp {
fn name() -> &'static str {
"divdf3vfp"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_large_f64(rng);
let b = gen_large_f64(rng);
if b == 0.0 {
return None;
}
let c = a / b;
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() || c.is_nan()
|| c.abs() <= unsafe { mem::transmute(4503599627370495u64) } {
return None;
}
Some(
Divdf3vfp {
a: to_u64(a),
b: to_u64(b),
c: to_u64(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
use compiler_builtins::float::div::__divdf3vfp;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64, u64), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn divdf3vfp() {
for &((a, b), c) in TEST_CASES {
let c_ = __divdf3vfp(mk_f64(a), mk_f64(b));
assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Udivdi3 {

8
tests/divdf3vfp.rs Normal file
View File

@ -0,0 +1,8 @@
#![feature(compiler_builtins_lib)]
#![feature(i128_type)]
#![cfg_attr(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux", test),
no_std)]
#[cfg(target_arch = "arm")]
include!(concat!(env!("OUT_DIR"), "/divdf3vfp.rs"));

8
tests/divsf3vfp.rs Normal file
View File

@ -0,0 +1,8 @@
#![feature(compiler_builtins_lib)]
#![feature(i128_type)]
#![cfg_attr(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux", test),
no_std)]
#[cfg(target_arch = "arm")]
include!(concat!(env!("OUT_DIR"), "/divsf3vfp.rs"));

8
tests/muldf3vfp.rs Normal file
View File

@ -0,0 +1,8 @@
#![feature(compiler_builtins_lib)]
#![feature(i128_type)]
#![cfg_attr(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux", test),
no_std)]
#[cfg(target_arch = "arm")]
include!(concat!(env!("OUT_DIR"), "/muldf3vfp.rs"));

8
tests/mulsf3vfp.rs Normal file
View File

@ -0,0 +1,8 @@
#![feature(compiler_builtins_lib)]
#![feature(i128_type)]
#![cfg_attr(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux", test),
no_std)]
#[cfg(target_arch = "arm")]
include!(concat!(env!("OUT_DIR"), "/mulsf3vfp.rs"));