1 //@compile-flags: -Zmiri-strict-provenance
2 #![feature(portable_simd, platform_intrinsics)]
6 let a = f32x4::splat(10.0);
7 let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
8 assert_eq!(-b, f32x4::from_array([-1.0, -2.0, -3.0, 4.0]));
9 assert_eq!(a + b, f32x4::from_array([11.0, 12.0, 13.0, 6.0]));
10 assert_eq!(a - b, f32x4::from_array([9.0, 8.0, 7.0, 14.0]));
11 assert_eq!(a * b, f32x4::from_array([10.0, 20.0, 30.0, -40.0]));
12 assert_eq!(b / a, f32x4::from_array([0.1, 0.2, 0.3, -0.4]));
13 assert_eq!(a / f32x4::splat(2.0), f32x4::splat(5.0));
14 assert_eq!(a % b, f32x4::from_array([0.0, 0.0, 1.0, 2.0]));
15 assert_eq!(b.abs(), f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
16 assert_eq!(a.simd_max(b * f32x4::splat(4.0)), f32x4::from_array([10.0, 10.0, 12.0, 10.0]));
17 assert_eq!(a.simd_min(b * f32x4::splat(4.0)), f32x4::from_array([4.0, 8.0, 10.0, -16.0]));
19 assert_eq!(a.mul_add(b, a), (a * b) + a);
20 assert_eq!(b.mul_add(b, a), (b * b) + a);
21 assert_eq!(a.mul_add(b, b), (a * b) + b);
23 f32x4::splat(-3.2).mul_add(b, f32x4::splat(f32::NEG_INFINITY)),
24 f32x4::splat(f32::NEG_INFINITY)
26 assert_eq!((a * a).sqrt(), a);
27 assert_eq!((b * b).sqrt(), b.abs());
29 assert_eq!(a.simd_eq(f32x4::splat(5.0) * b), Mask::from_array([false, true, false, false]));
30 assert_eq!(a.simd_ne(f32x4::splat(5.0) * b), Mask::from_array([true, false, true, true]));
31 assert_eq!(a.simd_le(f32x4::splat(5.0) * b), Mask::from_array([false, true, true, false]));
32 assert_eq!(a.simd_lt(f32x4::splat(5.0) * b), Mask::from_array([false, false, true, false]));
33 assert_eq!(a.simd_ge(f32x4::splat(5.0) * b), Mask::from_array([true, true, false, true]));
34 assert_eq!(a.simd_gt(f32x4::splat(5.0) * b), Mask::from_array([true, false, false, true]));
36 assert_eq!(a.reduce_sum(), 40.0);
37 assert_eq!(b.reduce_sum(), 2.0);
38 assert_eq!(a.reduce_product(), 100.0 * 100.0);
39 assert_eq!(b.reduce_product(), -24.0);
40 assert_eq!(a.reduce_max(), 10.0);
41 assert_eq!(b.reduce_max(), 3.0);
42 assert_eq!(a.reduce_min(), 10.0);
43 assert_eq!(b.reduce_min(), -4.0);
46 f32x2::from_array([0.0, f32::NAN]).simd_max(f32x2::from_array([f32::NAN, 0.0])),
47 f32x2::from_array([0.0, 0.0])
49 assert_eq!(f32x2::from_array([0.0, f32::NAN]).reduce_max(), 0.0);
50 assert_eq!(f32x2::from_array([f32::NAN, 0.0]).reduce_max(), 0.0);
52 f32x2::from_array([0.0, f32::NAN]).simd_min(f32x2::from_array([f32::NAN, 0.0])),
53 f32x2::from_array([0.0, 0.0])
55 assert_eq!(f32x2::from_array([0.0, f32::NAN]).reduce_min(), 0.0);
56 assert_eq!(f32x2::from_array([f32::NAN, 0.0]).reduce_min(), 0.0);
60 let a = f64x4::splat(10.0);
61 let b = f64x4::from_array([1.0, 2.0, 3.0, -4.0]);
62 assert_eq!(-b, f64x4::from_array([-1.0, -2.0, -3.0, 4.0]));
63 assert_eq!(a + b, f64x4::from_array([11.0, 12.0, 13.0, 6.0]));
64 assert_eq!(a - b, f64x4::from_array([9.0, 8.0, 7.0, 14.0]));
65 assert_eq!(a * b, f64x4::from_array([10.0, 20.0, 30.0, -40.0]));
66 assert_eq!(b / a, f64x4::from_array([0.1, 0.2, 0.3, -0.4]));
67 assert_eq!(a / f64x4::splat(2.0), f64x4::splat(5.0));
68 assert_eq!(a % b, f64x4::from_array([0.0, 0.0, 1.0, 2.0]));
69 assert_eq!(b.abs(), f64x4::from_array([1.0, 2.0, 3.0, 4.0]));
70 assert_eq!(a.simd_max(b * f64x4::splat(4.0)), f64x4::from_array([10.0, 10.0, 12.0, 10.0]));
71 assert_eq!(a.simd_min(b * f64x4::splat(4.0)), f64x4::from_array([4.0, 8.0, 10.0, -16.0]));
73 assert_eq!(a.mul_add(b, a), (a * b) + a);
74 assert_eq!(b.mul_add(b, a), (b * b) + a);
75 assert_eq!(a.mul_add(b, b), (a * b) + b);
77 f64x4::splat(-3.2).mul_add(b, f64x4::splat(f64::NEG_INFINITY)),
78 f64x4::splat(f64::NEG_INFINITY)
80 assert_eq!((a * a).sqrt(), a);
81 assert_eq!((b * b).sqrt(), b.abs());
83 assert_eq!(a.simd_eq(f64x4::splat(5.0) * b), Mask::from_array([false, true, false, false]));
84 assert_eq!(a.simd_ne(f64x4::splat(5.0) * b), Mask::from_array([true, false, true, true]));
85 assert_eq!(a.simd_le(f64x4::splat(5.0) * b), Mask::from_array([false, true, true, false]));
86 assert_eq!(a.simd_lt(f64x4::splat(5.0) * b), Mask::from_array([false, false, true, false]));
87 assert_eq!(a.simd_ge(f64x4::splat(5.0) * b), Mask::from_array([true, true, false, true]));
88 assert_eq!(a.simd_gt(f64x4::splat(5.0) * b), Mask::from_array([true, false, false, true]));
90 assert_eq!(a.reduce_sum(), 40.0);
91 assert_eq!(b.reduce_sum(), 2.0);
92 assert_eq!(a.reduce_product(), 100.0 * 100.0);
93 assert_eq!(b.reduce_product(), -24.0);
94 assert_eq!(a.reduce_max(), 10.0);
95 assert_eq!(b.reduce_max(), 3.0);
96 assert_eq!(a.reduce_min(), 10.0);
97 assert_eq!(b.reduce_min(), -4.0);
100 f64x2::from_array([0.0, f64::NAN]).simd_max(f64x2::from_array([f64::NAN, 0.0])),
101 f64x2::from_array([0.0, 0.0])
103 assert_eq!(f64x2::from_array([0.0, f64::NAN]).reduce_max(), 0.0);
104 assert_eq!(f64x2::from_array([f64::NAN, 0.0]).reduce_max(), 0.0);
106 f64x2::from_array([0.0, f64::NAN]).simd_min(f64x2::from_array([f64::NAN, 0.0])),
107 f64x2::from_array([0.0, 0.0])
109 assert_eq!(f64x2::from_array([0.0, f64::NAN]).reduce_min(), 0.0);
110 assert_eq!(f64x2::from_array([f64::NAN, 0.0]).reduce_min(), 0.0);
114 let a = i32x4::splat(10);
115 let b = i32x4::from_array([1, 2, 3, -4]);
116 assert_eq!(-b, i32x4::from_array([-1, -2, -3, 4]));
117 assert_eq!(a + b, i32x4::from_array([11, 12, 13, 6]));
118 assert_eq!(a - b, i32x4::from_array([9, 8, 7, 14]));
119 assert_eq!(a * b, i32x4::from_array([10, 20, 30, -40]));
120 assert_eq!(a / b, i32x4::from_array([10, 5, 3, -2]));
121 assert_eq!(a / i32x4::splat(2), i32x4::splat(5));
122 assert_eq!(i32x2::splat(i32::MIN) / i32x2::splat(-1), i32x2::splat(i32::MIN));
123 assert_eq!(a % b, i32x4::from_array([0, 0, 1, 2]));
124 assert_eq!(i32x2::splat(i32::MIN) % i32x2::splat(-1), i32x2::splat(0));
125 assert_eq!(b.abs(), i32x4::from_array([1, 2, 3, 4]));
126 assert_eq!(a.simd_max(b * i32x4::splat(4)), i32x4::from_array([10, 10, 12, 10]));
127 assert_eq!(a.simd_min(b * i32x4::splat(4)), i32x4::from_array([4, 8, 10, -16]));
130 i8x4::from_array([i8::MAX, -23, 23, i8::MIN]).saturating_add(i8x4::from_array([
136 i8x4::from_array([i8::MAX, i8::MIN, i8::MAX, -100])
139 i8x4::from_array([i8::MAX, -28, 27, 42]).saturating_sub(i8x4::from_array([
145 i8x4::from_array([126, i8::MIN, -100, 122])
148 u8x4::from_array([u8::MAX, 0, 23, 42]).saturating_add(u8x4::from_array([
154 u8x4::from_array([u8::MAX, 1, u8::MAX, 242])
157 u8x4::from_array([u8::MAX, 0, 23, 42]).saturating_sub(u8x4::from_array([
163 u8x4::from_array([254, 0, 0, 0])
166 assert_eq!(!b, i32x4::from_array([!1, !2, !3, !-4]));
167 assert_eq!(b << i32x4::splat(2), i32x4::from_array([4, 8, 12, -16]));
168 assert_eq!(b >> i32x4::splat(1), i32x4::from_array([0, 1, 1, -2]));
169 assert_eq!(b & i32x4::splat(2), i32x4::from_array([0, 2, 2, 0]));
170 assert_eq!(b | i32x4::splat(2), i32x4::from_array([3, 2, 3, -2]));
171 assert_eq!(b ^ i32x4::splat(2), i32x4::from_array([3, 0, 1, -2]));
173 assert_eq!(a.simd_eq(i32x4::splat(5) * b), Mask::from_array([false, true, false, false]));
174 assert_eq!(a.simd_ne(i32x4::splat(5) * b), Mask::from_array([true, false, true, true]));
175 assert_eq!(a.simd_le(i32x4::splat(5) * b), Mask::from_array([false, true, true, false]));
176 assert_eq!(a.simd_lt(i32x4::splat(5) * b), Mask::from_array([false, false, true, false]));
177 assert_eq!(a.simd_ge(i32x4::splat(5) * b), Mask::from_array([true, true, false, true]));
178 assert_eq!(a.simd_gt(i32x4::splat(5) * b), Mask::from_array([true, false, false, true]));
180 assert_eq!(a.reduce_sum(), 40);
181 assert_eq!(b.reduce_sum(), 2);
182 assert_eq!(a.reduce_product(), 100 * 100);
183 assert_eq!(b.reduce_product(), -24);
184 assert_eq!(a.reduce_max(), 10);
185 assert_eq!(b.reduce_max(), 3);
186 assert_eq!(a.reduce_min(), 10);
187 assert_eq!(b.reduce_min(), -4);
189 assert_eq!(a.reduce_and(), 10);
190 assert_eq!(b.reduce_and(), 0);
191 assert_eq!(a.reduce_or(), 10);
192 assert_eq!(b.reduce_or(), -1);
193 assert_eq!(a.reduce_xor(), 0);
194 assert_eq!(b.reduce_xor(), -4);
198 let intmask = Mask::from_int(i32x4::from_array([0, -1, 0, 0]));
199 assert_eq!(intmask, Mask::from_array([false, true, false, false]));
200 assert_eq!(intmask.to_array(), [false, true, false, false]);
203 true, false, false, true, false, false, true, false, true, true, false, false, false, true,
206 let mask = Mask::<i64, 16>::from_array(values);
207 let bitmask = mask.to_bitmask();
208 assert_eq!(bitmask, 0b1010001101001001);
209 assert_eq!(Mask::<i64, 16>::from_bitmask(bitmask), mask);
211 let values = [false, false, false, true];
212 let mask = Mask::<i64, 4>::from_array(values);
213 let bitmask = mask.to_bitmask();
214 assert_eq!(bitmask, 0b1000);
215 assert_eq!(Mask::<i64, 4>::from_bitmask(bitmask), mask);
219 // between integer types
220 assert_eq!(i32x4::from_array([1, 2, 3, -4]), i16x4::from_array([1, 2, 3, -4]).cast());
221 assert_eq!(i16x4::from_array([1, 2, 3, -4]), i32x4::from_array([1, 2, 3, -4]).cast());
222 assert_eq!(i32x4::from_array([1, -1, 3, 4]), u64x4::from_array([1, u64::MAX, 3, 4]).cast());
226 i8x4::from_array([127, -128, 127, -128]),
227 f32x4::from_array([127.99, -128.99, 999.0, -999.0]).cast()
230 i32x4::from_array([0, 1, -1, 2147483520]),
233 /*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd),
234 /*-0x1.19999ap+0*/ f32::from_bits(0xbf8ccccd),
240 i32x8::from_array([i32::MAX, i32::MIN, i32::MAX, i32::MIN, i32::MAX, i32::MIN, 0, 0]),
258 /*0x1.26580cp+30*/ f32::from_bits(0x4e932c06),
262 i32x4::from_array([-2147483647i32, 1234567890i32, 16777219i32, -16777219i32]).cast()
267 f32x4::from_array([f32::INFINITY, f32::INFINITY, f32::NEG_INFINITY, f32::NEG_INFINITY]),
268 f64x4::from_array([f64::MAX, f64::INFINITY, f64::MIN, f64::NEG_INFINITY]).cast()
274 i32x4::from_array([0, 1, -1, 2147483520]),
277 /*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd),
278 /*-0x1.19999ap+0*/ f32::from_bits(0xbf8ccccd),
284 u64x4::from_array([0, 10000000000000000, u64::MAX - 2047, 9223372036854775808]),
288 (u64::MAX - 1024) as f64,
289 9223372036854775808.0
299 let a = f32x4::splat(10.0);
300 let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
302 assert_eq!(simd_swizzle!(b, [3, 0, 0, 2]), f32x4::from_array([-4.0, 1.0, 1.0, 3.0]));
303 assert_eq!(simd_swizzle!(b, [1, 2]), f32x2::from_array([2.0, 3.0]));
304 assert_eq!(simd_swizzle!(b, a, [First(3), Second(0)]), f32x2::from_array([-4.0, 10.0]));
307 fn simd_gather_scatter() {
308 let mut vec: Vec<i16> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
309 let idxs = Simd::from_array([9, 3, 0, 17]);
310 let result = Simd::gather_or_default(&vec, idxs); // Note the lane that is out-of-bounds.
311 assert_eq!(result, Simd::from_array([0, 13, 10, 0]));
313 let idxs = Simd::from_array([9, 3, 0, 0]);
314 Simd::from_array([-27, 82, -41, 124]).scatter(&mut vec, idxs);
315 assert_eq!(vec, vec![124, 11, 12, 82, 14, 15, 16, 17, 18]);
320 f32x4::from_array([0.9, 1.001, 2.0, -4.5]).ceil(),
321 f32x4::from_array([1.0, 2.0, 2.0, -4.0])
324 f32x4::from_array([0.9, 1.001, 2.0, -4.5]).floor(),
325 f32x4::from_array([0.0, 1.0, 2.0, -5.0])
328 f32x4::from_array([0.9, 1.001, 2.0, -4.5]).round(),
329 f32x4::from_array([1.0, 1.0, 2.0, -5.0])
332 f32x4::from_array([0.9, 1.001, 2.0, -4.5]).trunc(),
333 f32x4::from_array([0.0, 1.0, 2.0, -4.0])
337 f64x4::from_array([0.9, 1.001, 2.0, -4.5]).ceil(),
338 f64x4::from_array([1.0, 2.0, 2.0, -4.0])
341 f64x4::from_array([0.9, 1.001, 2.0, -4.5]).floor(),
342 f64x4::from_array([0.0, 1.0, 2.0, -5.0])
345 f64x4::from_array([0.9, 1.001, 2.0, -4.5]).round(),
346 f64x4::from_array([1.0, 1.0, 2.0, -5.0])
349 f64x4::from_array([0.9, 1.001, 2.0, -4.5]).trunc(),
350 f64x4::from_array([0.0, 1.0, 2.0, -4.0])
354 fn simd_intrinsics() {
355 extern "platform-intrinsic" {
356 fn simd_eq<T, U>(x: T, y: T) -> U;
357 fn simd_reduce_any<T>(x: T) -> bool;
358 fn simd_reduce_all<T>(x: T) -> bool;
359 fn simd_select<M, T>(m: M, yes: T, no: T) -> T;
362 // Make sure simd_eq returns all-1 for `true`
363 let a = i32x4::splat(10);
364 let b = i32x4::from_array([1, 2, 10, 4]);
365 let c: i32x4 = simd_eq(a, b);
366 assert_eq!(c, i32x4::from_array([0, 0, -1, 0]));
368 assert!(!simd_reduce_any(i32x4::splat(0)));
369 assert!(simd_reduce_any(i32x4::splat(-1)));
370 assert!(simd_reduce_any(i32x2::from_array([0, -1])));
371 assert!(!simd_reduce_all(i32x4::splat(0)));
372 assert!(simd_reduce_all(i32x4::splat(-1)));
373 assert!(!simd_reduce_all(i32x2::from_array([0, -1])));
376 simd_select(i8x4::from_array([0, -1, -1, 0]), a, b),
377 i32x4::from_array([1, 10, 10, 4])
380 simd_select(i8x4::from_array([0, -1, -1, 0]), b, a),
381 i32x4::from_array([10, 2, 10, 10])
393 simd_gather_scatter();