5
5
using System . Buffers ;
6
6
using System . Buffers . Binary ;
7
7
using System . Runtime . CompilerServices ;
8
+ using System . Runtime . InteropServices ;
8
9
using System . Text ;
9
10
using System . Threading ;
10
11
@@ -149,17 +150,32 @@ private static void ComputeHash(ReadOnlySpan<byte> data,
149
150
out uint hash1 ,
150
151
out uint hash2 )
151
152
{
152
- uint a , b , c ;
153
+ uint len = ( uint ) data . Length ;
154
+ uint a = 0xDEADBEEF + len + seed1 ;
155
+ uint b = a ;
156
+ uint c = a + seed2 ;
153
157
154
- a = b = c = ( uint ) ( 0xdeadbeef + data . Length + seed1 ) ;
155
- c += seed2 ;
158
+ int tripletCount = data . Length > 12 ? ( data . Length - 1 ) / 12 : 0 ;
156
159
157
- int index = 0 , size = data . Length ;
158
- while ( size > 12 )
160
+ int regionBytes = tripletCount * 12 ; // must be divisible by 4
161
+ ReadOnlySpan < byte > region = data . Slice ( 0 , regionBytes ) ;
162
+ ReadOnlySpan < uint > words = MemoryMarshal . Cast < byte , uint > ( region ) ;
163
+
164
+ int i = 0 ;
165
+ for ( ; i < tripletCount ; i ++ )
159
166
{
160
- a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index ) ) ;
161
- b += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index + 4 ) ) ;
162
- c += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index + 8 ) ) ;
167
+ int idx = i * 3 ;
168
+ uint w0 = BitConverter . IsLittleEndian ? words [ idx ] : BinaryPrimitives . ReverseEndianness ( words [ idx ] ) ;
169
+ uint w1 = BitConverter . IsLittleEndian
170
+ ? words [ idx + 1 ]
171
+ : BinaryPrimitives . ReverseEndianness ( words [ idx + 1 ] ) ;
172
+ uint w2 = BitConverter . IsLittleEndian
173
+ ? words [ idx + 2 ]
174
+ : BinaryPrimitives . ReverseEndianness ( words [ idx + 2 ] ) ;
175
+
176
+ a += w0 ;
177
+ b += w1 ;
178
+ c += w2 ;
163
179
164
180
a -= c ;
165
181
a ^= ( c << 4 ) | ( c >> 28 ) ;
@@ -184,51 +200,50 @@ private static void ComputeHash(ReadOnlySpan<byte> data,
184
200
c -= b ;
185
201
c ^= ( b << 4 ) | ( b >> 28 ) ;
186
202
b += a ;
187
-
188
- index += 12 ;
189
- size -= 12 ;
190
203
}
191
204
205
+ int byteIndex = regionBytes ;
206
+ int size = data . Length - byteIndex ;
192
207
switch ( size )
193
208
{
194
209
case 12 :
195
- a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index ) ) ;
196
- b += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index + 4 ) ) ;
197
- c += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index + 8 ) ) ;
210
+ a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex ) ) ;
211
+ b += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex + 4 ) ) ;
212
+ c += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex + 8 ) ) ;
198
213
break ;
199
214
case 11 :
200
- c += ( ( uint ) data [ index + 10 ] ) << 16 ;
215
+ c += ( uint ) data [ byteIndex + 10 ] << 16 ;
201
216
goto case 10 ;
202
217
case 10 :
203
- c += ( ( uint ) data [ index + 9 ] ) << 8 ;
218
+ c += ( uint ) data [ byteIndex + 9 ] << 8 ;
204
219
goto case 9 ;
205
220
case 9 :
206
- c += ( uint ) data [ index + 8 ] ;
221
+ c += data [ byteIndex + 8 ] ;
207
222
goto case 8 ;
208
223
case 8 :
209
- b += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index + 4 ) ) ;
210
- a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index ) ) ;
224
+ b += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex + 4 ) ) ;
225
+ a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex ) ) ;
211
226
break ;
212
227
case 7 :
213
- b += ( ( uint ) data [ index + 6 ] ) << 16 ;
228
+ b += ( uint ) data [ byteIndex + 6 ] << 16 ;
214
229
goto case 6 ;
215
230
case 6 :
216
- b += ( ( uint ) data [ index + 5 ] ) << 8 ;
231
+ b += ( uint ) data [ byteIndex + 5 ] << 8 ;
217
232
goto case 5 ;
218
233
case 5 :
219
- b += ( uint ) data [ index + 4 ] ;
234
+ b += data [ byteIndex + 4 ] ;
220
235
goto case 4 ;
221
236
case 4 :
222
- a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( index ) ) ;
237
+ a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex ) ) ;
223
238
break ;
224
239
case 3 :
225
- a += ( ( uint ) data [ index + 2 ] ) << 16 ;
240
+ a += ( uint ) data [ byteIndex + 2 ] << 16 ;
226
241
goto case 2 ;
227
242
case 2 :
228
- a += ( ( uint ) data [ index + 1 ] ) << 8 ;
243
+ a += ( uint ) data [ byteIndex + 1 ] << 8 ;
229
244
goto case 1 ;
230
245
case 1 :
231
- a += ( uint ) data [ index ] ;
246
+ a += data [ byteIndex ] ;
232
247
break ;
233
248
case 0 :
234
249
hash1 = c ;
0 commit comments