f32_bitwise && f64_bitwise

This commit is contained in:
Svyatoslav Nikolsky
2017-06-06 10:45:05 +03:00
parent e9a7d39704
commit de85e5996a
3 changed files with 35 additions and 7 deletions

View File

@ -9,5 +9,7 @@ macro_rules! run_test {
run_test!("i32", wasm_i32);
run_test!("f32", wasm_f32);
run_test!("f32_bitwise", wasm_f32_bitwise);
run_test!("f64", wasm_f64);
run_test!("f64_bitwise", wasm_f64_bitwise);
run_test!("endianness", wasm_endianness);

View File

@ -108,7 +108,21 @@ pub fn spec(name: &str) {
Ok(result) => {
let spec_expected = runtime_values(expected);
let actual_result = result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>();
assert_eq!(actual_result, spec_expected);
for (actual_result, spec_expected) in actual_result.iter().zip(spec_expected.iter()) {
assert_eq!(actual_result.variable_type(), spec_expected.variable_type());
// f32::NAN != f32::NAN
match spec_expected {
&RuntimeValue::F32(val) if val.is_nan() => match actual_result {
&RuntimeValue::F32(val) => assert!(val.is_nan()),
_ => unreachable!(), // checked above that types are same
},
&RuntimeValue::F64(val) if val.is_nan() => match actual_result {
&RuntimeValue::F64(val) => assert!(val.is_nan()),
_ => unreachable!(), // checked above that types are same
},
spec_expected @ _ => assert_eq!(actual_result, spec_expected),
}
}
println!("assert_return at line {} - success", line);
},
Err(e) => {

View File

@ -599,7 +599,7 @@ impl_integer!(i64);
impl_integer!(u64);
macro_rules! impl_float {
($type: ident) => {
($type: ident, $int_type: ident) => {
impl Float<$type> for $type {
fn abs(self) -> $type { self.abs() }
fn floor(self) -> $type { self.floor() }
@ -641,16 +641,28 @@ macro_rules! impl_float {
self.max(other)
}
fn copysign(self, other: $type) -> $type {
// TODO: this may be buggy for edge cases
if self.is_sign_positive() == other.is_sign_positive() {
use std::mem::size_of;
if self.is_nan() {
return self;
}
let sign_mask: $int_type = 1 << ((size_of::<$int_type>() << 3) - 1);
let self_int: $int_type = self.transmute_into();
let other_int: $int_type = other.transmute_into();
let is_self_sign_set = (self_int & sign_mask) != 0;
let is_other_sign_set = (other_int & sign_mask) != 0;
if is_self_sign_set == is_other_sign_set {
self
} else if is_other_sign_set {
(self_int | sign_mask).transmute_into()
} else {
self * -1.0
(self_int & !sign_mask).transmute_into()
}
}
}
}
}
impl_float!(f32);
impl_float!(f64);
impl_float!(f32, i32);
impl_float!(f64, i64);