1111//! [`#[inline]`](https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute).
1212//!
1313//! An optional SIMD variant that computes multiple hashes in parallel is also implemented.
14-
1514pub fn buffer_size ( n : usize ) -> usize {
1615 ( n + 9 ) . next_multiple_of ( 64 )
1716}
1817
19- pub fn hash ( mut buffer : & mut [ u8 ] , size : usize ) -> ( u32 , u32 , u32 , u32 ) {
18+ pub fn hash ( buffer : & mut [ u8 ] , size : usize ) -> [ u32 ; 4 ] {
2019 let end = buffer. len ( ) - 8 ;
2120 let bits = size * 8 ;
2221
@@ -29,11 +28,8 @@ pub fn hash(mut buffer: &mut [u8], size: usize) -> (u32, u32, u32, u32) {
2928 let mut c0: u32 = 0x98badcfe ;
3029 let mut d0: u32 = 0x10325476 ;
3130
32- while !buffer. is_empty ( ) {
33- let ( prefix, suffix) = buffer. split_at_mut ( 64 ) ;
34- buffer = suffix;
35-
36- for ( i, chunk) in prefix. chunks_exact ( 4 ) . enumerate ( ) {
31+ for block in buffer. chunks_exact ( 64 ) {
32+ for ( i, chunk) in block. chunks_exact ( 4 ) . enumerate ( ) {
3733 m[ i] = u32:: from_le_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
3834 }
3935
@@ -116,7 +112,7 @@ pub fn hash(mut buffer: &mut [u8], size: usize) -> (u32, u32, u32, u32) {
116112 d0 = d0. wrapping_add ( d) ;
117113 }
118114
119- ( a0. to_be ( ) , b0. to_be ( ) , c0. to_be ( ) , d0. to_be ( ) )
115+ [ a0. to_be ( ) , b0. to_be ( ) , c0. to_be ( ) , d0. to_be ( ) ]
120116}
121117
122118#[ inline]
@@ -150,69 +146,62 @@ fn common(f: u32, a: u32, b: u32, m: u32, s: u32, k: u32) -> u32 {
150146
151147#[ cfg( feature = "simd" ) ]
152148pub mod simd {
153- use std:: array;
149+ use std:: array:: from_fn ;
154150 use std:: simd:: num:: SimdUint as _;
155151 use std:: simd:: { LaneCount , Simd , SupportedLaneCount } ;
156152
157153 #[ inline]
158154 #[ expect( clippy:: too_many_lines) ]
159- pub fn hash < const N : usize > (
160- buffers : & mut [ [ u8 ; 64 ] ] ,
161- size : usize ,
162- ) -> ( [ u32 ; N ] , [ u32 ; N ] , [ u32 ; N ] , [ u32 ; N ] )
155+ pub fn hash_fixed < const N : usize > ( buffers : & mut [ [ u8 ; 64 ] ; N ] , size : usize ) -> [ [ u32 ; N ] ; 4 ]
163156 where
164157 LaneCount < N > : SupportedLaneCount ,
165158 {
166159 // Assume all buffers are the same size.
167- let end = 64 - 8 ;
168- let bits = size * 8 ;
169-
170160 for buffer in buffers. iter_mut ( ) {
171161 buffer[ size] = 0x80 ;
172- buffer[ end..] . copy_from_slice ( & bits. to_le_bytes ( ) ) ;
173162 }
174163
175- let mut a0: Simd < u32 , N > = Simd :: splat ( 0x67452301 ) ;
176- let mut b0: Simd < u32 , N > = Simd :: splat ( 0xefcdab89 ) ;
177- let mut c0: Simd < u32 , N > = Simd :: splat ( 0x98badcfe ) ;
178- let mut d0: Simd < u32 , N > = Simd :: splat ( 0x10325476 ) ;
164+ let mut a0 = Simd :: splat ( 0x67452301 ) ;
165+ let mut b0 = Simd :: splat ( 0xefcdab89 ) ;
166+ let mut c0 = Simd :: splat ( 0x98badcfe ) ;
167+ let mut d0 = Simd :: splat ( 0x10325476 ) ;
179168
180169 let mut a = a0;
181170 let mut b = b0;
182171 let mut c = c0;
183172 let mut d = d0;
184173
185- let m0 = message ( buffers, 0 ) ;
174+ let m0 = message ( buffers, 0 , size ) ;
186175 a = round1 ( a, b, c, d, m0, 7 , 0xd76aa478 ) ;
187- let m1 = message ( buffers, 1 ) ;
176+ let m1 = message ( buffers, 4 , size ) ;
188177 d = round1 ( d, a, b, c, m1, 12 , 0xe8c7b756 ) ;
189- let m2 = message ( buffers, 2 ) ;
178+ let m2 = message ( buffers, 8 , size ) ;
190179 c = round1 ( c, d, a, b, m2, 17 , 0x242070db ) ;
191- let m3 = message ( buffers, 3 ) ;
180+ let m3 = message ( buffers, 12 , size ) ;
192181 b = round1 ( b, c, d, a, m3, 22 , 0xc1bdceee ) ;
193- let m4 = message ( buffers, 4 ) ;
182+ let m4 = message ( buffers, 16 , size ) ;
194183 a = round1 ( a, b, c, d, m4, 7 , 0xf57c0faf ) ;
195- let m5 = message ( buffers, 5 ) ;
184+ let m5 = message ( buffers, 20 , size ) ;
196185 d = round1 ( d, a, b, c, m5, 12 , 0x4787c62a ) ;
197- let m6 = message ( buffers, 6 ) ;
186+ let m6 = message ( buffers, 24 , size ) ;
198187 c = round1 ( c, d, a, b, m6, 17 , 0xa8304613 ) ;
199- let m7 = message ( buffers, 7 ) ;
188+ let m7 = message ( buffers, 28 , size ) ;
200189 b = round1 ( b, c, d, a, m7, 22 , 0xfd469501 ) ;
201- let m8 = message ( buffers, 8 ) ;
190+ let m8 = message ( buffers, 32 , size ) ;
202191 a = round1 ( a, b, c, d, m8, 7 , 0x698098d8 ) ;
203- let m9 = message ( buffers, 9 ) ;
192+ let m9 = message ( buffers, 36 , size ) ;
204193 d = round1 ( d, a, b, c, m9, 12 , 0x8b44f7af ) ;
205- let m10 = message ( buffers, 10 ) ;
194+ let m10 = message ( buffers, 40 , size ) ;
206195 c = round1 ( c, d, a, b, m10, 17 , 0xffff5bb1 ) ;
207- let m11 = message ( buffers, 11 ) ;
196+ let m11 = message ( buffers, 44 , size ) ;
208197 b = round1 ( b, c, d, a, m11, 22 , 0x895cd7be ) ;
209- let m12 = message ( buffers, 12 ) ;
198+ let m12 = message ( buffers, 48 , size ) ;
210199 a = round1 ( a, b, c, d, m12, 7 , 0x6b901122 ) ;
211- let m13 = message ( buffers, 13 ) ;
200+ let m13 = message ( buffers, 52 , size ) ;
212201 d = round1 ( d, a, b, c, m13, 12 , 0xfd987193 ) ;
213- let m14 = message ( buffers , 14 ) ;
202+ let m14 = Simd :: splat ( size as u32 * 8 ) ;
214203 c = round1 ( c, d, a, b, m14, 17 , 0xa679438e ) ;
215- let m15 = message ( buffers , 15 ) ;
204+ let m15 = Simd :: splat ( 0 ) ;
216205 b = round1 ( b, c, d, a, m15, 22 , 0x49b40821 ) ;
217206
218207 a = round2 ( a, b, c, d, m1, 5 , 0xf61e2562 ) ;
@@ -271,25 +260,27 @@ pub mod simd {
271260 c0 += c;
272261 d0 += d;
273262
274- (
263+ [
275264 a0. swap_bytes ( ) . to_array ( ) ,
276265 b0. swap_bytes ( ) . to_array ( ) ,
277266 c0. swap_bytes ( ) . to_array ( ) ,
278267 d0. swap_bytes ( ) . to_array ( ) ,
279- )
268+ ]
280269 }
281270
282271 #[ inline]
283- fn message < const N : usize > ( buffers : & mut [ [ u8 ; 64 ] ] , i : usize ) -> Simd < u32 , N >
272+ fn message < const N : usize > ( buffers : & [ [ u8 ; 64 ] ; N ] , i : usize , size : usize ) -> Simd < u32 , N >
284273 where
285274 LaneCount < N > : SupportedLaneCount ,
286275 {
287- let start = 4 * i;
288- let end = start + 4 ;
289- Simd :: from_array ( array:: from_fn ( |lane| {
290- let slice = & buffers[ lane] [ start..end] ;
291- u32:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
292- } ) )
276+ if i > size {
277+ Simd :: splat ( 0 )
278+ } else {
279+ Simd :: from_array ( from_fn ( |lane| {
280+ let slice = & buffers[ lane] [ i..i + 4 ] ;
281+ u32:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
282+ } ) )
283+ }
293284 }
294285
295286 #[ inline]
0 commit comments