common_traits/
splat.rs

1/// Take a smaller value and broadcast to all the values
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    fn splat(value: T) -> Self;
7}
8
9/// Blanket implementation that ensures that a reflexive splat is a no-operation
10impl<T> Splat<T> for T {
11    #[inline(always)]
12    fn splat(value: T) -> Self {
13        value
14    }
15}
16
17macro_rules! impl_broadcast {
18    ($($ty1:ty => $ty2:ty,)*) => {
19$(
20impl Splat<$ty1> for $ty2 {
21    #[inline(always)]
22    fn splat(value: $ty1) -> Self {
23        const SIZE: usize = core::mem::size_of::<$ty2>() / core::mem::size_of::<$ty1>();
24        #[allow(clippy::useless_transmute)]
25        <$ty2>::from_ne_bytes(unsafe{
26            core::mem::transmute::<[$ty1; SIZE], [u8; core::mem::size_of::<$ty2>()]>([value; SIZE])
27        })
28    }
29}
30)*
31    };
32}
33
34impl_broadcast!(
35    u8 => u16,
36    u8 => u32,
37    u8 => u64,
38    u8 => usize,
39    u8 => u128,
40
41    u16 => u32,
42    u16 => u64,
43    u16 => u128,
44
45    u32 => u64,
46    u32 => u128,
47
48    u64 => u128,
49    // TODO add simd splat
50);