1010
1111#![ allow( unused) ]
1212#![ allow( non_camel_case_types) ]
13+ // FIXME: `cfg(minisimd_const)` is used to toggle use of const trait impls, which require a few
14+ // nightly features. Remove this when `const_trait_impls`, `const_cmp` and `const_index` are
15+ // stablilized.
16+ #![ allow( unexpected_cfgs) ]
1317
1418// The field is currently left `pub` for convenience in porting tests, many of
1519// which attempt to just construct it directly. That still works; it's just the
@@ -24,39 +28,32 @@ impl<T: Copy, const N: usize> Clone for Simd<T, N> {
2428 }
2529}
2630
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-
3331impl < T : core:: fmt:: Debug , const N : usize > core:: fmt:: Debug for Simd < T , N > {
3432 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> Result < ( ) , core:: fmt:: Error > {
3533 <[ T ; N ] as core:: fmt:: Debug >:: fmt ( self . as_array ( ) , f)
3634 }
3735}
3836
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-
4637impl < T , const N : usize > Simd < T , N > {
4738 pub const fn from_array ( a : [ T ; N ] ) -> Self {
4839 Simd ( a)
4940 }
50- pub fn as_array ( & self ) -> & [ T ; N ] {
41+ pub const fn as_array ( & self ) -> & [ T ; N ] {
5142 let p: * const Self = self ;
5243 unsafe { & * p. cast :: < [ T ; N ] > ( ) }
5344 }
54- pub fn into_array ( self ) -> [ T ; N ]
45+ pub const fn into_array ( self ) -> [ T ; N ]
5546 where
5647 T : Copy ,
5748 {
5849 * self . as_array ( )
5950 }
51+ pub const fn splat ( a : T ) -> Self
52+ where
53+ T : Copy ,
54+ {
55+ Self ( [ a; N ] )
56+ }
6057}
6158
6259pub type u8x2 = Simd < u8 , 2 > ;
@@ -109,6 +106,14 @@ pub type i64x8 = Simd<i64, 8>;
109106pub type i128x2 = Simd < i128 , 2 > ;
110107pub type i128x4 = Simd < i128 , 4 > ;
111108
109+ pub type usizex2 = Simd < usize , 2 > ;
110+ pub type usizex4 = Simd < usize , 4 > ;
111+ pub type usizex8 = Simd < usize , 8 > ;
112+
113+ pub type isizex2 = Simd < isize , 2 > ;
114+ pub type isizex4 = Simd < isize , 4 > ;
115+ pub type isizex8 = Simd < isize , 8 > ;
116+
112117pub type f32x2 = Simd < f32 , 2 > ;
113118pub type f32x4 = Simd < f32 , 4 > ;
114119pub type f32x8 = Simd < f32 , 8 > ;
@@ -122,7 +127,7 @@ pub type f64x8 = Simd<f64, 8>;
122127// which attempt to just construct it directly. That still works; it's just the
123128// `.0` projection that doesn't.
124129#[ repr( simd, packed) ]
125- #[ derive( Copy ) ]
130+ #[ derive( Copy , Eq ) ]
126131pub struct PackedSimd < T , const N : usize > ( pub [ T ; N ] ) ;
127132
128133impl < T : Copy , const N : usize > Clone for PackedSimd < T , N > {
@@ -131,12 +136,6 @@ impl<T: Copy, const N: usize> Clone for PackedSimd<T, N> {
131136 }
132137}
133138
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-
140139impl < T : core:: fmt:: Debug , const N : usize > core:: fmt:: Debug for PackedSimd < T , N > {
141140 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> Result < ( ) , core:: fmt:: Error > {
142141 <[ T ; N ] as core:: fmt:: Debug >:: fmt ( self . as_array ( ) , f)
@@ -147,14 +146,100 @@ impl<T, const N: usize> PackedSimd<T, N> {
147146 pub const fn from_array ( a : [ T ; N ] ) -> Self {
148147 PackedSimd ( a)
149148 }
150- pub fn as_array ( & self ) -> & [ T ; N ] {
149+ pub const fn as_array ( & self ) -> & [ T ; N ] {
151150 let p: * const Self = self ;
152151 unsafe { & * p. cast :: < [ T ; N ] > ( ) }
153152 }
154- pub fn into_array ( self ) -> [ T ; N ]
153+ pub const fn into_array ( self ) -> [ T ; N ]
155154 where
156155 T : Copy ,
157156 {
158157 * self . as_array ( )
159158 }
159+ pub const fn splat ( a : T ) -> Self
160+ where
161+ T : Copy ,
162+ {
163+ Self ( [ a; N ] )
164+ }
160165}
166+
167+ // As `const_trait_impl` is a language feature with specialized syntax, we have to use them in a way
168+ // such that it doesn't get parsed as Rust code unless `cfg(minisimd_const)` is on. The easiest way
169+ // for that is a macro
170+
171+ #[ cfg( minisimd_const) ]
172+ macro_rules! impl_traits {
173+ ( ) => {
174+ impl <T : [ const ] PartialEq , const N : usize > const PartialEq for Simd <T , N > {
175+ fn eq( & self , other: & Self ) -> bool {
176+ self . as_array( ) == other. as_array( )
177+ }
178+ }
179+
180+ impl <T , const N : usize > const core:: ops:: Index <usize > for Simd <T , N > {
181+ type Output = T ;
182+ fn index( & self , i: usize ) -> & T {
183+ & self . as_array( ) [ i]
184+ }
185+ }
186+
187+ impl <T : [ const ] PartialEq , const N : usize > const PartialEq for PackedSimd <T , N > {
188+ fn eq( & self , other: & Self ) -> bool {
189+ self . as_array( ) == other. as_array( )
190+ }
191+ }
192+ } ;
193+ }
194+
195+ #[ cfg( not( minisimd_const) ) ]
196+ macro_rules! impl_traits {
197+ ( ) => {
198+ impl <T : PartialEq , const N : usize > PartialEq for Simd <T , N > {
199+ fn eq( & self , other: & Self ) -> bool {
200+ self . as_array( ) == other. as_array( )
201+ }
202+ }
203+
204+ impl <T , const N : usize > core:: ops:: Index <usize > for Simd <T , N > {
205+ type Output = T ;
206+ fn index( & self , i: usize ) -> & T {
207+ & self . as_array( ) [ i]
208+ }
209+ }
210+
211+ impl <T : PartialEq , const N : usize > PartialEq for PackedSimd <T , N > {
212+ fn eq( & self , other: & Self ) -> bool {
213+ self . as_array( ) == other. as_array( )
214+ }
215+ }
216+ } ;
217+ }
218+
219+ impl_traits ! ( ) ;
220+
221+ /// Version of `assert_eq` that ignores fancy runtime printing in const context
222+ #[ cfg( minisimd_const) ]
223+ #[ macro_export]
224+ macro_rules! assert_eq_const_safe {
225+ ( $left: expr, $right: expr $( , ) ?) => {
226+ assert_eq_const_safe!(
227+ $left,
228+ $right,
229+ concat!( "`" , stringify!( $left) , "` == `" , stringify!( $right) , "`" )
230+ ) ;
231+ } ;
232+ ( $left: expr, $right: expr$( , $( $arg: tt) +) ?) => {
233+ {
234+ let left = $left;
235+ let right = $right;
236+ // type inference works better with the concrete type on the
237+ // left, but humans work better with the expected on the
238+ // right
239+ assert!( right == left, $( $( $arg) * ) ,* ) ;
240+ }
241+ } ;
242+ }
243+
244+ #[ cfg( minisimd_const) ]
245+ use assert_eq_const_safe;
0 commit comments