@@ -166,20 +166,58 @@ macro_rules! define_common_ops {
166166 unsafe { simd_mul( self , other) }
167167 }
168168 }
169- ) +
170- }
171- }
172169
173- macro_rules! define_float_ops {
174- ( $( $ty: ident) ,+) => {
175- $(
176170 impl :: std:: ops:: Div for $ty {
177171 type Output = Self ;
178172 #[ inline( always) ]
179173 fn div( self , other: Self ) -> Self {
180174 unsafe { simd_div( self , other) }
181175 }
182176 }
177+
178+ impl :: std:: ops:: Rem for $ty {
179+ type Output = Self ;
180+ #[ inline( always) ]
181+ fn rem( self , other: Self ) -> Self {
182+ unsafe { simd_rem( self , other) }
183+ }
184+ }
185+
186+ impl :: std:: ops:: AddAssign for $ty {
187+ #[ inline( always) ]
188+ fn add_assign( & mut self , other: Self ) {
189+ * self = * self + other;
190+ }
191+ }
192+
193+ impl :: std:: ops:: SubAssign for $ty {
194+ #[ inline( always) ]
195+ fn sub_assign( & mut self , other: Self ) {
196+ * self = * self - other;
197+ }
198+ }
199+
200+ impl :: std:: ops:: MulAssign for $ty {
201+ #[ inline( always) ]
202+ fn mul_assign( & mut self , other: Self ) {
203+ * self = * self * other;
204+ }
205+ }
206+
207+ impl :: std:: ops:: DivAssign for $ty {
208+ #[ inline( always) ]
209+ fn div_assign( & mut self , other: Self ) {
210+ * self = * self / other;
211+ }
212+ }
213+
214+ impl :: std:: ops:: RemAssign for $ty {
215+ #[ inline( always) ]
216+ fn rem_assign( & mut self , other: Self ) {
217+ * self = * self % other;
218+ }
219+ }
220+
183221 ) +
184222 }
185223}
@@ -201,13 +239,63 @@ macro_rules! define_shifts {
201239 unsafe { simd_shr( self , $ty:: splat( other as $elem) ) }
202240 }
203241 }
242+
243+ impl :: std:: ops:: ShlAssign <$by> for $ty {
244+ #[ inline( always) ]
245+ fn shl_assign( & mut self , other: $by) {
246+ * self = * self << other;
247+ }
248+ }
249+ impl :: std:: ops:: ShrAssign <$by> for $ty {
250+ #[ inline( always) ]
251+ fn shr_assign( & mut self , other: $by) {
252+ * self = * self >> other;
253+ }
254+ }
255+
204256 ) +
205257 }
206258}
207259
260+ macro_rules! define_float_ops {
261+ ( $( $ty: ident) ,+) => {
262+ $(
263+ impl :: std:: ops:: Neg for $ty {
264+ type Output = Self ;
265+ #[ inline( always) ]
266+ fn neg( self ) -> Self {
267+ Self :: splat( -1.0 ) * self
268+ }
269+ }
270+ ) +
271+ } ;
272+ }
273+
274+ macro_rules! define_signed_integer_ops {
275+ ( $( $ty: ident) ,+) => {
276+ $(
277+ impl :: std:: ops:: Neg for $ty {
278+ type Output = Self ;
279+ #[ inline( always) ]
280+ fn neg( self ) -> Self {
281+ Self :: splat( -1 ) * self
282+ }
283+ }
284+ ) +
285+ } ;
286+ }
287+
208288macro_rules! define_integer_ops {
209289 ( $( ( $ty: ident, $elem: ident) ) ,+) => {
210290 $(
291+ impl :: std:: ops:: Not for $ty {
292+ type Output = Self ;
293+ #[ inline( always) ]
294+ fn not( self ) -> Self {
295+ $ty:: splat( !0 ) ^ self
296+ }
297+ }
298+
211299 impl :: std:: ops:: BitAnd for $ty {
212300 type Output = Self ;
213301 #[ inline( always) ]
@@ -229,13 +317,25 @@ macro_rules! define_integer_ops {
229317 unsafe { simd_xor( self , other) }
230318 }
231319 }
232- impl :: std:: ops:: Not for $ty {
233- type Output = Self ;
320+ impl :: std:: ops:: BitAndAssign for $ty {
234321 #[ inline( always) ]
235- fn not( self ) -> Self {
236- $ty:: splat( !0 ) ^ self
322+ fn bitand_assign( & mut self , other: Self ) {
323+ * self = * self & other;
324+ }
325+ }
326+ impl :: std:: ops:: BitOrAssign for $ty {
327+ #[ inline( always) ]
328+ fn bitor_assign( & mut self , other: Self ) {
329+ * self = * self | other;
330+ }
331+ }
332+ impl :: std:: ops:: BitXorAssign for $ty {
333+ #[ inline( always) ]
334+ fn bitxor_assign( & mut self , other: Self ) {
335+ * self = * self ^ other;
237336 }
238337 }
338+
239339 define_shifts!(
240340 $ty, $elem,
241341 u8 , u16 , u32 , u64 , usize ,
@@ -321,3 +421,186 @@ mod tests {
321421 assert ! ( cfg_feature_enabled!( "sse" ) ) ;
322422 }
323423}
424+
425+
426+ #[ cfg( test) ]
427+ #[ macro_export]
428+ macro_rules! test_arithmetic_ {
429+ ( $tn: ident, $zero: expr, $one: expr, $two: expr, $four: expr) => {
430+ {
431+ let z = $tn:: splat( $zero) ;
432+ let o = $tn:: splat( $one) ;
433+ let t = $tn:: splat( $two) ;
434+ let f = $tn:: splat( $four) ;
435+
436+ // add
437+ assert_eq!( z + z, z) ;
438+ assert_eq!( o + z, o) ;
439+ assert_eq!( t + z, t) ;
440+ assert_eq!( t + t, f) ;
441+ // sub
442+ assert_eq!( z - z, z) ;
443+ assert_eq!( o - z, o) ;
444+ assert_eq!( t - z, t) ;
445+ assert_eq!( f - t, t) ;
446+ assert_eq!( f - o - o, t) ;
447+ // mul
448+ assert_eq!( z * z, z) ;
449+ assert_eq!( z * o, z) ;
450+ assert_eq!( z * t, z) ;
451+ assert_eq!( o * t, t) ;
452+ assert_eq!( t * t, f) ;
453+ // div
454+ assert_eq!( z / o, z) ;
455+ assert_eq!( t / o, t) ;
456+ assert_eq!( f / o, f) ;
457+ assert_eq!( t / t, o) ;
458+ assert_eq!( f / t, t) ;
459+ // rem
460+ assert_eq!( o % o, z) ;
461+ assert_eq!( f % t, z) ;
462+
463+ {
464+ let mut v = z;
465+ assert_eq!( v, z) ;
466+ v += o; // add_assign
467+ assert_eq!( v, o) ;
468+ v -= o; // sub_assign
469+ assert_eq!( v, z) ;
470+ v = t;
471+ v *= o; // mul_assign
472+ assert_eq!( v, t) ;
473+ v *= t;
474+ assert_eq!( v, f) ;
475+ v /= o; // div_assign
476+ assert_eq!( v, f) ;
477+ v /= t;
478+ assert_eq!( v, t) ;
479+ v %= t; // rem_assign
480+ assert_eq!( v, z) ;
481+ }
482+ }
483+ } ;
484+ }
485+
486+ #[ cfg( test) ]
487+ #[ macro_export]
488+ macro_rules! test_neg_ {
489+ ( $tn: ident, $zero: expr, $one: expr, $two: expr, $four: expr) => {
490+ {
491+ let z = $tn:: splat( $zero) ;
492+ let o = $tn:: splat( $one) ;
493+ let t = $tn:: splat( $two) ;
494+ let f = $tn:: splat( $four) ;
495+
496+ let nz = $tn:: splat( -$zero) ;
497+ let no = $tn:: splat( -$one) ;
498+ let nt = $tn:: splat( -$two) ;
499+ let nf = $tn:: splat( -$four) ;
500+
501+ assert_eq!( -z, nz) ;
502+ assert_eq!( -o, no) ;
503+ assert_eq!( -t, nt) ;
504+ assert_eq!( -f, nf) ;
505+ }
506+ } ;
507+ }
508+
509+ #[ cfg( test) ]
510+ #[ macro_export]
511+ macro_rules! test_bit_arithmetic_ {
512+ ( $tn: ident) => {
513+ {
514+ let z = $tn:: splat( 0 ) ;
515+ let o = $tn:: splat( 1 ) ;
516+ let t = $tn:: splat( 2 ) ;
517+ let f = $tn:: splat( 4 ) ;
518+ let m = $tn:: splat( !z. extract( 0 ) ) ;
519+
520+ // shr
521+ assert_eq!( o >> 1 , z) ;
522+ assert_eq!( t >> 1 , o) ;
523+ assert_eq!( f >> 1 , t) ;
524+ // shl
525+ assert_eq!( o << 1 , t) ;
526+ assert_eq!( o << 2 , f) ;
527+ assert_eq!( t << 1 , f) ;
528+ // bitand
529+ assert_eq!( o & o, o) ;
530+ assert_eq!( t & t, t) ;
531+ assert_eq!( t & o, z) ;
532+ // bitor
533+ assert_eq!( o | o, o) ;
534+ assert_eq!( t | t, t) ;
535+ assert_eq!( z | o, o) ;
536+ // bitxor
537+ assert_eq!( o ^ o, z) ;
538+ assert_eq!( t ^ t, z) ;
539+ assert_eq!( z ^ o, o) ;
540+ // not
541+ assert_eq!( !z, m) ;
542+ assert_eq!( !m, z) ;
543+
544+ { // shr_assign
545+ let mut v = o;
546+ v >>= 1 ;
547+ assert_eq!( v, z) ;
548+ }
549+ { // shl_assign
550+ let mut v = o;
551+ v <<= 1 ;
552+ assert_eq!( v, t) ;
553+ }
554+ { // and_assign
555+ let mut v = o;
556+ v &= t;
557+ assert_eq!( v, z) ;
558+ }
559+ { // or_assign
560+ let mut v = z;
561+ v |= o;
562+ assert_eq!( v, o) ;
563+ }
564+ { // xor_assign
565+ let mut v = z;
566+ v ^= o;
567+ assert_eq!( v, o) ;
568+ }
569+ }
570+ } ;
571+ }
572+
573+
574+ #[ cfg( test) ]
575+ #[ macro_export]
576+ macro_rules! test_ops_si {
577+ ( $( $tn: ident) ,+) => {
578+ $(
579+ test_arithmetic_!( $tn, 0 , 1 , 2 , 4 ) ;
580+ test_neg_!( $tn, 0 , 1 , 2 , 4 ) ;
581+ test_bit_arithmetic_!( $tn) ;
582+ ) +
583+ } ;
584+ }
585+
586+ #[ cfg( test) ]
587+ #[ macro_export]
588+ macro_rules! test_ops_ui {
589+ ( $( $tn: ident) ,+) => {
590+ $(
591+ test_arithmetic_!( $tn, 0 , 1 , 2 , 4 ) ;
592+ test_bit_arithmetic_!( $tn) ;
593+ ) +
594+ } ;
595+ }
596+
597+ #[ cfg( test) ]
598+ #[ macro_export]
599+ macro_rules! test_ops_f {
600+ ( $( $tn: ident) ,+) => {
601+ $(
602+ test_arithmetic_!( $tn, 0. , 1. , 2. , 4. ) ;
603+ test_neg_!( $tn, 0. , 1. , 2. , 4. ) ;
604+ ) +
605+ } ;
606+ }
0 commit comments