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

Code before:
        {
            if (destination.Length < Size)
            {
                ThrowDestinationTooShort();
            }

            uint hash = HashToUInt32(source);
            BinaryPrimitives.WriteUInt32LittleEndian(destination, hash);
            return Size;
        }

        /// <summary>
        /// Computes the Adler-32 hash of the provided data.
        /// </summary>
        /// <param name="source">The data to hash.</param>
        /// <returns>
        /// The computed Adler-32 hash.
        /// </returns>
        [CLSCompliant(false)]
        public static uint HashToUInt32(ReadOnlySpan<byte> source)
            => Update(InitialState, source);

        private static uint Update(uint adler, ReadOnlySpan<byte> buf)
        {
            uint Base = 65521; // largest prime smaller than 65536
            int NMax = 5552; // NMax is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
            if (buf.IsEmpty)
            {
                return adler;
            }

            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;
            while (buf.Length > 0)
            {
                int k = buf.Length < NMax ? buf.Length : NMax;
                foreach (byte b in buf.Slice(0, k))
                {
                    s1 += b;
                    s2 += s1;
                }
                s1 %= Base;
                s2 %= Base;
                buf = buf.Slice(k);
            }

            return (s2 << 16) | s1;
        }
    }
}


Review comment (performance):
We should keep the `const` qualifier.

```suggestion
            const uint Base = 65521; // largest prime smaller than 65536
            const int NMax = 5552; // NMax is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
```

Code after:
            if (destination.Length < Size)
            {
                ThrowDestinationTooShort();
            }

            uint hash = HashToUInt32(source);
            BinaryPrimitives.WriteUInt32BigEndian(destination, hash);
            return Size;
        }

        /// <summary>
        /// Computes the Adler-32 hash of the provided data.
        /// </summary>
        /// <param name="source">The data to hash.</param>
        /// <returns>
        /// The computed Adler-32 hash.
        /// </returns>
        [CLSCompliant(false)]
        public static uint HashToUInt32(ReadOnlySpan<byte> source)
            => Update(InitialState, source);

        private static uint Update(uint adler, ReadOnlySpan<byte> buf)
        {
            if (buf.IsEmpty)
            {
                return adler;
            }

            return UpdateScalar(adler, buf);
        }

        private static uint UpdateScalar(uint adler, ReadOnlySpan<byte> buf)
        {
            const uint Base = 65521; // largest prime smaller than 65536
            const int NMax = 5552; // NMax is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1

            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;
            while (buf.Length > 0)
            {
                int k = buf.Length < NMax ? buf.Length : NMax;
                foreach (byte b in buf.Slice(0, k))
                {
                    s1 += b;
                    s2 += s1;
                }
                s1 %= Base;
                s2 %= Base;
                buf = buf.Slice(k);
            }