1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! Implements integer shifts.

macro_rules! impl_shifts {
    ($id:ident, $elem_ty:ident, $($by:ident),+) => {
        $(
            impl ::ops::Shl<$by> for $id {
                type Output = Self;
                #[inline]
                fn shl(self, other: $by) -> Self {
                    unsafe { simd_shl(self, $id::splat(other as $elem_ty)) }
                }
            }
            impl ::ops::Shr<$by> for $id {
                type Output = Self;
                #[inline]
                fn shr(self, other: $by) -> Self {
                    unsafe { simd_shr(self, $id::splat(other as $elem_ty)) }
                }
            }

            impl ::ops::ShlAssign<$by> for $id {
                #[inline]
                fn shl_assign(&mut self, other: $by) {
                    *self = *self << other;
                }
            }
            impl ::ops::ShrAssign<$by> for $id {
                #[inline]
                fn shr_assign(&mut self, other: $by) {
                    *self = *self >> other;
                }
            }

        )+
    }
}

macro_rules! impl_all_shifts {
    ($id:ident, $elem_ty:ident) => {
        impl_shifts!(
            $id, $elem_ty,
            u8, u16, u32, u64, usize,
            i8, i16, i32, i64, isize);

    }
}

#[cfg(test)]
#[macro_export]
macro_rules! test_shift_ops {
    ($id:ident, $elem_ty:ident, $($index_ty:ident),+) => {
        #[test]
        fn shift_ops() {
            use ::coresimd::simd::$id;
            use ::std::mem;
            let z = $id::splat(0 as $elem_ty);
            let o = $id::splat(1 as $elem_ty);
            let t = $id::splat(2 as $elem_ty);
            let f = $id::splat(4 as $elem_ty);

            $(
                {
                    let zi = 0 as $index_ty;
                    let oi = 1 as $index_ty;
                    let ti = 2 as $index_ty;
                    let maxi = (mem::size_of::<$elem_ty>() * 8 - 1) as $index_ty;

                    // shr
                    assert_eq!(z >> zi, z);
                    assert_eq!(z >> oi, z);
                    assert_eq!(z >> ti, z);
                    assert_eq!(z >> ti, z);

                    assert_eq!(o >> zi, o);
                    assert_eq!(t >> zi, t);
                    assert_eq!(f >> zi, f);
                    assert_eq!(f >> maxi, z);

                    assert_eq!(o >> oi, z);
                    assert_eq!(t >> oi, o);
                    assert_eq!(t >> ti, z);
                    assert_eq!(f >> oi, t);
                    assert_eq!(f >> ti, o);
                    assert_eq!(f >> maxi, z);

                    // shl
                    assert_eq!(z << zi, z);
                    assert_eq!(o << zi, o);
                    assert_eq!(t << zi, t);
                    assert_eq!(f << zi, f);
                    assert_eq!(f << maxi, z);

                    assert_eq!(o << oi, t);
                    assert_eq!(o << ti, f);
                    assert_eq!(t << oi, f);

                    {  // shr_assign
                        let mut v = o;
                        v >>= oi;
                        assert_eq!(v, z);
                    }
                    {  // shl_assign
                        let mut v = o;
                        v <<= oi;
                        assert_eq!(v, t);
                    }
                }
            )+
        }
    };
}

#[cfg(test)]
#[macro_export]
macro_rules! test_all_shift_ops {
    ($id:ident, $elem_ty:ident) => {
        test_shift_ops!(
            $id, $elem_ty,
            u8, u16, u32, u64, usize,
            i8, i16, i32, i64, isize);
    }
}