@@ -387,6 +387,70 @@ macro_rules! uint_module {
387387 }
388388 }
389389
390+ #[ cfg( not( miri) ) ] // Miri is too slow
391+ #[ test]
392+ fn test_lots_of_gather_scatter( ) {
393+ // Generate a handful of bit patterns to use as inputs
394+ let xs = {
395+ let mut xs = vec![ ] ;
396+ let mut x: $T = !0 ;
397+ let mut w = $T:: BITS ;
398+ while w > 0 {
399+ w >>= 1 ;
400+ xs. push( x) ;
401+ xs. push( !x) ;
402+ x ^= x << w;
403+ }
404+ xs
405+ } ;
406+ if $T:: BITS == 8 {
407+ assert_eq!( & xs, & [ 0xff , 0x00 , 0x0f , 0xf0 , 0x33 , 0xcc , 0x55 , 0xaa ] ) ;
408+ }
409+
410+ // `256 * BITS` masks
411+ let sparse_masks = ( i8 :: MIN ..=i8 :: MAX )
412+ . map( |i| ( i as i128 as $T) . rotate_right( 4 ) )
413+ . flat_map( |x| ( 0 ..$T:: BITS ) . map( move |s| ( ( 1 as $T) << s) ^ x) ) ;
414+
415+ for sparse in sparse_masks {
416+ // Collect the set bits to sequential low bits
417+ let dense = sparse. gather_bits( sparse) ;
418+ let count = sparse. count_ones( ) ;
419+ assert_eq!( count, dense. count_ones( ) ) ;
420+ assert_eq!( count, dense. trailing_ones( ) ) ;
421+
422+ let mut t = sparse;
423+ for k in 0 ..$T:: BITS {
424+ let x = ( ( 1 as $T) << k) . scatter_bits( sparse) ;
425+ let y = t. isolate_lowest_one( ) ;
426+ assert_eq!( x, y) ;
427+ t ^= y;
428+ }
429+
430+ let mut t = sparse;
431+ for k in 0 ..count {
432+ let y = t. isolate_lowest_one( ) ;
433+ let x = y. gather_bits( sparse) ;
434+ assert_eq!( x, ( 1 as $T) << k) ;
435+ t ^= y;
436+ }
437+
438+ for & x in & xs {
439+ // Gather bits from `x & sparse` to `dense`
440+ let dx = x. gather_bits( sparse) ;
441+ assert_eq!( dx & !dense, 0 ) ;
442+
443+ // Scatter bits from `x & dense` to `sparse`
444+ let sx = x. scatter_bits( sparse) ;
445+ assert_eq!( sx & !sparse, 0 ) ;
446+
447+ // The other recovers the input (within the mask)
448+ assert_eq!( dx. scatter_bits( sparse) , x & sparse) ;
449+ assert_eq!( sx. gather_bits( sparse) , x & dense) ;
450+ }
451+ }
452+ }
453+
390454 test_runtime_and_compiletime! {
391455 fn test_div_floor( ) {
392456 assert_eq_const_safe!( $T: ( 8 as $T) . div_floor( 3 ) , 2 ) ;
0 commit comments