@@ -13,6 +13,115 @@ macro_rules! impl_shuffle_lane {
1313 pub fn shuffle<const IDX : [ u32 ; $n] >( self , second: Self ) -> Self {
1414 unsafe { crate :: intrinsics:: $fn( self , second, IDX ) }
1515 }
16+
17+ /// Reverse the order of the lanes in the vector.
18+ #[ inline]
19+ pub fn reverse( self ) -> Self {
20+ const fn idx( ) -> [ u32 ; $n] {
21+ let mut idx = [ 0u32 ; $n] ;
22+ let mut i = 0 ;
23+ while i < $n {
24+ idx[ i] = ( $n - i - 1 ) as u32 ;
25+ i += 1 ;
26+ }
27+ idx
28+ }
29+ self . shuffle:: <{ idx( ) } >( self )
30+ }
31+
32+ /// Interleave two vectors.
33+ ///
34+ /// Produces two vectors with lanes taken alternately from `self` and `other`.
35+ ///
36+ /// The first result contains the first `LANES / 2` lanes from `self` and `other`,
37+ /// alternating, starting with the first lane of `self`.
38+ ///
39+ /// The second result contains the last `LANES / 2` lanes from `self` and `other`,
40+ /// alternating, starting with the lane `LANES / 2` from the start of `self`.
41+ ///
42+ /// This particular permutation is efficient on many architectures.
43+ ///
44+ /// ```
45+ /// # use core_simd::SimdU32;
46+ /// let a = SimdU32::from_array([0, 1, 2, 3]);
47+ /// let b = SimdU32::from_array([4, 5, 6, 7]);
48+ /// let (x, y) = a.interleave(b);
49+ /// assert_eq!(x.to_array(), [0, 4, 1, 5]);
50+ /// assert_eq!(y.to_array(), [2, 6, 3, 7]);
51+ /// ```
52+ #[ inline]
53+ pub fn interleave( self , other: Self ) -> ( Self , Self ) {
54+ const fn lo( ) -> [ u32 ; $n] {
55+ let mut idx = [ 0u32 ; $n] ;
56+ let mut i = 0 ;
57+ while i < $n {
58+ let offset = i / 2 ;
59+ idx[ i] = if i % 2 == 0 {
60+ offset
61+ } else {
62+ $n + offset
63+ } as u32 ;
64+ i += 1 ;
65+ }
66+ idx
67+ }
68+ const fn hi( ) -> [ u32 ; $n] {
69+ let mut idx = [ 0u32 ; $n] ;
70+ let mut i = 0 ;
71+ while i < $n {
72+ let offset = ( $n + i) / 2 ;
73+ idx[ i] = if i % 2 == 0 {
74+ offset
75+ } else {
76+ $n + offset
77+ } as u32 ;
78+ i += 1 ;
79+ }
80+ idx
81+ }
82+ ( self . shuffle:: <{ lo( ) } >( other) , self . shuffle:: <{ hi( ) } >( other) )
83+ }
84+
85+ /// Deinterleave two vectors.
86+ ///
87+ /// The first result takes every other lane of `self` and then `other`, starting with
88+ /// the first lane.
89+ ///
90+ /// The second result takes every other lane of `self` and then `other`, starting with
91+ /// the second lane.
92+ ///
93+ /// This particular permutation is efficient on many architectures.
94+ ///
95+ /// ```
96+ /// # use core_simd::SimdU32;
97+ /// let a = SimdU32::from_array([0, 4, 1, 5]);
98+ /// let b = SimdU32::from_array([2, 6, 3, 7]);
99+ /// let (x, y) = a.deinterleave(b);
100+ /// assert_eq!(x.to_array(), [0, 1, 2, 3]);
101+ /// assert_eq!(y.to_array(), [4, 5, 6, 7]);
102+ /// ```
103+ #[ inline]
104+ pub fn deinterleave( self , other: Self ) -> ( Self , Self ) {
105+ const fn even( ) -> [ u32 ; $n] {
106+ let mut idx = [ 0u32 ; $n] ;
107+ let mut i = 0 ;
108+ while i < $n {
109+ idx[ i] = 2 * i as u32 ;
110+ i += 1 ;
111+ }
112+ idx
113+ }
114+ const fn odd( ) -> [ u32 ; $n] {
115+ let mut idx = [ 0u32 ; $n] ;
116+ let mut i = 0 ;
117+ while i < $n {
118+ idx[ i] = 1 + 2 * i as u32 ;
119+ i += 1 ;
120+ }
121+ idx
122+ }
123+ ( self . shuffle:: <{ even( ) } >( other) , self . shuffle:: <{ odd( ) } >( other) )
124+ }
16125 }
17126 }
18127}
0 commit comments