Skip to main content

common_traits/
splat.rs

1/// Takes a smaller value and broadcasts it to all positions.
2///
3/// (Thanks to B3NNY for the more readable code, this should compile to
4/// the original multiplication by 0x0101010101010101).
5pub trait Splat<T> {
6    /// Broadcasts `value` to all positions.
7    fn splat(value: T) -> Self;
8}
9
10/// Blanket implementation that ensures that a reflexive splat is a no-op.
11impl<T> Splat<T> for T {
12    #[inline(always)]
13    fn splat(value: T) -> Self {
14        value
15    }
16}
17
18macro_rules! impl_broadcast {
19    ($($ty1:ty => $ty2:ty,)*) => {
20$(
21impl Splat<$ty1> for $ty2 {
22    #[inline(always)]
23    fn splat(value: $ty1) -> Self {
24        const SIZE: usize = core::mem::size_of::<$ty2>() / core::mem::size_of::<$ty1>();
25        #[allow(clippy::useless_transmute)]
26        <$ty2>::from_ne_bytes(unsafe{
27            core::mem::transmute::<[$ty1; SIZE], [u8; core::mem::size_of::<$ty2>()]>([value; SIZE])
28        })
29    }
30}
31)*
32    };
33}
34
35impl_broadcast!(
36    u8 => u16,
37    u8 => u32,
38    u8 => u64,
39    u8 => usize,
40    u8 => u128,
41
42    u16 => u32,
43    u16 => u64,
44    u16 => u128,
45
46    u32 => u64,
47    u32 => u128,
48
49    u64 => u128,
50    // TODO add simd splat
51);