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,80 @@ 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+ }
165+ }
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+ macro_rules! impl_traits {
172+ ( $( $const_: ident) ?) => {
173+ impl <T : $( [ $const_] ) ? PartialEq , const N : usize > $( $const_) ? PartialEq for Simd <T , N > {
174+ fn eq( & self , other: & Self ) -> bool {
175+ self . as_array( ) == other. as_array( )
176+ }
177+ }
178+
179+ impl <T , const N : usize > $( $const_) ? core:: ops:: Index <usize > for Simd <T , N > {
180+ type Output = T ;
181+ fn index( & self , i: usize ) -> & T {
182+ & self . as_array( ) [ i]
183+ }
184+ }
185+
186+ impl <T : $( [ $const_] ) ? PartialEq , const N : usize > $( $const_) ? PartialEq for PackedSimd <T , N >
187+ {
188+ fn eq( & self , other: & Self ) -> bool {
189+ self . as_array( ) == other. as_array( )
190+ }
191+ }
192+ } ;
160193}
194+
195+ #[ cfg( minisimd_const) ]
196+ impl_traits ! ( const ) ;
197+
198+ #[ cfg( not( minisimd_const) ) ]
199+ impl_traits ! ( ) ;
200+
201+ /// Version of `assert_eq` that ignores fancy runtime printing in const context
202+ #[ cfg( minisimd_const) ]
203+ #[ macro_export]
204+ macro_rules! assert_eq {
205+ ( $left: expr, $right: expr $( , ) ?) => {
206+ assert_eq!(
207+ $left,
208+ $right,
209+ concat!( "`" , stringify!( $left) , "` == `" , stringify!( $right) , "`" )
210+ ) ;
211+ } ;
212+ ( $left: expr, $right: expr$( , $( $arg: tt) +) ?) => {
213+ {
214+ let left = $left;
215+ let right = $right;
216+ // type inference works better with the concrete type on the
217+ // left, but humans work better with the expected on the
218+ // right
219+ assert!( right == left, $( $( $arg) * ) ,* ) ;
220+ }
221+ } ;
222+ }
223+
224+ #[ cfg( minisimd_const) ]
225+ use assert_eq;
0 commit comments