Repository: dotnet/runtime
File: src/libraries/System.IO.Hashing/src/System/IO/Hashing/Adler32.cs (C#)

Code before:
        private static uint UpdateArm128(uint adler, ReadOnlySpan<byte> source)
        {
            Debug.Assert(source.Length >= Vector128<byte>.Count * 2);

            const int BlockSize = 32; // two Vector128<byte> loads

            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;

            ref byte sourceRef = ref MemoryMarshal.GetReference(source);
            int length = source.Length;

            do
            {
                int n = Math.Min(length, NMax);
                int blocks = n / BlockSize;
                n = blocks * BlockSize;
                length -= n;

                Vector128<uint> vs1 = Vector128<uint>.Zero;
                Vector128<uint> vps = Vector128.CreateScalar(s1 * (uint)blocks);

                Vector128<ushort> vColumnSum1 = Vector128<ushort>.Zero;
                Vector128<ushort> vColumnSum2 = Vector128<ushort>.Zero;
                Vector128<ushort> vColumnSum3 = Vector128<ushort>.Zero;
                Vector128<ushort> vColumnSum4 = Vector128<ushort>.Zero;

                do
                {
                    Vector128<byte> bytes1 = Vector128.LoadUnsafe(ref sourceRef);
                    Vector128<byte> bytes2 = Vector128.LoadUnsafe(ref sourceRef, 16);
                    sourceRef = ref Unsafe.Add(ref sourceRef, BlockSize);

                    vps += vs1;

                    vs1 = AdvSimd.AddPairwiseWideningAndAdd(
                        vs1,
                        AdvSimd.AddPairwiseWideningAndAdd(
                            AdvSimd.AddPairwiseWidening(bytes1),
                            bytes2));

                    vColumnSum1 = AdvSimd.AddWideningLower(vColumnSum1, bytes1.GetLower());
                    vColumnSum2 = AdvSimd.AddWideningLower(vColumnSum2, bytes1.GetUpper());
                    vColumnSum3 = AdvSimd.AddWideningLower(vColumnSum3, bytes2.GetLower());
                    vColumnSum4 = AdvSimd.AddWideningLower(vColumnSum4, bytes2.GetUpper());
                }
                while (--blocks > 0);

                Vector128<uint> vs2 = vps << 5;
                vs2 = AdvSimd.MultiplyWideningLowerAndAdd(vs2, vColumnSum1.GetLower(), Vector64.Create((ushort)32, 31, 30, 29));
                vs2 = AdvSimd.MultiplyWideningLowerAndAdd(vs2, vColumnSum1.GetUpper(), Vector64.Create((ushort)28, 27, 26, 25));

Review comment (suggestion):
I think all of this could be put in ``Adler32.Vectorized.cs`` as the csproj can separate the .NET specific stuff from say the .NET Standard target(s).

Code after:
            if (length >= Vector256<byte>.Count)
            {
                return UpdateVector256((s2 << 16) | s1, MemoryMarshal.CreateReadOnlySpan(ref sourceRef, length));
            }

            if (length > 0)
            {
                UpdateScalarTail(ref sourceRef, length, ref s1, ref s2);
            }

            return (s2 << 16) | s1;
        }

        private static void UpdateScalarTail(ref byte sourceRef, int length, ref uint s1, ref uint s2)
        {
            Debug.Assert(length is > 0 and < NMax);

            foreach (byte b in MemoryMarshal.CreateReadOnlySpan(ref sourceRef, length))
            {
                s1 += b;
                s2 += s1;
            }

            s1 %= ModBase;
            s2 %= ModBase;
        }
#endif
    }
}