about summary refs log tree commit diff
path: root/src/tools/miri/tests/pass/shims/x86/rounding-error.rs
blob: bf56111b2e496907d9af891b08888ba646a72548 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 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);
}