private static ulong WyHashCore(byte[] array, int ibStart, int cbSize, ulong seed) { // We work a lot with 64-bit integers - reading ulongs from the source array using a cast span gives a big performance boost over BitConverter.ToUInt64 var span64 = MemoryMarshal.Cast <byte, ulong>(array); var len = cbSize - ibStart; var p = 0; for (int i = ibStart; i + 32 <= len; i += 32, p += 32) { seed = SafeWyCore.Mum(seed ^ SafeWyCore.Prime0, SafeWyCore.Mum(SafeWyCore.Read64(span64, p) ^ SafeWyCore.Prime1, SafeWyCore.Read64(span64, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(SafeWyCore.Read64(span64, p + 16) ^ SafeWyCore.Prime3, SafeWyCore.Read64(span64, p + 24) ^ SafeWyCore.Prime4)); } seed ^= SafeWyCore.Prime0; switch (len & 31) { case 1: seed = SafeWyCore.Mum(seed, SafeWyCore.Read8(array, p) ^ SafeWyCore.Prime1); break; case 2: seed = SafeWyCore.Mum(seed, SafeWyCore.Read16(array, p) ^ SafeWyCore.Prime1); break; case 3: seed = SafeWyCore.Mum(seed, ((SafeWyCore.Read16(array, p) << 8) | SafeWyCore.Read8(array, p + 2)) ^ SafeWyCore.Prime1); break; case 4: seed = SafeWyCore.Mum(seed, SafeWyCore.Read32(array, p) ^ SafeWyCore.Prime1); break; case 5: seed = SafeWyCore.Mum(seed, ((SafeWyCore.Read32(array, p) << 8) | SafeWyCore.Read8(array, p + 4)) ^ SafeWyCore.Prime1); break; case 6: seed = SafeWyCore.Mum(seed, ((SafeWyCore.Read32(array, p) << 16) | SafeWyCore.Read16(array, p + 4)) ^ SafeWyCore.Prime1); break; case 7: seed = SafeWyCore.Mum(seed, ((SafeWyCore.Read32(array, p) << 24) | (SafeWyCore.Read16(array, p + 4) << 8) | SafeWyCore.Read8(array, p + 6)) ^ SafeWyCore.Prime1); break; case 8: seed = SafeWyCore.Mum(seed, SafeWyCore.Read64Swapped(array, p) ^ SafeWyCore.Prime1); break; case 9: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read8(array, p + 8) ^ SafeWyCore.Prime2); break; case 10: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read16(array, p + 8) ^ SafeWyCore.Prime2); break; case 11: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, ((SafeWyCore.Read16(array, p + 8) << 8) | SafeWyCore.Read8(array, p + 10)) ^ SafeWyCore.Prime2); break; case 12: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read32(array, p + 8) ^ SafeWyCore.Prime2); break; case 13: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, ((SafeWyCore.Read32(array, p + 8) << 8) | SafeWyCore.Read8(array, p + 12)) ^ SafeWyCore.Prime2); break; case 14: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, ((SafeWyCore.Read32(array, p + 8) << 16) | SafeWyCore.Read16(array, p + 12)) ^ SafeWyCore.Prime2); break; case 15: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, ((SafeWyCore.Read32(array, p + 8) << 24) | (SafeWyCore.Read16(array, p + 12) << 8) | SafeWyCore.Read8(array, p + 14)) ^ SafeWyCore.Prime2); break; case 16: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2); break; case 17: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(seed, SafeWyCore.Read8(array, p + 16) ^ SafeWyCore.Prime3); break; case 18: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(seed, SafeWyCore.Read16(array, p + 16) ^ SafeWyCore.Prime3); break; case 19: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(seed, ((SafeWyCore.Read16(array, p + 16) << 8) | SafeWyCore.Read8(array, p + 18)) ^ SafeWyCore.Prime3); break; case 20: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(seed, SafeWyCore.Read32(array, p + 16) ^ SafeWyCore.Prime3); break; case 21: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(seed, ((SafeWyCore.Read32(array, p + 16) << 8) | SafeWyCore.Read8(array, p + 20)) ^ SafeWyCore.Prime3); break; case 22: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(seed, ((SafeWyCore.Read32(array, p + 16) << 16) | SafeWyCore.Read16(array, p + 20)) ^ SafeWyCore.Prime3); break; case 23: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(seed, ((SafeWyCore.Read32(array, p + 16) << 24) | (SafeWyCore.Read16(array, p + 20) << 8) | SafeWyCore.Read8(array, p + 22)) ^ SafeWyCore.Prime3); break; case 24: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(seed, SafeWyCore.Read64Swapped(array, p + 16) ^ SafeWyCore.Prime3); break; case 25: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p + 16) ^ seed, SafeWyCore.Read8(array, p + 24) ^ SafeWyCore.Prime4); break; case 26: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p + 16) ^ seed, SafeWyCore.Read16(array, p + 24) ^ SafeWyCore.Prime4); break; case 27: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p + 16) ^ seed, ((SafeWyCore.Read16(array, p + 24) << 8) | SafeWyCore.Read8(array, p + 26)) ^ SafeWyCore.Prime4); break; case 28: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p + 16) ^ seed, SafeWyCore.Read32(array, p + 24) ^ SafeWyCore.Prime4); break; case 29: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p + 16) ^ seed, ((SafeWyCore.Read32(array, p + 24) << 8) | SafeWyCore.Read8(array, p + 28)) ^ SafeWyCore.Prime4); break; case 30: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p + 16) ^ seed, ((SafeWyCore.Read32(array, p + 24) << 16) | SafeWyCore.Read16(array, p + 28)) ^ SafeWyCore.Prime4); break; case 31: seed = SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p) ^ seed, SafeWyCore.Read64Swapped(array, p + 8) ^ SafeWyCore.Prime2) ^ SafeWyCore.Mum(SafeWyCore.Read64Swapped(array, p + 16) ^ seed, ((SafeWyCore.Read32(array, p + 24) << 24) | (SafeWyCore.Read16(array, p + 28) << 8) | SafeWyCore.Read8(array, p + 30)) ^ SafeWyCore.Prime4); break; } return(seed); }
private static ulong HashFinal(ulong seed, ulong length) => SafeWyCore.Mum(seed, length ^ SafeWyCore.Prime5);