//! Default implementation of a mask reduction for any target. macro_rules! fallback_to_other_impl { ($id:ident, $other:ident) => { impl All for $id { #[inline] unsafe fn all(self) -> bool { let m: $other = crate::mem::transmute(self); m.all() } } impl Any for $id { #[inline] unsafe fn any(self) -> bool { let m: $other = crate::mem::transmute(self); m.any() } } }; } /// Fallback implementation. macro_rules! fallback_impl { // 16-bit wide masks: (m8x2) => { impl All for m8x2 { #[inline] unsafe fn all(self) -> bool { let i: u16 = crate::mem::transmute(self); i == u16::max_value() } } impl Any for m8x2 { #[inline] unsafe fn any(self) -> bool { let i: u16 = crate::mem::transmute(self); i != 0 } } }; // 32-bit wide masks (m8x4) => { impl All for m8x4 { #[inline] unsafe fn all(self) -> bool { let i: u32 = crate::mem::transmute(self); i == u32::max_value() } } impl Any for m8x4 { #[inline] unsafe fn any(self) -> bool { let i: u32 = crate::mem::transmute(self); i != 0 } } }; (m16x2) => { fallback_to_other_impl!(m16x2, m8x4); }; // 64-bit wide masks: (m8x8) => { impl All for m8x8 { #[inline] unsafe fn all(self) -> bool { let i: u64 = crate::mem::transmute(self); i == u64::max_value() } } impl Any for m8x8 { #[inline] unsafe fn any(self) -> bool { let i: u64 = crate::mem::transmute(self); i != 0 } } }; (m16x4) => { fallback_to_other_impl!(m16x4, m8x8); }; (m32x2) => { fallback_to_other_impl!(m32x2, m16x4); }; // FIXME: 64x1 maxk // 128-bit wide masks: (m8x16) => { impl All for m8x16 { #[inline] unsafe fn all(self) -> bool { let i: u128 = crate::mem::transmute(self); i == u128::max_value() } } impl Any for m8x16 { #[inline] unsafe fn any(self) -> bool { let i: u128 = crate::mem::transmute(self); i != 0 } } }; (m16x8) => { fallback_to_other_impl!(m16x8, m8x16); }; (m32x4) => { fallback_to_other_impl!(m32x4, m16x8); }; (m64x2) => { fallback_to_other_impl!(m64x2, m32x4); }; (m128x1) => { fallback_to_other_impl!(m128x1, m64x2); }; // 256-bit wide masks (m8x32) => { impl All for m8x32 { #[inline] unsafe fn all(self) -> bool { let i: [u128; 2] = crate::mem::transmute(self); let o: [u128; 2] = [u128::max_value(); 2]; i == o } } impl Any for m8x32 { #[inline] unsafe fn any(self) -> bool { let i: [u128; 2] = crate::mem::transmute(self); let o: [u128; 2] = [0; 2]; i != o } } }; (m16x16) => { fallback_to_other_impl!(m16x16, m8x32); }; (m32x8) => { fallback_to_other_impl!(m32x8, m16x16); }; (m64x4) => { fallback_to_other_impl!(m64x4, m32x8); }; (m128x2) => { fallback_to_other_impl!(m128x2, m64x4); }; // 512-bit wide masks (m8x64) => { impl All for m8x64 { #[inline] unsafe fn all(self) -> bool { let i: [u128; 4] = crate::mem::transmute(self); let o: [u128; 4] = [u128::max_value(); 4]; i == o } } impl Any for m8x64 { #[inline] unsafe fn any(self) -> bool { let i: [u128; 4] = crate::mem::transmute(self); let o: [u128; 4] = [0; 4]; i != o } } }; (m16x32) => { fallback_to_other_impl!(m16x32, m8x64); }; (m32x16) => { fallback_to_other_impl!(m32x16, m16x32); }; (m64x8) => { fallback_to_other_impl!(m64x8, m32x16); }; (m128x4) => { fallback_to_other_impl!(m128x4, m64x8); }; // Masks with pointer-sized elements64 (msizex2) => { cfg_if! { if #[cfg(target_pointer_width = "64")] { fallback_to_other_impl!(msizex2, m64x2); } else if #[cfg(target_pointer_width = "32")] { fallback_to_other_impl!(msizex2, m32x2); } else { compile_error!("unsupported target_pointer_width"); } } }; (msizex4) => { cfg_if! { if #[cfg(target_pointer_width = "64")] { fallback_to_other_impl!(msizex4, m64x4); } else if #[cfg(target_pointer_width = "32")] { fallback_to_other_impl!(msizex4, m32x4); } else { compile_error!("unsupported target_pointer_width"); } } }; (msizex8) => { cfg_if! { if #[cfg(target_pointer_width = "64")] { fallback_to_other_impl!(msizex8, m64x8); } else if #[cfg(target_pointer_width = "32")] { fallback_to_other_impl!(msizex8, m32x8); } else { compile_error!("unsupported target_pointer_width"); } } }; } macro_rules! recurse_half { ($vid:ident, $vid_h:ident) => { impl All for $vid { #[inline] unsafe fn all(self) -> bool { union U { halves: ($vid_h, $vid_h), vec: $vid, } let halves = U { vec: self }.halves; halves.0.all() && halves.1.all() } } impl Any for $vid { #[inline] unsafe fn any(self) -> bool { union U { halves: ($vid_h, $vid_h), vec: $vid, } let halves = U { vec: self }.halves; halves.0.any() || halves.1.any() } } }; }