| use crate::{ |
| core_arch::{simd::*, simd_llvm::*, x86::*}, |
| mem::{self, transmute}, |
| }; |
| |
| #[cfg(test)] |
| use stdarch_test::assert_instr; |
| |
| /// Computes the absolute values of packed 32-bit integers in `a`. |
| /// |
| /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33&text=_mm512_abs_epi32) |
| #[inline] |
| #[target_feature(enable = "avx512f")] |
| #[cfg_attr(test, assert_instr(vpabsd))] |
| pub unsafe fn _mm512_abs_epi32(a: __m512i) -> __m512i { |
| let a = a.as_i32x16(); |
| // all-0 is a properly initialized i32x16 |
| let zero: i32x16 = mem::zeroed(); |
| let sub = simd_sub(zero, a); |
| let cmp: i32x16 = simd_gt(a, zero); |
| transmute(simd_select(cmp, a, sub)) |
| } |
| |
| /// Computes the absolute value of packed 32-bit integers in `a`, and store the |
| /// unsigned results in `dst` using writemask `k` (elements are copied from |
| /// `src` when the corresponding mask bit is not set). |
| /// |
| /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33&text=_mm512_abs_epi32) |
| #[inline] |
| #[target_feature(enable = "avx512f")] |
| #[cfg_attr(test, assert_instr(vpabsd))] |
| pub unsafe fn _mm512_mask_abs_epi32(src: __m512i, k: __mmask16, a: __m512i) -> __m512i { |
| let abs = _mm512_abs_epi32(a).as_i32x16(); |
| transmute(simd_select_bitmask(k, abs, src.as_i32x16())) |
| } |
| |
| /// Computes the absolute value of packed 32-bit integers in `a`, and store the |
| /// unsigned results in `dst` using zeromask `k` (elements are zeroed out when |
| /// the corresponding mask bit is not set). |
| /// |
| /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33,34,35,35&text=_mm512_maskz_abs_epi32) |
| #[inline] |
| #[target_feature(enable = "avx512f")] |
| #[cfg_attr(test, assert_instr(vpabsd))] |
| pub unsafe fn _mm512_maskz_abs_epi32(k: __mmask16, a: __m512i) -> __m512i { |
| let abs = _mm512_abs_epi32(a).as_i32x16(); |
| let zero = _mm512_setzero_si512().as_i32x16(); |
| transmute(simd_select_bitmask(k, abs, zero)) |
| } |
| |
| /// Returns vector of type `__m512i` with all elements set to zero. |
| /// |
| /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990&text=_mm512_setzero_si512) |
| #[inline] |
| #[target_feature(enable = "avx512f")] |
| #[cfg_attr(test, assert_instr(vxorps))] |
| pub unsafe fn _mm512_setzero_si512() -> __m512i { |
| // All-0 is a properly initialized __m512i |
| mem::zeroed() |
| } |
| |
| /// Sets packed 32-bit integers in `dst` with the supplied values in reverse |
| /// order. |
| #[inline] |
| #[target_feature(enable = "avx512f")] |
| pub unsafe fn _mm512_setr_epi32( |
| e15: i32, |
| e14: i32, |
| e13: i32, |
| e12: i32, |
| e11: i32, |
| e10: i32, |
| e9: i32, |
| e8: i32, |
| e7: i32, |
| e6: i32, |
| e5: i32, |
| e4: i32, |
| e3: i32, |
| e2: i32, |
| e1: i32, |
| e0: i32, |
| ) -> __m512i { |
| let r = i32x16( |
| e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0, |
| ); |
| transmute(r) |
| } |
| |
| /// Broadcast 64-bit integer `a` to all elements of `dst`. |
| #[inline] |
| #[target_feature(enable = "avx512f")] |
| pub unsafe fn _mm512_set1_epi64(a: i64) -> __m512i { |
| transmute(i64x8::splat(a)) |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use std; |
| use stdarch_test::simd_test; |
| |
| use crate::core_arch::x86::*; |
| |
| #[simd_test(enable = "avx512f")] |
| unsafe fn test_mm512_abs_epi32() { |
| #[rustfmt::skip] |
| let a = _mm512_setr_epi32( |
| 0, 1, -1, std::i32::MAX, |
| std::i32::MIN, 100, -100, -32, |
| 0, 1, -1, std::i32::MAX, |
| std::i32::MIN, 100, -100, -32, |
| ); |
| let r = _mm512_abs_epi32(a); |
| let e = _mm512_setr_epi32( |
| 0, |
| 1, |
| 1, |
| std::i32::MAX, |
| std::i32::MAX.wrapping_add(1), |
| 100, |
| 100, |
| 32, |
| 0, |
| 1, |
| 1, |
| std::i32::MAX, |
| std::i32::MAX.wrapping_add(1), |
| 100, |
| 100, |
| 32, |
| ); |
| assert_eq_m512i(r, e); |
| } |
| |
| #[simd_test(enable = "avx512f")] |
| unsafe fn test_mm512_mask_abs_epi32() { |
| #[rustfmt::skip] |
| let a = _mm512_setr_epi32( |
| 0, 1, -1, std::i32::MAX, |
| std::i32::MIN, 100, -100, -32, |
| 0, 1, -1, std::i32::MAX, |
| std::i32::MIN, 100, -100, -32, |
| ); |
| let r = _mm512_mask_abs_epi32(a, 0, a); |
| assert_eq_m512i(r, a); |
| let r = _mm512_mask_abs_epi32(a, 0b11111111, a); |
| let e = _mm512_setr_epi32( |
| 0, |
| 1, |
| 1, |
| std::i32::MAX, |
| std::i32::MAX.wrapping_add(1), |
| 100, |
| 100, |
| 32, |
| 0, |
| 1, |
| -1, |
| std::i32::MAX, |
| std::i32::MIN, |
| 100, |
| -100, |
| -32, |
| ); |
| assert_eq_m512i(r, e); |
| } |
| |
| #[simd_test(enable = "avx512f")] |
| unsafe fn test_mm512_maskz_abs_epi32() { |
| #[rustfmt::skip] |
| let a = _mm512_setr_epi32( |
| 0, 1, -1, std::i32::MAX, |
| std::i32::MIN, 100, -100, -32, |
| 0, 1, -1, std::i32::MAX, |
| std::i32::MIN, 100, -100, -32, |
| ); |
| let r = _mm512_maskz_abs_epi32(0, a); |
| assert_eq_m512i(r, _mm512_setzero_si512()); |
| let r = _mm512_maskz_abs_epi32(0b11111111, a); |
| let e = _mm512_setr_epi32( |
| 0, |
| 1, |
| 1, |
| std::i32::MAX, |
| std::i32::MAX.wrapping_add(1), |
| 100, |
| 100, |
| 32, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| ); |
| assert_eq_m512i(r, e); |
| } |
| } |