7373//! [sbbf-paper]: https://arxiv.org/pdf/2101.01719
7474//! [bf-formulae]: http://tfk.mit.edu/pdf/bloom.pdf
7575
76+ use core:: simd:: cmp:: SimdPartialEq ;
77+ use core:: simd:: Simd ;
78+
7679/// Salt values as defined in the [spec](https://github.com/apache/parquet-format/blob/master/BloomFilter.md#technical-approach).
7780const SALT : [ u32 ; 8 ] = [
7881 0x47b6137b_u32 ,
@@ -90,20 +93,16 @@ const SALT: [u32; 8] = [
9093#[ derive( Debug , Copy , Clone ) ]
9194#[ repr( transparent) ]
9295struct Block ( [ u32 ; 8 ] ) ;
96+
97+ type U32x8 = Simd < u32 , 8 > ;
98+
9399impl Block {
94100 const ZERO : Block = Block ( [ 0 ; 8 ] ) ;
95101
96102 /// takes as its argument a single unsigned 32-bit integer and returns a block in which each
97103 /// word has exactly one bit set.
98104 fn mask ( x : u32 ) -> Self {
99- let mut result = [ 0_u32 ; 8 ] ;
100- for i in 0 ..8 {
101- // wrapping instead of checking for overflow
102- let y = x. wrapping_mul ( SALT [ i] ) ;
103- let y = y >> 27 ;
104- result[ i] = 1 << y;
105- }
106- Self ( result)
105+ Self ( Self :: mask_simd ( x) . to_array ( ) )
107106 }
108107
109108 #[ inline]
@@ -136,13 +135,17 @@ impl Block {
136135
137136 /// Returns true when every bit that is set in the result of mask is also set in the block.
138137 fn check ( & self , hash : u32 ) -> bool {
139- let mask = Self :: mask ( hash) ;
140- for i in 0 ..8 {
141- if self [ i] & mask[ i] == 0 {
142- return false ;
143- }
144- }
145- true
138+ let mask = Self :: mask_simd ( hash) ;
139+ let block_vec = U32x8 :: from_array ( self . 0 ) ;
140+ ( block_vec & mask) . simd_ne ( U32x8 :: splat ( 0 ) ) . all ( )
141+ }
142+
143+ #[ inline( always) ]
144+ fn mask_simd ( x : u32 ) -> U32x8 {
145+ let hash_vec = U32x8 :: splat ( x) ;
146+ let salt_vec = U32x8 :: from_array ( SALT ) ;
147+ let bit_index = ( hash_vec * salt_vec) >> U32x8 :: splat ( 27 ) ;
148+ U32x8 :: splat ( 1 ) << bit_index
146149 }
147150}
148151
0 commit comments