@@ -13,6 +13,115 @@ macro_rules! impl_shuffle_lane {
13
13
pub fn shuffle<const IDX : [ u32 ; $n] >( self , second: Self ) -> Self {
14
14
unsafe { crate :: intrinsics:: $fn( self , second, IDX ) }
15
15
}
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
+ }
16
125
}
17
126
}
18
127
}
0 commit comments