@@ -155,23 +155,22 @@ private static void ComputeHash(ReadOnlySpan<byte> data,
155
155
uint b = a ;
156
156
uint c = a + seed2 ;
157
157
158
- int tripletCount = data . Length > 12 ? ( data . Length - 1 ) / 12 : 0 ;
158
+ int chunks = data . Length > 12 ? ( data . Length - 1 ) / 12 : 0 ;
159
159
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 ++ )
160
+ ref byte ptr = ref MemoryMarshal . GetReference ( data ) ;
161
+ for ( int i = 0 ; i < chunks ; i ++ )
166
162
{
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 ] ) ;
163
+ uint w0 = Unsafe . ReadUnaligned < uint > ( ref ptr ) ;
164
+ uint w1 = Unsafe . ReadUnaligned < uint > ( ref Unsafe . Add ( ref ptr , 4 ) ) ;
165
+ uint w2 = Unsafe . ReadUnaligned < uint > ( ref Unsafe . Add ( ref ptr , 8 ) ) ;
166
+ ptr = ref Unsafe . Add ( ref ptr , 12 ) ;
167
+
168
+ if ( ! BitConverter . IsLittleEndian )
169
+ {
170
+ w0 = BinaryPrimitives . ReverseEndianness ( w0 ) ;
171
+ w1 = BinaryPrimitives . ReverseEndianness ( w1 ) ;
172
+ w2 = BinaryPrimitives . ReverseEndianness ( w2 ) ;
173
+ }
175
174
176
175
a += w0 ;
177
176
b += w1 ;
@@ -202,48 +201,49 @@ private static void ComputeHash(ReadOnlySpan<byte> data,
202
201
b += a ;
203
202
}
204
203
205
- int byteIndex = regionBytes ;
206
- int size = data . Length - byteIndex ;
207
- switch ( size )
204
+ int consumed = chunks * 12 ;
205
+ ref byte tail = ref Unsafe . Add ( ref MemoryMarshal . GetReference ( data ) , consumed ) ;
206
+ int left = data . Length - consumed ;
207
+ switch ( left )
208
208
{
209
209
case 12 :
210
- a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex ) ) ;
211
- b += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex + 4 ) ) ;
212
- c += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex + 8 ) ) ;
210
+ a += BitConverter . IsLittleEndian ? Unsafe . ReadUnaligned < uint > ( ref tail ) : BinaryPrimitives . ReverseEndianness ( Unsafe . ReadUnaligned < uint > ( ref tail ) ) ;
211
+ b += BitConverter . IsLittleEndian ? Unsafe . ReadUnaligned < uint > ( ref Unsafe . Add ( ref tail , 4 ) ) : BinaryPrimitives . ReverseEndianness ( Unsafe . ReadUnaligned < uint > ( ref Unsafe . Add ( ref tail , 4 ) ) ) ;
212
+ c += BitConverter . IsLittleEndian ? Unsafe . ReadUnaligned < uint > ( ref Unsafe . Add ( ref tail , 8 ) ) : BinaryPrimitives . ReverseEndianness ( Unsafe . ReadUnaligned < uint > ( ref Unsafe . Add ( ref tail , 8 ) ) ) ;
213
213
break ;
214
214
case 11 :
215
- c += ( uint ) data [ byteIndex + 10 ] << 16 ;
215
+ c += ( uint ) Unsafe . Add ( ref tail , 10 ) << 16 ;
216
216
goto case 10 ;
217
217
case 10 :
218
- c += ( uint ) data [ byteIndex + 9 ] << 8 ;
218
+ c += ( uint ) Unsafe . Add ( ref tail , 9 ) << 8 ;
219
219
goto case 9 ;
220
220
case 9 :
221
- c += data [ byteIndex + 8 ] ;
221
+ c += Unsafe . Add ( ref tail , 8 ) ;
222
222
goto case 8 ;
223
223
case 8 :
224
- b += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex + 4 ) ) ;
225
- a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex ) ) ;
224
+ b += BitConverter . IsLittleEndian ? Unsafe . ReadUnaligned < uint > ( ref Unsafe . Add ( ref tail , 4 ) ) : BinaryPrimitives . ReverseEndianness ( Unsafe . ReadUnaligned < uint > ( ref Unsafe . Add ( ref tail , 4 ) ) ) ;
225
+ a += BitConverter . IsLittleEndian ? Unsafe . ReadUnaligned < uint > ( ref tail ) : BinaryPrimitives . ReverseEndianness ( Unsafe . ReadUnaligned < uint > ( ref tail ) ) ;
226
226
break ;
227
227
case 7 :
228
- b += ( uint ) data [ byteIndex + 6 ] << 16 ;
228
+ b += ( uint ) Unsafe . Add ( ref tail , 6 ) << 16 ;
229
229
goto case 6 ;
230
230
case 6 :
231
- b += ( uint ) data [ byteIndex + 5 ] << 8 ;
231
+ b += ( uint ) Unsafe . Add ( ref tail , 5 ) << 8 ;
232
232
goto case 5 ;
233
233
case 5 :
234
- b += data [ byteIndex + 4 ] ;
234
+ b += Unsafe . Add ( ref tail , 4 ) ;
235
235
goto case 4 ;
236
236
case 4 :
237
- a += BinaryPrimitives . ReadUInt32LittleEndian ( data . Slice ( byteIndex ) ) ;
237
+ a += BitConverter . IsLittleEndian ? Unsafe . ReadUnaligned < uint > ( ref tail ) : BinaryPrimitives . ReverseEndianness ( Unsafe . ReadUnaligned < uint > ( ref tail ) ) ;
238
238
break ;
239
239
case 3 :
240
- a += ( uint ) data [ byteIndex + 2 ] << 16 ;
240
+ a += ( uint ) Unsafe . Add ( ref tail , 2 ) << 16 ;
241
241
goto case 2 ;
242
242
case 2 :
243
- a += ( uint ) data [ byteIndex + 1 ] << 8 ;
243
+ a += ( uint ) Unsafe . Add ( ref tail , 1 ) << 8 ;
244
244
goto case 1 ;
245
245
case 1 :
246
- a += data [ byteIndex ] ;
246
+ a += Unsafe . Add ( ref tail , 0 ) ;
247
247
break ;
248
248
case 0 :
249
249
hash1 = c ;
0 commit comments