1
- use super :: {
2
- mask, Array , ArraySize , False , Gr , Hs1HashKey , Hs1Params , PhantomData , Quot , True , B16 , U4 ,
3
- } ;
1
+ use super :: { mask, Array , False , Gr , Hs1HashKey , Hs1Params , PhantomData , Quot , True , B16 , U4 } ;
4
2
use aead:: array:: typenum:: Unsigned ;
5
3
use core:: mem;
6
4
5
+ #[ cfg( target_feature = "sse2" ) ]
6
+ mod sse2;
7
+
7
8
#[ derive( Clone ) ]
8
9
pub struct Hasher < P : Hs1Params > {
9
10
k : Hs1HashKey < P > ,
@@ -53,41 +54,52 @@ impl<P: Hs1Params> Hasher<P> {
53
54
pub fn new ( k : & Hs1HashKey < P > ) -> Self {
54
55
Self {
55
56
k : k. clone ( ) ,
56
- h : array_from_iter ( core :: iter :: repeat ( 1 ) ) ,
57
- block : Array :: default ( ) ,
57
+ h : Array :: from_fn ( |_| 1 ) ,
58
+ block : Default :: default ( ) ,
58
59
bytes : 0 ,
59
60
_marker : PhantomData ,
60
61
}
61
62
}
62
63
64
+ #[ inline( always) ]
63
65
fn update_block ( & mut self ) -> & mut Self {
64
66
assert ! ( usize :: from( self . bytes) <= self . block_u8( ) . len( ) ) ;
65
67
68
+ #[ cfg( target_feature = "sse2" ) ]
69
+ if true {
70
+ // SAFETY: sse2 is supported
71
+ unsafe {
72
+ return self . update_block_sse2 ( ) ;
73
+ }
74
+ }
75
+
66
76
#[ inline( always) ]
67
- fn nh_step ( & [ ax, bx, cx, dx] : & [ u32 ; 4 ] , & [ ay, by, cy, dy] : & [ u32 ; 4 ] ) -> u64 {
68
- let d = u64:: from ( dx. wrapping_add ( dy) ) ;
69
- let c = u64:: from ( cx. wrapping_add ( cy) ) ;
70
- let b = u64:: from ( bx. wrapping_add ( by) ) ;
77
+ fn nh_step ( & [ ax, bx, cx, dx] : & [ u32 ; 4 ] , & [ ay, by, cy, dy] : & [ u32 ; 4 ] ) -> [ u64 ; 2 ] {
71
78
let a = u64:: from ( ax. wrapping_add ( ay) ) ;
72
- ( a * c) . wrapping_add ( b * d)
79
+ let b = u64:: from ( bx. wrapping_add ( by) ) ;
80
+ let c = u64:: from ( cx. wrapping_add ( cy) ) ;
81
+ let d = u64:: from ( dx. wrapping_add ( dy) ) ;
82
+ [ a * c, b * d]
73
83
}
74
84
75
85
let m_ints = & self . block ;
76
86
77
87
let block16_count = usize:: from ( ( ( self . bytes + 15 ) / 16 ) . max ( 1 ) ) ;
78
88
79
- let mut nh = Array :: < u64 , P :: T > :: default ( ) ;
89
+ let mut nh = Array :: < [ u64 ; 2 ] , P :: T > :: default ( ) ;
80
90
for ( i0, m_ints_i) in m_ints. chunks_exact ( 4 ) . enumerate ( ) . take ( block16_count) {
81
- for ( nh_i , k_n_i_i) in nh. iter_mut ( ) . zip ( self . k . nh . chunks_exact ( 4 ) . skip ( i0) ) {
91
+ for ( [ nh_i0 , nh_i1 ] , k_n_i_i) in nh. iter_mut ( ) . zip ( self . k . nh . chunks_exact ( 4 ) . skip ( i0) ) {
82
92
let k_n_i_i = k_n_i_i. try_into ( ) . expect ( "exactly 4 elements" ) ;
83
93
let m_ints_i = m_ints_i. try_into ( ) . expect ( "exactly 4 elements" ) ;
84
- let s = nh_step ( k_n_i_i, m_ints_i) ;
85
- * nh_i = nh_i. wrapping_add ( s) ;
94
+ let [ s0, s1] = nh_step ( k_n_i_i, m_ints_i) ;
95
+ * nh_i0 = nh_i0. wrapping_add ( s0) ;
96
+ * nh_i1 = nh_i1. wrapping_add ( s1) ;
86
97
}
87
98
}
88
99
89
100
nh. iter ( )
90
- . map ( |nh_i| ( nh_i + ( u64:: from ( self . bytes ) & mask ( 4 ) ) ) & mask ( 60 ) )
101
+ . map ( |& [ ac, bd] | ac. wrapping_add ( bd) )
102
+ . map ( |nh_i| ( nh_i. wrapping_add ( u64:: from ( self . bytes ) & mask ( 4 ) ) ) & mask ( 60 ) )
91
103
. zip ( self . k . poly . iter ( ) )
92
104
. zip ( self . h . iter_mut ( ) )
93
105
. for_each ( |( ( a_i, & k_p_i) , h_i) | * h_i = poly_step ( * h_i, a_i, k_p_i) ) ;
@@ -97,6 +109,7 @@ impl<P: Hs1Params> Hasher<P> {
97
109
self
98
110
}
99
111
112
+ #[ inline( always) ]
100
113
pub fn update < ' a > ( & ' a mut self , bytes : & [ u8 ] ) -> & ' a mut Self {
101
114
assert ! ( usize :: from( self . bytes) < self . block_u8( ) . len( ) ) ;
102
115
let start = usize:: from ( self . bytes ) ;
@@ -123,6 +136,7 @@ impl<P: Hs1Params> Hasher<P> {
123
136
self
124
137
}
125
138
139
+ #[ inline( always) ]
126
140
pub ( crate ) fn pad_to ( & mut self , bits : u8 ) -> & mut Self {
127
141
debug_assert ! ( 1 << bits <= B16 :: <P >:: to_u8( ) ) ;
128
142
let m = mask ( bits) as u8 ;
@@ -131,6 +145,7 @@ impl<P: Hs1Params> Hasher<P> {
131
145
}
132
146
133
147
// TODO &mut self helps avoid needing to clone(), but might be unintuitive
148
+ #[ inline( always) ]
134
149
pub fn finalize ( & mut self ) -> Array < Output < P > , P :: T > {
135
150
// TODO we need to handle empty data properly
136
151
// However, see the note in crate::test::test_vectors::hash_me_empty
@@ -146,6 +161,7 @@ impl<P: Hs1Params> Hasher<P> {
146
161
out
147
162
}
148
163
164
+ #[ inline( always) ]
149
165
fn block_u8 ( & mut self ) -> & mut Array < u8 , B16 < P > > {
150
166
const {
151
167
assert ! (
@@ -177,18 +193,6 @@ const fn poly_finalize(a: u64) -> u64 {
177
193
a & c
178
194
}
179
195
180
- #[ inline( always) ]
181
- fn array_from_iter < I , L > ( it : I ) -> Array < I :: Item , L >
182
- where
183
- I : IntoIterator ,
184
- L : ArraySize ,
185
- I :: Item : Default ,
186
- {
187
- let mut v = Array :: < I :: Item , L > :: default ( ) ;
188
- v. iter_mut ( ) . zip ( it) . for_each ( |( w, r) | * w = r) ;
189
- v
190
- }
191
-
192
196
#[ cfg( test) ]
193
197
mod test {
194
198
#[ test]
0 commit comments