| // We're testing x86 target specific features |
| //@only-target: x86_64 i686 |
| |
| //! rsqrt and rcp SSE/AVX operations are approximate. We use that as license to treat them as |
| //! non-deterministic. Ensure that we do indeed see random results within the expected error bounds. |
| |
| #[cfg(target_arch = "x86")] |
| use std::arch::x86::*; |
| #[cfg(target_arch = "x86_64")] |
| use std::arch::x86_64::*; |
| use std::collections::HashSet; |
| |
| fn main() { |
| let mut vals = HashSet::new(); |
| for _ in 0..50 { |
| unsafe { |
| // Compute the inverse square root of 4.0, four times. |
| let a = _mm_setr_ps(4.0, 4.0, 4.0, 4.0); |
| let exact = 0.5; |
| let r = _mm_rsqrt_ps(a); |
| let r: [f32; 4] = std::mem::transmute(r); |
| // Check the results. |
| for r in r { |
| vals.insert(r.to_bits()); |
| // Ensure the relative error is less than 2^-12. |
| let rel_error = (r - exact) / exact; |
| let log_error = rel_error.abs().log2(); |
| assert!( |
| rel_error == 0.0 || log_error < -12.0, |
| "got an error of {rel_error} = 2^{log_error}" |
| ); |
| } |
| } |
| } |
| // Ensure we saw a bunch of different results. |
| assert!(vals.len() >= 50); |
| } |