1010
1111#![ allow( unused) ]
1212#![ allow( non_camel_case_types) ]
13+ #![ allow( unexpected_cfgs) ]
1314
1415// The field is currently left `pub` for convenience in porting tests, many of
1516// which attempt to just construct it directly. That still works; it's just the
@@ -24,39 +25,32 @@ impl<T: Copy, const N: usize> Clone for Simd<T, N> {
2425 }
2526}
2627
27- impl < T : PartialEq , const N : usize > PartialEq for Simd < T , N > {
28- fn eq ( & self , other : & Self ) -> bool {
29- self . as_array ( ) == other. as_array ( )
30- }
31- }
32-
3328impl < T : core:: fmt:: Debug , const N : usize > core:: fmt:: Debug for Simd < T , N > {
3429 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> Result < ( ) , core:: fmt:: Error > {
3530 <[ T ; N ] as core:: fmt:: Debug >:: fmt ( self . as_array ( ) , f)
3631 }
3732}
3833
39- impl < T , const N : usize > core:: ops:: Index < usize > for Simd < T , N > {
40- type Output = T ;
41- fn index ( & self , i : usize ) -> & T {
42- & self . as_array ( ) [ i]
43- }
44- }
45-
4634impl < T , const N : usize > Simd < T , N > {
4735 pub const fn from_array ( a : [ T ; N ] ) -> Self {
4836 Simd ( a)
4937 }
50- pub fn as_array ( & self ) -> & [ T ; N ] {
38+ pub const fn as_array ( & self ) -> & [ T ; N ] {
5139 let p: * const Self = self ;
5240 unsafe { & * p. cast :: < [ T ; N ] > ( ) }
5341 }
54- pub fn into_array ( self ) -> [ T ; N ]
42+ pub const fn into_array ( self ) -> [ T ; N ]
5543 where
5644 T : Copy ,
5745 {
5846 * self . as_array ( )
5947 }
48+ pub const fn splat ( a : T ) -> Self
49+ where
50+ T : Copy ,
51+ {
52+ Self ( [ a; N ] )
53+ }
6054}
6155
6256pub type u8x2 = Simd < u8 , 2 > ;
@@ -109,6 +103,14 @@ pub type i64x8 = Simd<i64, 8>;
109103pub type i128x2 = Simd < i128 , 2 > ;
110104pub type i128x4 = Simd < i128 , 4 > ;
111105
106+ pub type usizex2 = Simd < usize , 2 > ;
107+ pub type usizex4 = Simd < usize , 4 > ;
108+ pub type usizex8 = Simd < usize , 8 > ;
109+
110+ pub type isizex2 = Simd < isize , 2 > ;
111+ pub type isizex4 = Simd < isize , 4 > ;
112+ pub type isizex8 = Simd < isize , 8 > ;
113+
112114pub type f32x2 = Simd < f32 , 2 > ;
113115pub type f32x4 = Simd < f32 , 4 > ;
114116pub type f32x8 = Simd < f32 , 8 > ;
@@ -122,7 +124,7 @@ pub type f64x8 = Simd<f64, 8>;
122124// which attempt to just construct it directly. That still works; it's just the
123125// `.0` projection that doesn't.
124126#[ repr( simd, packed) ]
125- #[ derive( Copy ) ]
127+ #[ derive( Copy , Eq ) ]
126128pub struct PackedSimd < T , const N : usize > ( pub [ T ; N ] ) ;
127129
128130impl < T : Copy , const N : usize > Clone for PackedSimd < T , N > {
@@ -131,12 +133,6 @@ impl<T: Copy, const N: usize> Clone for PackedSimd<T, N> {
131133 }
132134}
133135
134- impl < T : PartialEq , const N : usize > PartialEq for PackedSimd < T , N > {
135- fn eq ( & self , other : & Self ) -> bool {
136- self . as_array ( ) == other. as_array ( )
137- }
138- }
139-
140136impl < T : core:: fmt:: Debug , const N : usize > core:: fmt:: Debug for PackedSimd < T , N > {
141137 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> Result < ( ) , core:: fmt:: Error > {
142138 <[ T ; N ] as core:: fmt:: Debug >:: fmt ( self . as_array ( ) , f)
@@ -147,14 +143,100 @@ impl<T, const N: usize> PackedSimd<T, N> {
147143 pub const fn from_array ( a : [ T ; N ] ) -> Self {
148144 PackedSimd ( a)
149145 }
150- pub fn as_array ( & self ) -> & [ T ; N ] {
146+ pub const fn as_array ( & self ) -> & [ T ; N ] {
151147 let p: * const Self = self ;
152148 unsafe { & * p. cast :: < [ T ; N ] > ( ) }
153149 }
154- pub fn into_array ( self ) -> [ T ; N ]
150+ pub const fn into_array ( self ) -> [ T ; N ]
155151 where
156152 T : Copy ,
157153 {
158154 * self . as_array ( )
159155 }
156+ pub const fn splat ( a : T ) -> Self
157+ where
158+ T : Copy ,
159+ {
160+ Self ( [ a; N ] )
161+ }
160162}
163+
164+ // As `const_trait_impl` is a language feature with specialized syntax, we have to use them in a way
165+ // such that it doesn't get parsed as Rust code unless `cfg(minisimd_const)` is on. The easiest way
166+ // for that is a macro
167+
168+ #[ cfg( minisimd_const) ]
169+ macro_rules! impl_traits {
170+ ( ) => {
171+ impl <T : [ const ] PartialEq , const N : usize > const PartialEq for Simd <T , N > {
172+ fn eq( & self , other: & Self ) -> bool {
173+ self . as_array( ) == other. as_array( )
174+ }
175+ }
176+
177+ impl <T , const N : usize > const core:: ops:: Index <usize > for Simd <T , N > {
178+ type Output = T ;
179+ fn index( & self , i: usize ) -> & T {
180+ & self . as_array( ) [ i]
181+ }
182+ }
183+
184+ impl <T : [ const ] PartialEq , const N : usize > const PartialEq for PackedSimd <T , N > {
185+ fn eq( & self , other: & Self ) -> bool {
186+ self . as_array( ) == other. as_array( )
187+ }
188+ }
189+ } ;
190+ }
191+
192+ #[ cfg( not( minisimd_const) ) ]
193+ macro_rules! impl_traits {
194+ ( ) => {
195+ impl <T : PartialEq , const N : usize > PartialEq for Simd <T , N > {
196+ fn eq( & self , other: & Self ) -> bool {
197+ self . as_array( ) == other. as_array( )
198+ }
199+ }
200+
201+ impl <T , const N : usize > core:: ops:: Index <usize > for Simd <T , N > {
202+ type Output = T ;
203+ fn index( & self , i: usize ) -> & T {
204+ & self . as_array( ) [ i]
205+ }
206+ }
207+
208+ impl <T : PartialEq , const N : usize > PartialEq for PackedSimd <T , N > {
209+ fn eq( & self , other: & Self ) -> bool {
210+ self . as_array( ) == other. as_array( )
211+ }
212+ }
213+ } ;
214+ }
215+
216+ impl_traits ! ( ) ;
217+
218+ /// Version of `assert_eq` that ignores fancy runtime printing in const context
219+ #[ cfg( minisimd_const) ]
220+ #[ macro_export]
221+ macro_rules! assert_eq_const_safe {
222+ ( $left: expr, $right: expr $( , ) ?) => {
223+ assert_eq_const_safe!(
224+ $left,
225+ $right,
226+ concat!( "`" , stringify!( $left) , "` == `" , stringify!( $right) , "`" )
227+ ) ;
228+ } ;
229+ ( $left: expr, $right: expr$( , $( $arg: tt) +) ?) => {
230+ {
231+ let left = $left;
232+ let right = $right;
233+ // type inference works better with the concrete type on the
234+ // left, but humans work better with the expected on the
235+ // right
236+ assert!( right == left, $( $( $arg) * ) ,* ) ;
237+ }
238+ } ;
239+ }
240+
241+ #[ cfg( minisimd_const) ]
242+ use assert_eq_const_safe;
0 commit comments