XxHashShared
using System.Buffers.Binary;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.IO.Hashing
{
internal static class XxHashShared
{
[StructLayout(LayoutKind.Auto)]
public struct State
{
internal unsafe fixed ulong Accumulators[8];
internal unsafe fixed byte Secret[192];
internal unsafe fixed byte Buffer[256];
internal uint ;
internal ulong ;
internal ulong ;
internal ulong ;
}
public const int = 64;
public const int = 192;
public const int = 136;
public const int = 7;
public const int = 8;
public const int = 11;
public const int = 16;
public const int = 8;
public const int = 240;
public const int = 4;
public const int = 256;
public const ulong = 13712233961653862072;
public const ulong = 2066345149520216444;
public const ulong = 15823274712020931806;
public const ulong = 2262974939099578482;
public const ulong = 8711581037947681227;
public const ulong = 2410270004345854594;
public const ulong = 10242386182634080440;
public const ulong = 5487137525590930912;
public const ulong = 14627906620379768892;
public const ulong = 11758427054878871688;
public const ulong = 5690594596133299313;
public const ulong = 15613098826807580984;
public const ulong = 4554437623014685352;
public const ulong = 2111919702937427193;
public const ulong = 3556072174620004746;
public const ulong = 7238261902898274248;
public const ulong = 9295848262624092985;
public const ulong = 7914194659941938988;
public const ulong = 11835586108195898345;
public const ulong = 16607528436649670564;
public const ulong = 15013455763555273806;
public const ulong = 5046485836271438973;
public const ulong = 10391458616325699444;
public const ulong = 5920048007935066598;
public const ulong = 7336514198459093435;
public const ulong = 5216419214072683403;
public const ulong = 17228863761319568023;
public const ulong = 8573350489219836230;
public const ulong = 13536968629829821247;
public const ulong = 16163852396094277575;
public const ulong = 11400714785074694791;
public const ulong = 14029467366897019727;
public const ulong = 1609587929392839161;
public const ulong = 9650029242287828579;
public const ulong = 2870177450012600261;
public const uint = 2654435761;
public const uint = 2246822519;
public const uint = 3266489917;
public const uint = 668265263;
public const uint = 374761393;
public unsafe static ReadOnlySpan<byte> => new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.2CF2F88BF9B71283059B6DF53E5BCDE20ADBFD9E8D6CE2C1AB106262BB283BED, 192);
public unsafe static void (ref State state, ulong seed)
{
state.Seed = seed;
fixed (byte* ptr = state.Secret) {
if (seed == 0)
DefaultSecret.CopyTo(new Span<byte>(ptr, 192));
else
DeriveSecretFromSeed(ptr, seed);
}
Reset(ref state);
}
public unsafe static void (ref State state)
{
state.BufferedCount = 0;
state.StripesProcessedInCurrentBlock = 0;
state.TotalLength = 0;
fixed (ulong* accumulators = state.Accumulators) {
InitializeAccumulators(accumulators);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong (ulong hash, uint length)
{
hash ^= (System.Numerics.BitOperations.RotateLeft(hash, 49) ^ System.Numerics.BitOperations.RotateLeft(hash, 24));
hash = (ulong)((long)hash * -6939452855193903323);
hash ^= (hash >> 35) + length;
hash = (ulong)((long)hash * -6939452855193903323);
return XorShift(hash, 28);
}
public unsafe static void (ulong* accumulators, byte* source, uint length, byte* secret)
{
int num = (int)((length - 1) / 1024);
Accumulate(accumulators, source, secret, 16, true, num);
int num2 = 1024 * num;
int stripesToProcess = (int)((length - 1 - num2) / 64);
Accumulate(accumulators, source + num2, secret, stripesToProcess, false, 1);
Accumulate512(accumulators, source + length - 64, secret + 121);
}
public unsafe static void (ulong* accumulators, ref ulong stripesSoFar, ulong stripesPerBlock, byte* source, ulong stripes, byte* secret)
{
ulong num = stripesPerBlock - stripesSoFar;
if (num <= stripes) {
ulong num2 = stripes - num;
Accumulate(accumulators, source, secret + (int)stripesSoFar * 8, (int)num, false, 1);
ScrambleAccumulators(accumulators, secret + 128);
Accumulate(accumulators, source + (int)num * 64, secret, (int)num2, false, 1);
stripesSoFar = num2;
} else {
Accumulate(accumulators, source, secret + (int)stripesSoFar * 8, (int)stripes, false, 1);
stripesSoFar += stripes;
}
}
public unsafe static void (ref State state, ReadOnlySpan<byte> source)
{
state.TotalLength += (uint)source.Length;
fixed (byte* ptr = state.Buffer) {
if (source.Length > 256 - state.BufferedCount) {
fixed (byte* ptr2 = state.Secret) {
fixed (ulong* accumulators = state.Accumulators) {
fixed (byte* ptr3 = &MemoryMarshal.GetReference(source)) {
int num = 0;
ReadOnlySpan<byte> readOnlySpan;
if (state.BufferedCount != 0) {
int num2 = (int)(256 - state.BufferedCount);
readOnlySpan = source.Slice(0, num2);
readOnlySpan.CopyTo(new Span<byte>(ptr + state.BufferedCount, num2));
num = num2;
ConsumeStripes(accumulators, ref state.StripesProcessedInCurrentBlock, 16, ptr, 4, ptr2);
state.BufferedCount = 0;
}
if (source.Length - num > 1024) {
ulong num3 = (ulong)(source.Length - num - 1) / 64;
ulong num4 = 16 - state.StripesProcessedInCurrentBlock;
Accumulate(accumulators, ptr3 + num, ptr2 + (int)state.StripesProcessedInCurrentBlock * 8, (int)num4, false, 1);
ScrambleAccumulators(accumulators, ptr2 + 128);
state.StripesProcessedInCurrentBlock = 0;
num += (int)num4 * 64;
for (num3 -= num4; num3 >= 16; num3 -= 16) {
Accumulate(accumulators, ptr3 + num, ptr2, 16, false, 1);
ScrambleAccumulators(accumulators, ptr2 + 128);
num += 1024;
}
Accumulate(accumulators, ptr3 + num, ptr2, (int)num3, false, 1);
num += (int)num3 * 64;
state.StripesProcessedInCurrentBlock = num3;
readOnlySpan = source.Slice(num - 64, 64);
readOnlySpan.CopyTo(new Span<byte>(ptr + 256 - 64, 64));
} else if (source.Length - num > 256) {
do {
ConsumeStripes(accumulators, ref state.StripesProcessedInCurrentBlock, 16, ptr3 + num, 4, ptr2);
num += 256;
} while (source.Length - num > 256);
readOnlySpan = source.Slice(num - 64, 64);
readOnlySpan.CopyTo(new Span<byte>(ptr + 256 - 64, 64));
}
Span<byte> destination = new Span<byte>(ptr, source.Length - num);
readOnlySpan = source.Slice(num);
readOnlySpan.CopyTo(destination);
state.BufferedCount = (uint)destination.Length;
}
}
}
} else {
source.CopyTo(new Span<byte>(ptr + state.BufferedCount, source.Length));
state.BufferedCount += (uint)source.Length;
}
}
}
public unsafe static void (ref State state, ulong* accumulators)
{
fixed (ulong* ptr = state.Accumulators) {
for (int i = 0; i < 8; i++) {
accumulators[i] = ptr[i];
}
}
}
public unsafe static void (ref State state, ulong* accumulators, byte* secret)
{
fixed (byte* ptr = state.Buffer) {
byte* source;
if (state.BufferedCount >= 64) {
uint num = (state.BufferedCount - 1) / 64;
ulong stripesSoFar = state.StripesProcessedInCurrentBlock;
ConsumeStripes(accumulators, ref stripesSoFar, 16, ptr, num, secret);
source = ptr + state.BufferedCount - 64;
} else {
byte* ptr2 = stackalloc byte[64];
int num2 = (int)(64 - state.BufferedCount);
ReadOnlySpan<byte> readOnlySpan = new ReadOnlySpan<byte>(ptr + 256 - num2, num2);
readOnlySpan.CopyTo(new Span<byte>(ptr2, 64));
readOnlySpan = new ReadOnlySpan<byte>(ptr, (int)state.BufferedCount);
readOnlySpan.CopyTo(new Span<byte>(ptr2 + num2, (int)state.BufferedCount));
source = ptr2;
}
Accumulate512(accumulators, source, secret + 121);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void (ulong* accumulators)
{
*accumulators = 3266489917;
accumulators[1] = 11400714785074694791;
accumulators[2] = 14029467366897019727;
accumulators[3] = 1609587929392839161;
accumulators[4] = 9650029242287828579;
accumulators[5] = 2246822519;
accumulators[6] = 2870177450012600261;
accumulators[7] = 2654435761;
}
public unsafe static ulong (ulong* accumulators, byte* secret, ulong start)
{
return Avalanche(start + Multiply64To128ThenFold(*accumulators ^ ReadUInt64LE(secret), accumulators[1] ^ ReadUInt64LE(secret + 8)) + Multiply64To128ThenFold(accumulators[2] ^ ReadUInt64LE(secret + 16), accumulators[3] ^ ReadUInt64LE(secret + 24)) + Multiply64To128ThenFold(accumulators[4] ^ ReadUInt64LE(secret + 32), accumulators[5] ^ ReadUInt64LE(secret + 40)) + Multiply64To128ThenFold(accumulators[6] ^ ReadUInt64LE(secret + 48), accumulators[7] ^ ReadUInt64LE(secret + 56)));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static ulong (byte* source, ulong secretLow, ulong secretHigh, ulong seed)
{
return Multiply64To128ThenFold(ReadUInt64LE(source) ^ (secretLow + seed), ReadUInt64LE(source + 8) ^ (secretHigh - seed));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong (uint v1, uint v2)
{
return (ulong)((long)v1 * (long)v2);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong (ulong hash)
{
hash = XorShift(hash, 37);
hash *= 1609587791953885689;
hash = XorShift(hash, 32);
return hash;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong (ulong left, ulong right, out ulong lower)
{
ulong num = Multiply32To64((uint)left, (uint)right);
ulong num2 = Multiply32To64((uint)(left >> 32), (uint)right);
ulong num3 = Multiply32To64((uint)left, (uint)(right >> 32));
ulong num4 = Multiply32To64((uint)(left >> 32), (uint)(right >> 32));
ulong num5 = (num >> 32) + (num2 & uint.MaxValue) + num3;
ulong result = (num2 >> 32) + (num5 >> 32) + num4;
lower = ((num5 << 32) | (num & uint.MaxValue));
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong (ulong left, ulong right)
{
ulong lower;
ulong num = Multiply64To128(left, right, out lower);
return lower ^ num;
}
public unsafe static void (byte* destinationSecret, ulong seed)
{
fixed (byte* ptr = &MemoryMarshal.GetReference(DefaultSecret)) {
for (int i = 0; i < 192; i += 16) {
WriteUInt64LE(destinationSecret + i, ReadUInt64LE(ptr + i) + seed);
WriteUInt64LE(destinationSecret + i + 8, ReadUInt64LE(ptr + i + 8) - seed);
}
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private unsafe static void (ulong* accumulators, byte* source, byte* secret, int stripesToProcess, bool scramble = false, int blockCount = 1)
{
byte* secret2 = secret + 128;
for (int i = 0; i < blockCount; i++) {
for (int j = 0; j < stripesToProcess; j++) {
Accumulate512Inlined(accumulators, source, secret + j * 8);
source += 64;
}
if (scramble)
ScrambleAccumulators(accumulators, secret2);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public unsafe static void (ulong* accumulators, byte* source, byte* secret)
{
Accumulate512Inlined(accumulators, source, secret);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe static void (ulong* accumulators, byte* source, byte* secret)
{
for (int i = 0; i < 8; i++) {
ulong num = ReadUInt64LE(source + 8 * i);
ulong num2 = num ^ ReadUInt64LE(secret + i * 8);
accumulators[i ^ 1] += num;
accumulators[i] += Multiply32To64((uint)num2, (uint)(num2 >> 32));
}
}
private unsafe static void (ulong* accumulators, byte* secret)
{
for (int i = 0; i < 8; i++) {
ulong num = XorShift(*accumulators, 47) ^ ReadUInt64LE(secret);
*accumulators = num * 2654435761;
accumulators++;
secret += 8;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong (ulong value, int shift)
{
return value ^ (value >> shift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static uint (byte* data)
{
if (!BitConverter.IsLittleEndian)
return BinaryPrimitives.ReverseEndianness(Unsafe.ReadUnaligned<uint>(data));
return Unsafe.ReadUnaligned<uint>(data);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static ulong (byte* data)
{
if (!BitConverter.IsLittleEndian)
return BinaryPrimitives.ReverseEndianness(Unsafe.ReadUnaligned<ulong>(data));
return Unsafe.ReadUnaligned<ulong>(data);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe static void (byte* data, ulong value)
{
if (!BitConverter.IsLittleEndian)
value = BinaryPrimitives.ReverseEndianness(value);
Unsafe.WriteUnaligned(data, value);
}
}
}