1 // run-pass
2 // ignore-emscripten
3 // ignore-android
4 
5 // FIXME: this test fails on arm-android because the NDK version 14 is too old.
6 // It needs at least version 18. We disable it on all android build bots because
7 // there is no way in compile-test to disable it for an (arch,os) pair.
8 
9 // Test that the simd floating-point math intrinsics produce correct results.
10 
11 #![feature(repr_simd, platform_intrinsics)]
12 #![allow(non_camel_case_types)]
13 
14 #[repr(simd)]
15 #[derive(Copy, Clone, PartialEq, Debug)]
16 struct f32x4(pub f32, pub f32, pub f32, pub f32);
17 
18 extern "platform-intrinsic" {
simd_fsqrt<T>(x: T) -> T19     fn simd_fsqrt<T>(x: T) -> T;
simd_fabs<T>(x: T) -> T20     fn simd_fabs<T>(x: T) -> T;
simd_fsin<T>(x: T) -> T21     fn simd_fsin<T>(x: T) -> T;
simd_fcos<T>(x: T) -> T22     fn simd_fcos<T>(x: T) -> T;
simd_fexp<T>(x: T) -> T23     fn simd_fexp<T>(x: T) -> T;
simd_fexp2<T>(x: T) -> T24     fn simd_fexp2<T>(x: T) -> T;
simd_fma<T>(x: T, y: T, z: T) -> T25     fn simd_fma<T>(x: T, y: T, z: T) -> T;
simd_flog<T>(x: T) -> T26     fn simd_flog<T>(x: T) -> T;
simd_flog10<T>(x: T) -> T27     fn simd_flog10<T>(x: T) -> T;
simd_flog2<T>(x: T) -> T28     fn simd_flog2<T>(x: T) -> T;
simd_fpow<T>(x: T, y: T) -> T29     fn simd_fpow<T>(x: T, y: T) -> T;
simd_fpowi<T>(x: T, y: i32) -> T30     fn simd_fpowi<T>(x: T, y: i32) -> T;
31 
32     // rounding functions
simd_ceil<T>(x: T) -> T33     fn simd_ceil<T>(x: T) -> T;
simd_floor<T>(x: T) -> T34     fn simd_floor<T>(x: T) -> T;
simd_round<T>(x: T) -> T35     fn simd_round<T>(x: T) -> T;
simd_trunc<T>(x: T) -> T36     fn simd_trunc<T>(x: T) -> T;
37 }
38 
39 macro_rules! assert_approx_eq_f32 {
40     ($a:expr, $b:expr) => ({
41         let (a, b) = (&$a, &$b);
42         assert!((*a - *b).abs() < 1.0e-6,
43                 "{} is not approximately equal to {}", *a, *b);
44     })
45 }
46 macro_rules! assert_approx_eq {
47     ($a:expr, $b:expr) => ({
48         let a = $a;
49         let b = $b;
50         assert_approx_eq_f32!(a.0, b.0);
51         assert_approx_eq_f32!(a.1, b.1);
52         assert_approx_eq_f32!(a.2, b.2);
53         assert_approx_eq_f32!(a.3, b.3);
54     })
55 }
56 
main()57 fn main() {
58     let x = f32x4(1.0, 1.0, 1.0, 1.0);
59     let y = f32x4(-1.0, -1.0, -1.0, -1.0);
60     let z = f32x4(0.0, 0.0, 0.0, 0.0);
61 
62     let h = f32x4(0.5, 0.5, 0.5, 0.5);
63 
64     unsafe {
65         let r = simd_fabs(y);
66         assert_approx_eq!(x, r);
67 
68         let r = simd_fcos(z);
69         assert_approx_eq!(x, r);
70 
71         let r = simd_fexp(z);
72         assert_approx_eq!(x, r);
73 
74         let r = simd_fexp2(z);
75         assert_approx_eq!(x, r);
76 
77         let r = simd_fma(x, h, h);
78         assert_approx_eq!(x, r);
79 
80         let r = simd_fsqrt(x);
81         assert_approx_eq!(x, r);
82 
83         let r = simd_flog(x);
84         assert_approx_eq!(z, r);
85 
86         let r = simd_flog2(x);
87         assert_approx_eq!(z, r);
88 
89         let r = simd_flog10(x);
90         assert_approx_eq!(z, r);
91 
92         let r = simd_fpow(h, x);
93         assert_approx_eq!(h, r);
94 
95         let r = simd_fpowi(h, 1);
96         assert_approx_eq!(h, r);
97 
98         let r = simd_fsin(z);
99         assert_approx_eq!(z, r);
100 
101         // rounding functions
102         let r = simd_floor(h);
103         assert_eq!(z, r);
104 
105         let r = simd_ceil(h);
106         assert_eq!(x, r);
107 
108         let r = simd_round(h);
109         assert_eq!(x, r);
110 
111         let r = simd_trunc(h);
112         assert_eq!(z, r);
113     }
114 }
115