Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 66 additions & 4 deletions fearless_simd_tests/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn supports_highest_level() {

#[simd_test]
#[ignore]
fn test_f32_to_i32_exhaustive<S: Simd>(simd: S) {
fn test_f32_to_i32_precise_exhaustive<S: Simd>(simd: S) {
// The vectorize call doesn't affect the outcome of the test, but does make it complete far more quickly
#[expect(
clippy::cast_possible_truncation,
Expand All @@ -74,11 +74,35 @@ fn test_f32_to_i32_exhaustive<S: Simd>(simd: S) {
|| {
for i in (0..u32::MAX).step_by(4) {
let floats = f32x4::from_fn(simd, |n| f32::from_bits(n as u32 + i));
let ints = floats.to_int::<i32x4<_>>();
let ints = floats.to_int_precise::<i32x4<_>>();
let ints_ref = (*floats).map(|f| f as i32);
assert_eq!(
*ints, ints_ref,
"f32x4::to_int::<i32x4<_>>() returns the same results as Rust's `as i32`"
"f32x4::to_int_precise::<i32x4<_>>() returns the same results as Rust's `as i32`"
);
}
},
);
}

#[simd_test]
#[ignore]
fn test_f32_to_u32_precise_exhaustive<S: Simd>(simd: S) {
// The vectorize call doesn't affect the outcome of the test, but does make it complete far more quickly
#[expect(
clippy::cast_possible_truncation,
reason = "that's the exact behavior we're testing"
)]
simd.vectorize(
#[inline(always)]
|| {
for i in (0..u32::MAX).step_by(4) {
let floats = f32x4::from_fn(simd, |n| f32::from_bits(n as u32 + i));
let ints = floats.to_int_precise::<u32x4<_>>();
let ints_ref = (*floats).map(|f| f as u32);
assert_eq!(
*ints, ints_ref,
"f32x4::to_int_precise::<u32x4<_>>() returns the same results as Rust's `as u32`"
);
}
},
Expand All @@ -98,11 +122,49 @@ fn test_f32_to_u32_exhaustive<S: Simd>(simd: S) {
|| {
for i in (0..u32::MAX).step_by(4) {
let floats = f32x4::from_fn(simd, |n| f32::from_bits(n as u32 + i));
// If the value is out of range of u32 because f32 cannot represent it exactly, skip the value
// The out-of-range semantics are explicitly implementation-defined in the non-precise version.
if ! (*floats).iter().all(|val| !val.is_nan() && *val > u32::MIN as f32 && *val < u32::MAX as f32) {
continue;
}
let ints = floats.to_int::<u32x4<_>>();
let ints_ref = (*floats).map(|f| f as u32);
assert_eq!(
*ints, ints_ref,
"f32x4::to_int::<u32x4<_>>() returns the same results as Rust's `as u32`"
"f32x4::to_int::<u32x4<_>>() returns the same results as Rust's `as u32` (input: {:?})", floats.as_slice()
);
}
},
);
}

#[simd_test]
#[ignore]
fn test_f32_to_i32_exhaustive<S: Simd>(simd: S) {
// The vectorize call doesn't affect the outcome of the test, but does make it complete far more quickly
#[expect(
clippy::cast_possible_truncation,
reason = "that's the exact behavior we're testing"
)]
simd.vectorize(
#[inline(always)]
|| {
for i in (0..u32::MAX).step_by(4) {
let floats = f32x4::from_fn(simd, |n| f32::from_bits(n as u32 + i));
// If the value is out of range of i32 because f32 cannot represent it exactly, skip the value
// The out-of-range semantics are explicitly implementation-defined in the non-precise version.
if !(*floats)
.iter()
.all(|val| !val.is_nan() && *val > i32::MIN as f32 && *val < i32::MAX as f32)
{
continue;
}
let ints = floats.to_int::<i32x4<_>>();
let ints_ref = (*floats).map(|f| f as i32);
assert_eq!(
*ints, ints_ref,
"f32x4::to_int::<i32x4<_>>() returns the same results as Rust's `as i32` (input: {:?})",
floats.as_slice()
);
}
},
Expand Down