@@ -211,6 +211,19 @@ private static void StoreTransposed4(Span<Vector128<uint>> chainingValues, Span<
211211 second3 . StoreUnsafe ( ref outputWord , 28 ) ;
212212 }
213213
214+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
215+ private static void StoreTransposed4 ( ref Vector128 < uint > chainingValue , Span < uint > output , int count )
216+ {
217+ ref var outputWord = ref MemoryMarshal . GetReference ( output ) ;
218+ Transpose4 ( ref chainingValue ) ;
219+ Transpose4 ( ref Unsafe . Add ( ref chainingValue , 4 ) ) ;
220+ for ( nuint lane = 0 ; lane < ( nuint ) count ; lane ++ )
221+ {
222+ Unsafe . Add ( ref chainingValue , lane ) . StoreUnsafe ( ref outputWord , lane * 8 ) ;
223+ Unsafe . Add ( ref chainingValue , lane + 4 ) . StoreUnsafe ( ref outputWord , ( lane * 8 ) + 4 ) ;
224+ }
225+ }
226+
214227 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
215228 private static void Transpose4 (
216229 ref Vector128 < uint > row0 ,
@@ -228,6 +241,20 @@ private static void Transpose4(
228241 row3 = AdvSimd . Arm64 . ZipHigh ( row01High . AsUInt64 ( ) , row23High . AsUInt64 ( ) ) . AsUInt32 ( ) ;
229242 }
230243
244+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
245+ private static void Transpose4 ( ref Vector128 < uint > first )
246+ {
247+ var row0 = first ;
248+ var row1 = Unsafe . Add ( ref first , 1 ) ;
249+ var row2 = Unsafe . Add ( ref first , 2 ) ;
250+ var row3 = Unsafe . Add ( ref first , 3 ) ;
251+ Transpose4 ( ref row0 , ref row1 , ref row2 , ref row3 ) ;
252+ first = row0 ;
253+ Unsafe . Add ( ref first , 1 ) = row1;
254+ Unsafe . Add ( ref first , 2 ) = row2;
255+ Unsafe . Add ( ref first , 3 ) = row3;
256+ }
257+
231258 [ SkipLocalsInit ]
232259 private static int Hash4ChunksArm64 (
233260 ReadOnlySpan < byte > input ,
@@ -279,6 +306,55 @@ private static int Hash4ChunksArm64(
279306 return Degree ;
280307 }
281308
309+ [ SkipLocalsInit ]
310+ private static bool TryCompress4ParentsArm64 (
311+ Span < uint > childChainingValues ,
312+ int parentCount ,
313+ ReadOnlySpan < uint > keyWords ,
314+ uint flags )
315+ {
316+ if ( ! AdvSimd . Arm64 . IsSupported || parentCount is < 1 or > 4 )
317+ {
318+ return false ;
319+ }
320+
321+ Span < Vector128 < uint > > chainingValues = stackalloc Vector128 < uint > [ 8 ] ;
322+ Span < Vector128 < uint > > message = stackalloc Vector128 < uint > [ 16 ] ;
323+ ref var chainingValue = ref MemoryMarshal . GetReference ( chainingValues ) ;
324+ ref var messageWord = ref MemoryMarshal . GetReference ( message ) ;
325+ ref var childWord = ref MemoryMarshal . GetReference ( childChainingValues ) ;
326+ for ( var index = 0 ; index < 8 ; index ++ )
327+ {
328+ Unsafe . Add ( ref chainingValue , index ) = Vector128. Create ( keyWords [ index ] ) ;
329+ }
330+
331+ for ( nuint parent = ( nuint ) parentCount ; parent < 4 ; parent ++ )
332+ {
333+ Unsafe . Add ( ref messageWord , parent ) = Vector128 < uint > . Zero ;
334+ Unsafe . Add ( ref messageWord , parent + 4 ) = Vector128 < uint > . Zero ;
335+ Unsafe . Add ( ref messageWord , parent + 8 ) = Vector128 < uint > . Zero ;
336+ Unsafe . Add ( ref messageWord , parent + 12 ) = Vector128 < uint > . Zero ;
337+ }
338+
339+ for ( nuint parent = 0 ; parent < ( nuint ) parentCount ; parent ++ )
340+ {
341+ var childOffset = parent * 16 ;
342+ Unsafe . Add ( ref messageWord , parent ) = Vector128. LoadUnsafe ( ref childWord , childOffset ) ;
343+ Unsafe . Add ( ref messageWord , parent + 4 ) = Vector128. LoadUnsafe ( ref childWord , childOffset + 4 ) ;
344+ Unsafe . Add ( ref messageWord , parent + 8 ) = Vector128. LoadUnsafe ( ref childWord , childOffset + 8 ) ;
345+ Unsafe . Add ( ref messageWord , parent + 12 ) = Vector128. LoadUnsafe ( ref childWord , childOffset + 12 ) ;
346+ }
347+
348+ Transpose4 ( ref messageWord ) ;
349+ Transpose4 ( ref Unsafe . Add ( ref messageWord , 4 ) ) ;
350+ Transpose4 ( ref Unsafe . Add ( ref messageWord , 8 ) ) ;
351+ Transpose4 ( ref Unsafe . Add ( ref messageWord , 12 ) ) ;
352+ var zero = Vector128 < uint > . Zero ;
353+ Compress4Arm64 ( ref chainingValue , ref messageWord , in zero , in zero , flags | Parent ) ;
354+ StoreTransposed4 ( ref chainingValue , childChainingValues , parentCount ) ;
355+ return true ;
356+ }
357+
282358 [ SkipLocalsInit ]
283359 private static void Compress4Arm64 (
284360 ref Vector128 < uint > chainingValue ,
0 commit comments