use generic_array::typenum::{U8, U12};
use super::arch;
use crate::register::{
CastRegister, ConcatRegister, ExtendRegister, IndexableRegister, NumericRegister, Register, Storage,
array::ArrayRegister, reduced::ReducedRegister,
};
macro_rules! sat_clamp_narrow8 {
($from:ty, $fe:ty, $ie:ty) => {
#[inline(always)]
fn saturating_cast_from(value: Storage<$from>) -> Storage<Self> {
let lo = <$from as Register>::splat(<$ie>::MIN as $fe);
let hi = <$from as Register>::splat(<$ie>::MAX as $fe);
let clamped = <$from as NumericRegister>::min(<$from as NumericRegister>::max(value, lo), hi);
<Self as CastRegister<$from>>::cast_from(clamped)
}
};
}
pub type I8x4V3 = ReducedRegister<super::I8x16V3, U12>;
pub type U8x4V3 = ReducedRegister<super::U8x16V3, U12>;
pub type I8x8V3 = ReducedRegister<super::I8x16V3, U8>;
pub type U8x8V3 = ReducedRegister<super::U8x16V3, U8>;
#[inline(always)]
fn store_bytes(v: arch::__m128i) -> [i8; 16] {
let mut arr = [0i8; 16];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, v) };
arr
}
macro_rules! impl_concat_x4_from_x2 {
($red:ty, $elem:ty) => {
#[thermite_macros::inline_always]
impl ConcatRegister<ArrayRegister<$elem, 2>> for $red {
fn concat(lo: Storage<ArrayRegister<$elem, 2>>, hi: Storage<ArrayRegister<$elem, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi8(
lo.0[0] as i8,
lo.0[1] as i8,
hi.0[0] as i8,
hi.0[1] as i8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
)
})
}
fn split(value: Storage<Self>) -> (Storage<ArrayRegister<$elem, 2>>, Storage<ArrayRegister<$elem, 2>>) {
let a = store_bytes(value.0);
(
ArrayRegister([a[0] as $elem, a[1] as $elem]),
ArrayRegister([a[2] as $elem, a[3] as $elem]),
)
}
}
#[thermite_macros::inline_always]
impl ExtendRegister<ArrayRegister<$elem, 2>> for $red {
fn extend(value: Storage<ArrayRegister<$elem, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi8(
value.0[0] as i8,
value.0[1] as i8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
)
})
}
fn narrow(value: Storage<Self>) -> Storage<ArrayRegister<$elem, 2>> {
let a = store_bytes(value.0);
ArrayRegister([a[0] as $elem, a[1] as $elem])
}
}
};
}
impl_concat_x4_from_x2!(I8x4V3, i8);
impl_concat_x4_from_x2!(U8x4V3, u8);
macro_rules! impl_concat_x8_from_x4 {
($x8:ty, $x4:ty) => {
#[thermite_macros::inline_always]
impl ExtendRegister<$x4> for $x8 {
fn extend(value: Storage<$x4>) -> Storage<Self> {
ReducedRegister::new(value.0)
}
fn narrow(value: Storage<Self>) -> Storage<$x4> {
ReducedRegister::new(value.0)
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<$x4> for $x8 {
fn concat(lo: Storage<$x4>, hi: Storage<$x4>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_unpacklo_epi32(lo.0, hi.0) })
}
fn split(value: Storage<Self>) -> (Storage<$x4>, Storage<$x4>) {
(
ReducedRegister::new(value.0),
ReducedRegister::new(unsafe { arch::_mm_srli_si128(value.0, 4) }),
)
}
}
};
}
impl_concat_x8_from_x4!(I8x8V3, I8x4V3);
impl_concat_x8_from_x4!(U8x8V3, U8x4V3);
macro_rules! impl_concat_x16_from_x8 {
($native:ty, $x8:ty) => {
#[thermite_macros::inline_always]
impl ConcatRegister<$x8> for $native {
fn concat(lo: Storage<$x8>, hi: Storage<$x8>) -> Storage<Self> {
unsafe { arch::_mm_unpacklo_epi64(lo.0, hi.0) }
}
fn split(value: Storage<Self>) -> (Storage<$x8>, Storage<$x8>) {
(
ReducedRegister::new(value),
ReducedRegister::new(unsafe { arch::_mm_unpackhi_epi64(value, value) }),
)
}
}
};
}
impl_concat_x16_from_x8!(super::I8x16V3, I8x8V3);
impl_concat_x16_from_x8!(super::U8x16V3, U8x8V3);
#[thermite_macros::inline_always]
impl CastRegister<I8x4V3> for super::half16::I16x4V3 {
fn cast_from(value: Storage<I8x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_cvtepi8_epi16(value.0) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x4V3> for super::half16::U16x4V3 {
fn cast_from(value: Storage<U8x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_cvtepu8_epi16(value.0) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::half16::I16x4V3> for I8x4V3 {
fn cast_from(value: Storage<super::half16::I16x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_shuffle_epi8(value.0, arch::_mm_narrow_word_to_byte_maskx_v2()) })
}
fn saturating_cast_from(value: Storage<super::half16::I16x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_packs_epi16(value.0, value.0) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::half16::U16x4V3> for U8x4V3 {
fn cast_from(value: Storage<super::half16::U16x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_shuffle_epi8(value.0, arch::_mm_narrow_word_to_byte_maskx_v2()) })
}
fn saturating_cast_from(value: Storage<super::half16::U16x4V3>) -> Storage<Self> {
let clamped = unsafe { arch::_mm_min_epu16(value.0, arch::_mm_set1_epi16(0xFF)) };
ReducedRegister::new(unsafe { arch::_mm_packus_epi16(clamped, clamped) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<I8x8V3> for super::I16x8V3 {
fn cast_from(value: Storage<I8x8V3>) -> Storage<Self> {
unsafe { arch::_mm_cvtepi8_epi16(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x8V3> for super::U16x8V3 {
fn cast_from(value: Storage<U8x8V3>) -> Storage<Self> {
unsafe { arch::_mm_cvtepu8_epi16(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I16x8V3> for I8x8V3 {
fn cast_from(value: Storage<super::I16x8V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_shuffle_epi8(value, arch::_mm_narrow_word_to_byte_maskx_v2()) })
}
fn saturating_cast_from(value: Storage<super::I16x8V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_packs_epi16(value, value) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U16x8V3> for U8x8V3 {
fn cast_from(value: Storage<super::U16x8V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_shuffle_epi8(value, arch::_mm_narrow_word_to_byte_maskx_v2()) })
}
fn saturating_cast_from(value: Storage<super::U16x8V3>) -> Storage<Self> {
let clamped = unsafe { arch::_mm_min_epu16(value, arch::_mm_set1_epi16(0xFF)) };
ReducedRegister::new(unsafe { arch::_mm_packus_epi16(clamped, clamped) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I32x4V3> for I8x4V3 {
fn saturating_cast_from(value: Storage<super::I32x4V3>) -> Storage<Self> {
let words = <super::half16::I16x4V3 as CastRegister<super::I32x4V3>>::saturating_cast_from(value);
<Self as CastRegister<super::half16::I16x4V3>>::saturating_cast_from(words)
}
fn cast_from(value: Storage<super::I32x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_shuffle_epi8(value, arch::_mm_narrow_dword_to_byte_maskx_v2()) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U32x4V3> for U8x4V3 {
fn saturating_cast_from(value: Storage<super::U32x4V3>) -> Storage<Self> {
let words = <super::half16::U16x4V3 as CastRegister<super::U32x4V3>>::saturating_cast_from(value);
<Self as CastRegister<super::half16::U16x4V3>>::saturating_cast_from(words)
}
fn cast_from(value: Storage<super::U32x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_shuffle_epi8(value, arch::_mm_narrow_dword_to_byte_maskx_v2()) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I32x8V3> for I8x8V3 {
fn saturating_cast_from(value: Storage<super::I32x8V3>) -> Storage<Self> {
let words = <super::I16x8V3 as CastRegister<super::I32x8V3>>::saturating_cast_from(value);
<Self as CastRegister<super::I16x8V3>>::saturating_cast_from(words)
}
fn cast_from(value: Storage<super::I32x8V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm256_cvtepi32_epi8x_v3(value) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U32x8V3> for U8x8V3 {
fn saturating_cast_from(value: Storage<super::U32x8V3>) -> Storage<Self> {
let words = <super::U16x8V3 as CastRegister<super::U32x8V3>>::saturating_cast_from(value);
<Self as CastRegister<super::U16x8V3>>::saturating_cast_from(words)
}
fn cast_from(value: Storage<super::U32x8V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm256_cvtepi32_epi8x_v3(value) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I8x16V3> for super::I16x16V3 {
fn cast_from(value: Storage<super::I8x16V3>) -> Storage<Self> {
unsafe { arch::_mm256_cvtepi8_epi16(value) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U8x16V3> for super::U16x16V3 {
fn cast_from(value: Storage<super::U8x16V3>) -> Storage<Self> {
unsafe { arch::_mm256_cvtepu8_epi16(value) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<I8x4V3> for super::I32x4V3 {
fn cast_from(value: Storage<I8x4V3>) -> Storage<Self> {
unsafe { arch::_mm_cvtepi8_epi32(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x4V3> for super::U32x4V3 {
fn cast_from(value: Storage<U8x4V3>) -> Storage<Self> {
unsafe { arch::_mm_cvtepu8_epi32(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<I8x8V3> for super::I32x8V3 {
fn cast_from(value: Storage<I8x8V3>) -> Storage<Self> {
unsafe { arch::_mm256_cvtepi8_epi32(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x8V3> for super::U32x8V3 {
fn cast_from(value: Storage<U8x8V3>) -> Storage<Self> {
unsafe { arch::_mm256_cvtepu8_epi32(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I8x16V3> for ArrayRegister<super::I32x8V3, 2> {
fn cast_from(value: Storage<super::I8x16V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi8_epi32(value), arch::_mm256_cvtepi8_epi32(arch::_mm_srli_si128(value, 8)), ])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U8x16V3> for ArrayRegister<super::U32x8V3, 2> {
fn cast_from(value: Storage<super::U8x16V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepu8_epi32(value),
arch::_mm256_cvtepu8_epi32(arch::_mm_srli_si128(value, 8)),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<i8, 2>> for super::half::I32x2V3 {
fn cast_from(value: Storage<ArrayRegister<i8, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<u8, 2>> for super::half::U32x2V3 {
fn cast_from(value: Storage<ArrayRegister<u8, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::half::I32x2V3> for ArrayRegister<i8, 2> {
fn cast_from(value: Storage<super::half::I32x2V3>) -> Storage<Self> {
let mut arr = [0i32; 4];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
ArrayRegister([arr[0] as i8, arr[1] as i8])
}
sat_clamp_narrow8!(super::half::I32x2V3, i32, i8);
}
#[thermite_macros::inline_always]
impl CastRegister<super::half::U32x2V3> for ArrayRegister<u8, 2> {
fn cast_from(value: Storage<super::half::U32x2V3>) -> Storage<Self> {
let mut arr = [0u32; 4];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
ArrayRegister([arr[0] as u8, arr[1] as u8])
}
sat_clamp_narrow8!(super::half::U32x2V3, u32, u8);
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<i8, 2>> for super::I64x2V3 {
fn cast_from(value: Storage<ArrayRegister<i8, 2>>) -> Storage<Self> {
unsafe { arch::_mm_set_epi64x(value.0[1] as i64, value.0[0] as i64) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<u8, 2>> for super::U64x2V3 {
fn cast_from(value: Storage<ArrayRegister<u8, 2>>) -> Storage<Self> {
unsafe { arch::_mm_set_epi64x(value.0[1] as i64, value.0[0] as i64) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I64x2V3> for ArrayRegister<i8, 2> {
fn cast_from(value: Storage<super::I64x2V3>) -> Storage<Self> {
let mut arr = [0i64; 2];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value) };
ArrayRegister([arr[0] as i8, arr[1] as i8])
}
sat_clamp_narrow8!(super::I64x2V3, i64, i8);
}
#[thermite_macros::inline_always]
impl CastRegister<super::U64x2V3> for ArrayRegister<u8, 2> {
fn cast_from(value: Storage<super::U64x2V3>) -> Storage<Self> {
let mut arr = [0u64; 2];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value) };
ArrayRegister([arr[0] as u8, arr[1] as u8])
}
sat_clamp_narrow8!(super::U64x2V3, u64, u8);
}
#[thermite_macros::inline_always]
impl CastRegister<I8x4V3> for super::I64x4V3 {
fn cast_from(value: Storage<I8x4V3>) -> Storage<Self> {
unsafe { arch::_mm256_cvtepi8_epi64(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x4V3> for super::U64x4V3 {
fn cast_from(value: Storage<U8x4V3>) -> Storage<Self> {
unsafe { arch::_mm256_cvtepu8_epi64(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I64x4V3> for I8x4V3 {
fn cast_from(value: Storage<super::I64x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm256_cvtepi64_epi8x_v3(value) })
}
sat_clamp_narrow8!(super::I64x4V3, i64, i8);
}
#[thermite_macros::inline_always]
impl CastRegister<super::U64x4V3> for U8x4V3 {
fn cast_from(value: Storage<super::U64x4V3>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm256_cvtepi64_epi8x_v3(value) })
}
sat_clamp_narrow8!(super::U64x4V3, u64, u8);
}
#[thermite_macros::inline_always]
impl CastRegister<I8x8V3> for ArrayRegister<super::I64x4V3, 2> {
fn cast_from(value: Storage<I8x8V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi8_epi64(value.0), arch::_mm256_cvtepi8_epi64(arch::_mm_srli_si128(value.0, 4)), ])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x8V3> for ArrayRegister<super::U64x4V3, 2> {
fn cast_from(value: Storage<U8x8V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepu8_epi64(value.0),
arch::_mm256_cvtepu8_epi64(arch::_mm_srli_si128(value.0, 4)),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::I64x4V3, 2>> for I8x8V3 {
fn cast_from(value: Storage<ArrayRegister<super::I64x4V3, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_cvt2epi64x4_epi8x_v3(value.0) })
}
fn saturating_cast_from(value: Storage<ArrayRegister<super::I64x4V3, 2>>) -> Storage<Self> {
let words = <super::I16x8V3 as CastRegister<ArrayRegister<super::I64x4V3, 2>>>::saturating_cast_from(value);
<Self as CastRegister<super::I16x8V3>>::saturating_cast_from(words)
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::U64x4V3, 2>> for U8x8V3 {
fn cast_from(value: Storage<ArrayRegister<super::U64x4V3, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_cvt2epi64x4_epi8x_v3(value.0) })
}
fn saturating_cast_from(value: Storage<ArrayRegister<super::U64x4V3, 2>>) -> Storage<Self> {
let words = <super::U16x8V3 as CastRegister<ArrayRegister<super::U64x4V3, 2>>>::saturating_cast_from(value);
<Self as CastRegister<super::U16x8V3>>::saturating_cast_from(words)
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I8x16V3> for ArrayRegister<super::I64x4V3, 4> {
fn cast_from(value: Storage<super::I8x16V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi8_epi64(value),
arch::_mm256_cvtepi8_epi64(arch::_mm_srli_si128(value, 4)),
arch::_mm256_cvtepi8_epi64(arch::_mm_srli_si128(value, 8)),
arch::_mm256_cvtepi8_epi64(arch::_mm_srli_si128(value, 12)),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U8x16V3> for ArrayRegister<super::U64x4V3, 4> {
fn cast_from(value: Storage<super::U8x16V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepu8_epi64(value),
arch::_mm256_cvtepu8_epi64(arch::_mm_srli_si128(value, 4)),
arch::_mm256_cvtepu8_epi64(arch::_mm_srli_si128(value, 8)),
arch::_mm256_cvtepu8_epi64(arch::_mm_srli_si128(value, 12)),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<i8, 2>> for super::half::F32x2V3 {
fn cast_from(value: Storage<ArrayRegister<i8, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
let widened = arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0);
arch::_mm_cvtepi32_ps(widened)
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<u8, 2>> for super::half::F32x2V3 {
fn cast_from(value: Storage<ArrayRegister<u8, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
let widened = arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0);
arch::_mm_cvtepi32_ps(widened)
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<i8, 2>> for super::F64x2V3 {
fn cast_from(value: Storage<ArrayRegister<i8, 2>>) -> Storage<Self> {
unsafe {
let widened = arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0);
arch::_mm_cvtepi32_pd(widened)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<u8, 2>> for super::F64x2V3 {
fn cast_from(value: Storage<ArrayRegister<u8, 2>>) -> Storage<Self> {
unsafe {
let widened = arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0);
arch::_mm_cvtepi32_pd(widened)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<I8x4V3> for super::F32x4V3 {
fn cast_from(value: Storage<I8x4V3>) -> Storage<Self> {
unsafe {
let widened = arch::_mm_cvtepi8_epi32(value.0);
arch::_mm_cvtepi32_ps(widened)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x4V3> for super::F32x4V3 {
fn cast_from(value: Storage<U8x4V3>) -> Storage<Self> {
unsafe {
let widened = arch::_mm_cvtepu8_epi32(value.0);
arch::_mm_cvtepi32_ps(widened)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<I8x4V3> for super::F64x4V3 {
fn cast_from(value: Storage<I8x4V3>) -> Storage<Self> {
unsafe {
let widened = arch::_mm_cvtepi8_epi32(value.0); arch::_mm256_cvtepi32_pd(widened) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x4V3> for super::F64x4V3 {
fn cast_from(value: Storage<U8x4V3>) -> Storage<Self> {
unsafe {
let widened = arch::_mm_cvtepu8_epi32(value.0);
arch::_mm256_cvtepi32_pd(widened)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<I8x8V3> for super::F32x8V3 {
fn cast_from(value: Storage<I8x8V3>) -> Storage<Self> {
unsafe {
let widened = arch::_mm256_cvtepi8_epi32(value.0); arch::_mm256_cvtepi32_ps(widened)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x8V3> for super::F32x8V3 {
fn cast_from(value: Storage<U8x8V3>) -> Storage<Self> {
unsafe {
let widened = arch::_mm256_cvtepu8_epi32(value.0);
arch::_mm256_cvtepi32_ps(widened)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<I8x8V3> for ArrayRegister<super::F64x4V3, 2> {
fn cast_from(value: Storage<I8x8V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepi8_epi32(value.0)), arch::_mm256_cvtepi32_pd(arch::_mm_cvtepi8_epi32(arch::_mm_srli_si128(value.0, 4))), ])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<U8x8V3> for ArrayRegister<super::F64x4V3, 2> {
fn cast_from(value: Storage<U8x8V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepu8_epi32(value.0)),
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepu8_epi32(arch::_mm_srli_si128(value.0, 4))),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I8x16V3> for ArrayRegister<super::F32x8V3, 2> {
fn cast_from(value: Storage<super::I8x16V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi32_ps(arch::_mm256_cvtepi8_epi32(value)), arch::_mm256_cvtepi32_ps(arch::_mm256_cvtepi8_epi32(arch::_mm_srli_si128(value, 8))), ])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U8x16V3> for ArrayRegister<super::F32x8V3, 2> {
fn cast_from(value: Storage<super::U8x16V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi32_ps(arch::_mm256_cvtepu8_epi32(value)),
arch::_mm256_cvtepi32_ps(arch::_mm256_cvtepu8_epi32(arch::_mm_srli_si128(value, 8))),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I8x16V3> for ArrayRegister<super::F64x4V3, 4> {
fn cast_from(value: Storage<super::I8x16V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepi8_epi32(value)),
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepi8_epi32(arch::_mm_srli_si128(value, 4))),
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepi8_epi32(arch::_mm_srli_si128(value, 8))),
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepi8_epi32(arch::_mm_srli_si128(value, 12))),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U8x16V3> for ArrayRegister<super::F64x4V3, 4> {
fn cast_from(value: Storage<super::U8x16V3>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepu8_epi32(value)),
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepu8_epi32(arch::_mm_srli_si128(value, 4))),
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepu8_epi32(arch::_mm_srli_si128(value, 8))),
arch::_mm256_cvtepi32_pd(arch::_mm_cvtepu8_epi32(arch::_mm_srli_si128(value, 12))),
])
}
}
}
#[inline(always)]
fn bool_to_i8_mask(b: bool) -> i8 {
if b { !0 } else { 0 }
}
macro_rules! impl_mask_concat_x4_from_bool2 {
($red:ty) => {
#[thermite_macros::inline_always]
impl ConcatRegister<ArrayRegister<bool, 2>> for $red {
fn concat(lo: Storage<ArrayRegister<bool, 2>>, hi: Storage<ArrayRegister<bool, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi8(
bool_to_i8_mask(lo.0[0]),
bool_to_i8_mask(lo.0[1]),
bool_to_i8_mask(hi.0[0]),
bool_to_i8_mask(hi.0[1]),
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
)
})
}
fn split(value: Storage<Self>) -> (Storage<ArrayRegister<bool, 2>>, Storage<ArrayRegister<bool, 2>>) {
let a = store_bytes(value.0);
(
ArrayRegister([a[0] != 0, a[1] != 0]),
ArrayRegister([a[2] != 0, a[3] != 0]),
)
}
}
#[thermite_macros::inline_always]
impl ExtendRegister<ArrayRegister<bool, 2>> for $red {
fn extend(value: Storage<ArrayRegister<bool, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi8(
bool_to_i8_mask(value.0[0]),
bool_to_i8_mask(value.0[1]),
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
)
})
}
fn narrow(value: Storage<Self>) -> Storage<ArrayRegister<bool, 2>> {
let a = store_bytes(value.0);
ArrayRegister([a[0] != 0, a[1] != 0])
}
}
};
}
impl_mask_concat_x4_from_bool2!(I8x4V3);
impl_mask_concat_x4_from_bool2!(U8x4V3);
macro_rules! impl_indexable8 {
($idx:ty => $($ty:ty),* $(,)?) => {$( impl IndexableRegister<$idx> for $ty {} )*};
}
impl_indexable8!(<super::super::X86V3 as crate::simd::Simd>::u32x4 => I8x4V3, U8x4V3);
impl_indexable8!(<super::super::X86V3 as crate::simd::Simd>::u64x4 => I8x4V3, U8x4V3);
impl_indexable8!(<super::super::X86V3 as crate::simd::Simd>::u32x8 => I8x8V3, U8x8V3);
impl_indexable8!(<super::super::X86V3 as crate::simd::Simd>::u64x8 => I8x8V3, U8x8V3);