public static uint Compute(byte[] bytes) { if (!Sse42.IsSupported) { throw new NotSupportedException("SSE4.2 is not supported"); } uint crc = 0; int offset = 0; int len = bytes.Length; // x64 fast lane 8 bytes at a time if (Sse42.X64.IsSupported) { while (len >= 8) { crc = (uint)Sse42.X64.Crc32(crc, BitConverter.ToUInt64(bytes, offset)); offset += 8; len -= 8; } } while (len > 0) { crc = Sse42.Crc32(crc, bytes[offset]); offset++; len--; } return(crc); }
/// <summary>When overridden in a derived class, routes data written to the object into the hash algorithm for computing the hash.</summary> /// <param name="array">The input to compute the hash code for.</param> /// <param name="ibStart">The offset into the byte array from which to begin using data.</param> /// <param name="cbSize">The number of bytes in the byte array to use as data.</param> protected override void HashCore(byte[] array, int ibStart, int cbSize) { while (--cbSize >= 0) { _crc = Sse42.Crc32(_crc, array[ibStart++]); } }
/// <summary> /// Compute CRC32C for data /// </summary> /// <param name="input">input data</param> /// <param name="offset">offset</param> /// <param name="length">length</param> /// <returns>CRC32C checksum</returns> public static uint Compute(byte[] input, int offset, int length) { var crcLocal = uint.MaxValue; #if NETCOREAPP3_0 if (Sse42.IsSupported) { if (Sse42.X64.IsSupported) { while (length >= 8) { crcLocal = (uint)Sse42.X64.Crc32(crcLocal, BitConverter.ToUInt64(input, offset)); offset += 8; length -= 8; } } while (length > 0) { crcLocal = Sse42.Crc32(crcLocal, input[offset]); offset++; length--; } return(crcLocal ^ uint.MaxValue); } #endif while (length >= 16) { var a = Table[3 * 256 + input[offset + 12]] ^ Table[2 * 256 + input[offset + 13]] ^ Table[1 * 256 + input[offset + 14]] ^ Table[0 * 256 + input[offset + 15]]; var b = Table[7 * 256 + input[offset + 8]] ^ Table[6 * 256 + input[offset + 9]] ^ Table[5 * 256 + input[offset + 10]] ^ Table[4 * 256 + input[offset + 11]]; var c = Table[11 * 256 + input[offset + 4]] ^ Table[10 * 256 + input[offset + 5]] ^ Table[9 * 256 + input[offset + 6]] ^ Table[8 * 256 + input[offset + 7]]; var d = Table[15 * 256 + ((byte)crcLocal ^ input[offset])] ^ Table[14 * 256 + ((byte)(crcLocal >> 8) ^ input[offset + 1])] ^ Table[13 * 256 + ((byte)(crcLocal >> 16) ^ input[offset + 2])] ^ Table[12 * 256 + ((crcLocal >> 24) ^ input[offset + 3])]; crcLocal = d ^ c ^ b ^ a; offset += 16; length -= 16; } while (--length >= 0) { crcLocal = Table[(byte)(crcLocal ^ input[offset++])] ^ (crcLocal >> 8); } return(crcLocal ^ uint.MaxValue); }
/// <summary> /// Compute CRC32C for data /// </summary> /// <param name="input">input data</param> /// <param name="offset">offset</param> /// <param name="length">length</param> /// <returns>CRC32C checksum</returns> public static uint Compute(byte[] input, int offset, int length) { uint crcLocal = uint.MaxValue; #if NETCOREAPP3_0 if (_sseAvailable) { if (_x64Available) { while (length >= 8) { crcLocal = (uint)Sse42.X64.Crc32(crcLocal, BitConverter.ToUInt64(input, offset)); offset += 8; length -= 8; } } while (length > 0) { crcLocal = Sse42.Crc32(crcLocal, input[offset]); offset++; length--; } return(crcLocal ^ uint.MaxValue); } #endif while (length >= 16) { var a = Table[(3 * 256) + input[offset + 12]] ^ Table[(2 * 256) + input[offset + 13]] ^ Table[(1 * 256) + input[offset + 14]] ^ Table[(0 * 256) + input[offset + 15]]; var b = Table[(7 * 256) + input[offset + 8]] ^ Table[(6 * 256) + input[offset + 9]] ^ Table[(5 * 256) + input[offset + 10]] ^ Table[(4 * 256) + input[offset + 11]]; var c = Table[(11 * 256) + input[offset + 4]] ^ Table[(10 * 256) + input[offset + 5]] ^ Table[(9 * 256) + input[offset + 6]] ^ Table[(8 * 256) + input[offset + 7]]; var d = Table[(15 * 256) + ((byte)crcLocal ^ input[offset])] ^ Table[(14 * 256) + ((byte)(crcLocal >> 8) ^ input[offset + 1])] ^ Table[(13 * 256) + ((byte)(crcLocal >> 16) ^ input[offset + 2])] ^ Table[(12 * 256) + ((crcLocal >> 24) ^ input[offset + 3])]; crcLocal = d ^ c ^ b ^ a; offset += 16; length -= 16; } while (--length >= 0) { crcLocal = Table[(byte)(crcLocal ^ input[offset++])] ^ crcLocal >> 8; } return(crcLocal ^ uint.MaxValue); }
static uint Hash(uint val, byte other) { if (Sse.IsSupported) { return(Sse42.Crc32(val, other)); } else { return((uint)HashCode.Combine(val, other)); } }
private uint UpdateHash(uint val) { #if SUPPORTS_RUNTIME_INTRINSICS if (Sse42.IsSupported) { return(Sse42.Crc32(0U, val)); } else #endif { return((val * 2654435761U) >> 16); } }
public static uint Update(uint crc, ReadOnlySpan <byte> input) { crc ^= uint.MaxValue; while (input.Length >= sizeof(uint)) { crc = Sse42.Crc32(crc, Unsafe.ReadUnaligned <uint>(ref MemoryMarshal.GetReference(input))); input = input.Slice(sizeof(uint)); } for (int i = 0; i < input.Length; i++) { crc = Sse42.Crc32(crc, (byte)input[i]); } return(crc ^ uint.MaxValue); }
static ulong Hash8(ulong val, ulong other) { if (Sse.X64.IsSupported) { return(Sse42.X64.Crc32(val, other)); } else if (Sse.IsSupported) { val = Sse42.Crc32((uint)val, (uint)other); return(Sse42.Crc32((uint)val, (uint)(other >> 32))); } else { return((ulong)HashCode.Combine(val, other)); } }
public void Crc32() { //var left = Vector256.Create(a+0,a+1,a+2,a+3,a+4,a+5,a+6,a+7,a+8,a+9,a+10,a+11,a+12,a+13,a+14,a+15); //var right = Vector256.Create(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); var CRC32 = new CRC32(0); var actual_Crc32 = 0U; for (var a = 0U; a < 2; a++) { CRC32.Input(a); actual_Crc32 = Sse42.Crc32(actual_Crc32, a); } var expected_Crc32 = CRC32.GetHashCode(); Assert.AreEqual(expected_Crc32, actual_Crc32); }
static unsafe bool TestByteContainment() { byte value = (byte)0; byte *ptr = &value; if (Sse42.IsSupported) { if (Sse42.Crc32(0xffffffffU, (byte)0) != 0xad82acaeU) { Console.WriteLine("TestByteContainment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, value) != 0xad82acaeU) { Console.WriteLine("TestByteContainment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, *ptr) != 0xad82acaeU) { Console.WriteLine("TestByteContainment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, byteArray[1]) != 0xad82acaeU) { Console.WriteLine("TestByteContainment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, byteArray[*ptr + 1]) != 0xad82acaeU) { Console.WriteLine("TestByteContainment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, byteSF) != 0xad82acaeU) { Console.WriteLine("TestByteContainment failed on Crc32"); return(false); } } return(true); }
static unsafe bool TestUInt16Containment() { ushort value = (ushort)0; ushort *ptr = &value; if (Sse42.IsSupported) { if (Sse42.Crc32(0xffffffffU, (ushort)0) != 0xe9e882dU) { Console.WriteLine("TestUInt16Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, value) != 0xe9e882dU) { Console.WriteLine("TestUInt16Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, *ptr) != 0xe9e882dU) { Console.WriteLine("TestUInt16Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, ushortArray[1]) != 0xe9e882dU) { Console.WriteLine("TestUInt16Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, ushortArray[*ptr + 1]) != 0xe9e882dU) { Console.WriteLine("TestUInt16Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, ushortSF) != 0xe9e882dU) { Console.WriteLine("TestUInt16Containment failed on Crc32"); return(false); } } return(true); }
/// <summary>When overridden in a derived class, routes data written to the object into the hash algorithm for computing the hash.</summary> /// <param name="array">The input to compute the hash code for.</param> /// <param name="ibStart">The offset into the byte array from which to begin using data.</param> /// <param name="cbSize">The number of bytes in the byte array to use as data.</param> protected override void HashCore(byte[] array, int ibStart, int cbSize) { if (_x64Available) { while (cbSize >= 8) { _crc = (uint)Sse42.X64.Crc32(_crc, BitConverter.ToUInt64(array, ibStart)); ibStart += 8; cbSize -= 8; } } while (cbSize > 0) { _crc = Sse42.Crc32(_crc, array[ibStart]); ibStart++; cbSize--; } }
public static uint Update64(uint crc, ReadOnlySpan <byte> input) { ulong crcl = crc ^ uint.MaxValue; while (input.Length >= sizeof(ulong)) { crcl = Sse42.X64.Crc32(crcl, Unsafe.ReadUnaligned <ulong>(ref MemoryMarshal.GetReference(input))); input = input.Slice(sizeof(ulong)); } crc = unchecked ((uint)crcl); if (input.Length >= 4) { crc = Sse42.Crc32(crc, Unsafe.ReadUnaligned <uint>(ref MemoryMarshal.GetReference(input))); input = input.Slice(sizeof(uint)); } for (int i = 0; i < input.Length; i++) { crc = Sse42.Crc32(crc, (byte)input[i]); } return(crc ^ uint.MaxValue); }
public override ulong Run(CancellationToken cancellationToken) { if (!Sse42.IsSupported) { return(0uL); } var iterations = 0uL; while (!cancellationToken.IsCancellationRequested) { var crc = 0u; for (var i = 0; i < LENGTH; i++) { crc = Sse42.Crc32(crc, datas); } iterations++; } return(iterations); }
static int Main() { s_success = true; // We expect the AOT compiler generated HW intrinsics with the following characteristics: // // * TRUE = IsSupported assumed to be true, no runtime check // * NULL = IsSupported is a runtime check, code should be behind the check or bad things happen // * FALSE = IsSupported assumed to be false, no runtime check, PlatformNotSupportedException if used // // The test is compiled with multiple defines to test this. #if BASELINE_INTRINSICS bool vectorsAccelerated = true; int byteVectorLength = 16; bool?Sse2AndBelow = true; bool?Sse3Group = null; bool?AesLzPcl = null; bool?Sse4142 = null; bool?PopCnt = null; bool?Avx12 = false; bool?FmaBmi12 = false; bool?Avxvnni = false; #elif NON_VEX_INTRINSICS bool vectorsAccelerated = true; int byteVectorLength = 16; bool?Sse2AndBelow = true; bool?Sse3Group = true; bool?AesLzPcl = null; bool?Sse4142 = true; bool?PopCnt = null; bool?Avx12 = false; bool?FmaBmi12 = false; bool?Avxvnni = false; #elif VEX_INTRINSICS bool vectorsAccelerated = true; int byteVectorLength = 32; bool?Sse2AndBelow = true; bool?Sse3Group = true; bool?AesLzPcl = null; bool?Sse4142 = true; bool?PopCnt = null; bool?Avx12 = true; bool?FmaBmi12 = null; bool?Avxvnni = null; #else #error Who dis? #endif if (vectorsAccelerated != Vector.IsHardwareAccelerated) { throw new Exception($"Vectors HW acceleration state unexpected - expected {vectorsAccelerated}, got {Vector.IsHardwareAccelerated}"); } if (byteVectorLength != Vector <byte> .Count) { throw new Exception($"Unexpected vector length - expected {byteVectorLength}, got {Vector<byte>.Count}"); } Check("Sse", Sse2AndBelow, &SseIsSupported, Sse.IsSupported, () => Sse.Subtract(Vector128 <float> .Zero, Vector128 <float> .Zero).Equals(Vector128 <float> .Zero)); Check("Sse.X64", Sse2AndBelow, &SseX64IsSupported, Sse.X64.IsSupported, () => Sse.X64.ConvertToInt64WithTruncation(Vector128 <float> .Zero) == 0); Check("Sse2", Sse2AndBelow, &Sse2IsSupported, Sse2.IsSupported, () => Sse2.Extract(Vector128 <ushort> .Zero, 0) == 0); Check("Sse2.X64", Sse2AndBelow, &Sse2X64IsSupported, Sse2.X64.IsSupported, () => Sse2.X64.ConvertToInt64(Vector128 <double> .Zero) == 0); Check("Sse3", Sse3Group, &Sse3IsSupported, Sse3.IsSupported, () => Sse3.MoveHighAndDuplicate(Vector128 <float> .Zero).Equals(Vector128 <float> .Zero)); Check("Sse3.X64", Sse3Group, &Sse3X64IsSupported, Sse3.X64.IsSupported, null); Check("Ssse3", Sse3Group, &Ssse3IsSupported, Ssse3.IsSupported, () => Ssse3.Abs(Vector128 <short> .Zero).Equals(Vector128 <ushort> .Zero)); Check("Ssse3.X64", Sse3Group, &Ssse3X64IsSupported, Ssse3.X64.IsSupported, null); Check("Sse41", Sse4142, &Sse41IsSupported, Sse41.IsSupported, () => Sse41.Max(Vector128 <int> .Zero, Vector128 <int> .Zero).Equals(Vector128 <int> .Zero)); Check("Sse41.X64", Sse4142, &Sse41X64IsSupported, Sse41.X64.IsSupported, () => Sse41.X64.Extract(Vector128 <long> .Zero, 0) == 0); Check("Sse42", Sse4142, &Sse42IsSupported, Sse42.IsSupported, () => Sse42.Crc32(0, 0) == 0); Check("Sse42.X64", Sse4142, &Sse42X64IsSupported, Sse42.X64.IsSupported, () => Sse42.X64.Crc32(0, 0) == 0); Check("Aes", AesLzPcl, &AesIsSupported, Aes.IsSupported, () => Aes.KeygenAssist(Vector128 <byte> .Zero, 0).Equals(Vector128.Create((byte)99))); Check("Aes.X64", AesLzPcl, &AesX64IsSupported, Aes.X64.IsSupported, null); Check("Avx", Avx12, &AvxIsSupported, Avx.IsSupported, () => Avx.Add(Vector256 <double> .Zero, Vector256 <double> .Zero).Equals(Vector256 <double> .Zero)); Check("Avx.X64", Avx12, &AvxX64IsSupported, Avx.X64.IsSupported, null); Check("Avx2", Avx12, &Avx2IsSupported, Avx2.IsSupported, () => Avx2.Abs(Vector256 <int> .Zero).Equals(Vector256 <uint> .Zero)); Check("Avx2.X64", Avx12, &Avx2X64IsSupported, Avx2.X64.IsSupported, null); Check("Bmi1", FmaBmi12, &Bmi1IsSupported, Bmi1.IsSupported, () => Bmi1.AndNot(0, 0) == 0); Check("Bmi1.X64", FmaBmi12, &Bmi1X64IsSupported, Bmi1.X64.IsSupported, () => Bmi1.X64.AndNot(0, 0) == 0); Check("Bmi2", FmaBmi12, &Bmi2IsSupported, Bmi2.IsSupported, () => Bmi2.MultiplyNoFlags(0, 0) == 0); Check("Bmi2.X64", FmaBmi12, &Bmi2X64IsSupported, Bmi2.X64.IsSupported, () => Bmi2.X64.MultiplyNoFlags(0, 0) == 0); Check("Fma", FmaBmi12, &FmaIsSupported, Fma.IsSupported, () => Fma.MultiplyAdd(Vector128 <float> .Zero, Vector128 <float> .Zero, Vector128 <float> .Zero).Equals(Vector128 <float> .Zero)); Check("Fma.X64", FmaBmi12, &FmaX64IsSupported, Fma.X64.IsSupported, null); Check("Lzcnt", AesLzPcl, &LzcntIsSupported, Lzcnt.IsSupported, () => Lzcnt.LeadingZeroCount(0) == 32); Check("Lzcnt.X64", AesLzPcl, &LzcntX64IsSupported, Lzcnt.X64.IsSupported, () => Lzcnt.X64.LeadingZeroCount(0) == 64); Check("Pclmulqdq", AesLzPcl, &PclmulqdqIsSupported, Pclmulqdq.IsSupported, () => Pclmulqdq.CarrylessMultiply(Vector128 <long> .Zero, Vector128 <long> .Zero, 0).Equals(Vector128 <long> .Zero)); Check("Pclmulqdq.X64", AesLzPcl, &PclmulqdqX64IsSupported, Pclmulqdq.X64.IsSupported, null); Check("Popcnt", PopCnt, &PopcntIsSupported, Popcnt.IsSupported, () => Popcnt.PopCount(0) == 0); Check("Popcnt.X64", PopCnt, &PopcntX64IsSupported, Popcnt.X64.IsSupported, () => Popcnt.X64.PopCount(0) == 0); Check("AvxVnni", Avxvnni, &AvxVnniIsSupported, AvxVnni.IsSupported, () => AvxVnni.MultiplyWideningAndAdd(Vector128 <int> .Zero, Vector128 <byte> .Zero, Vector128 <sbyte> .Zero).Equals(Vector128 <int> .Zero)); Check("AvxVnni.X64", Avxvnni, &AvxVnniX64IsSupported, AvxVnni.X64.IsSupported, null); return(s_success ? 100 : 1); }
internal static uint Append(uint crc, byte *data, int len) { #if HAS_INTRINSICS if (IsHardwareAccelerated) { byte *next = data; //// TODO see for parallelism https://stackoverflow.com/questions/17645167/implementing-sse-4-2s-crc32c-in-software/17646775#17646775 var crc0 = uint.MaxValue ^ crc; while (len > 0 && ((ulong)next & 7) != 0) { crc0 = Sse42.Crc32(crc0, *next); next++; len--; } if (Sse42.X64.IsSupported) { while (len >= 32) { crc0 = (uint)Sse42.X64.Crc32(crc0, Read <ulong>(next)); crc0 = (uint)Sse42.X64.Crc32(crc0, Read <ulong>(next + 8)); crc0 = (uint)Sse42.X64.Crc32(crc0, Read <ulong>(next + 16)); crc0 = (uint)Sse42.X64.Crc32(crc0, Read <ulong>(next + 24)); next += 32; len -= 32; } while (len >= 16) { crc0 = (uint)Sse42.X64.Crc32(crc0, Read <ulong>(next)); crc0 = (uint)Sse42.X64.Crc32(crc0, Read <ulong>(next + 8)); next += 16; len -= 16; } while (len >= 8) { crc0 = (uint)Sse42.X64.Crc32(crc0, Read <ulong>(next)); next += 8; len -= 8; } } // NB do not unroll anything for x86 case, it doesn't matter much while (len >= 4) { crc0 = Sse42.Crc32(crc0, Read <uint>(next)); next += 4; len -= 4; } while (len >= 2) { crc0 = Sse42.Crc32(crc0, Read <ushort>(next)); next += 2; len -= 2; } while (len > 0) { crc0 = Sse42.Crc32(crc0, Read <byte>(next)); next++; len--; } return(crc0 ^ uint.MaxValue); } else { return(AppendManaged(crc, data, len)); } #else return(AppendManaged(crc, data, len)); #endif }
unsafe static Crc32cAlgorithm() { if (Sse42.X64.IsSupported #if CON_X86 | Sse42.IsSupported #endif ) { _Crc32cTable = null; CrcFunc = new Crc32cFunc((buffer, count, hashValue, reversed) => { #if CON_X86 var puint = (uint *)buffer; uint idata; while (count > 3) { idata = *(puint++); hashValue = Sse42.Crc32(hashValue, idata); count -= 4; } var pubyte = (byte *)puint; #else var pulong = (ulong *)buffer; ulong ldata; while (count > 7) { ldata = *(pulong++); hashValue = (uint)Sse42.X64.Crc32(hashValue, ldata); count -= 8; } var pubyte = (byte *)pulong; #endif byte bdata; while (count-- > 0) { bdata = *(pubyte++); hashValue = Sse42.Crc32(hashValue, bdata); } return(reversed ? ~hashValue : hashValue); }); } else { _Crc32cTable = new uint[] { 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U, 0xC79A971FU, 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU, 0x8AD958CFU, 0x78B2DBCCU, 0x6BE22838U, 0x9989AB3BU, 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, 0x5E133C24U, 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU, 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U, 0x9A879FA0U, 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U, 0x5D1D08BFU, 0xAF768BBCU, 0xBC267848U, 0x4E4DFB4BU, 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, 0x33ED7D2AU, 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U, 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U, 0x6DFE410EU, 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU, 0x30E349B1U, 0xC288CAB2U, 0xD1D83946U, 0x23B3BA45U, 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, 0xE4292D5AU, 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU, 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U, 0x417B1DBCU, 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U, 0x86E18AA3U, 0x748A09A0U, 0x67DAFA54U, 0x95B17957U, 0xCBA24573U, 0x39C9C670U, 0x2A993584U, 0xD8F2B687U, 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U, 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U, 0x96BF4DCCU, 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U, 0xDBFC821CU, 0x2997011FU, 0x3AC7F2EBU, 0xC8AC71E8U, 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, 0x0F36E6F7U, 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U, 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U, 0xEB1FCBADU, 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U, 0x2C855CB2U, 0xDEEEDFB1U, 0xCDBE2C45U, 0x3FD5AF46U, 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, 0x62C8A7F9U, 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U, 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U, 0x3CDB9BDDU, 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U, 0x82F63B78U, 0x709DB87BU, 0x63CD4B8FU, 0x91A6C88CU, 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, 0x563C5F93U, 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U, 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU, 0x92A8FC17U, 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U, 0x55326B08U, 0xA759E80BU, 0xB4091BFFU, 0x466298FCU, 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, 0x0B21572CU, 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U, 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U, 0x65D122B9U, 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU, 0x2892ED69U, 0xDAF96E6AU, 0xC9A99D9EU, 0x3BC21E9DU, 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, 0xFC588982U, 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU, 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U, 0x38CC2A06U, 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U, 0xFF56BD19U, 0x0D3D3E1AU, 0x1E6DCDEEU, 0xEC064EEDU, 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, 0xD0DDD530U, 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU, 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU, 0x8ECEE914U, 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U, 0xD3D3E1ABU, 0x21B862A8U, 0x32E8915CU, 0xC083125FU, 0x144976B4U, 0xE622F5B7U, 0xF5720643U, 0x07198540U, 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U, 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU, 0xE330A81AU, 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU, 0x24AA3F05U, 0xD6C1BC06U, 0xC5914FF2U, 0x37FACCF1U, 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, 0x7AB90321U, 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU, 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U, 0x34F4F86AU, 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU, 0x79B737BAU, 0x8BDCB4B9U, 0x988C474DU, 0x6AE7C44EU, 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, 0xAD7D5351U }; CrcFunc = new Crc32cFunc((buffer, count, hashValue, reversed) => { fixed(uint *table = _Crc32cTable) { while (count-- > 0) { hashValue = (hashValue >> 8) ^ table[(hashValue ^ *(buffer++)) & 0xFF]; } } return(reversed ? ~hashValue : hashValue); }); } }
/// <summary>Compute a CRC32 code for the input array segment.</summary> /// <param name="array">Array to read from.</param> /// <param name="offset">Offset in the array to start reading from.</param> /// <param name="count">Number of bytes to read.</param> /// <returns>CRC32 code of the input.</returns> public static uint Compute(byte[] array, int offset, int count) { // Validate if (array == null) { throw new ArgumentNullException(nameof(array), "Array is null."); } else if (offset < 0) { throw new ArgumentException(string.Format( "Offset {0} is negative", offset ), nameof(offset)); } else if (count < 0) { throw new ArgumentException(string.Format( "Count {0} is negative", count ), nameof(count)); } else if (offset + count > array.Length) { throw new ArgumentException(string.Format( "Count {0} from offset {1} extends beyond array length {2}", count, offset, array.Length ), nameof(count)); } uint crcLocal = uint.MaxValue; // Use SSE4 if available #if NETCOREAPP3_0 if (_sseAvailable) { if (_x64Available) { while (count >= 8) { crcLocal = (uint)Sse42.X64.Crc32(crcLocal, BitConverter.ToUInt64(array, offset)); offset += 8; count -= 8; } } while (count > 0) { crcLocal = Sse42.Crc32(crcLocal, array[offset]); offset++; count--; } return(crcLocal ^ uint.MaxValue); } #endif // Generate lookup table if not yet generated if (Table == null) { uint[] table = new uint[16 * 256]; for (uint i = 0; i < 256; i++) { uint res = i; for (int t = 0; t < 16; t++) { for (int k = 0; k < 8; k++) { res = (res & 1) == 1 ? Poly ^ (res >> 1) : (res >> 1); } table[t * 256 + i] = res; } } Interlocked.Exchange(ref Table, table); } while (count >= 16) { var a = Table[(3 * 256) + array[offset + 12]] ^ Table[(2 * 256) + array[offset + 13]] ^ Table[(1 * 256) + array[offset + 14]] ^ Table[(0 * 256) + array[offset + 15]]; var b = Table[(7 * 256) + array[offset + 8]] ^ Table[(6 * 256) + array[offset + 9]] ^ Table[(5 * 256) + array[offset + 10]] ^ Table[(4 * 256) + array[offset + 11]]; var c = Table[(11 * 256) + array[offset + 4]] ^ Table[(10 * 256) + array[offset + 5]] ^ Table[(9 * 256) + array[offset + 6]] ^ Table[(8 * 256) + array[offset + 7]]; var d = Table[(15 * 256) + ((byte)crcLocal ^ array[offset])] ^ Table[(14 * 256) + ((byte)(crcLocal >> 8) ^ array[offset + 1])] ^ Table[(13 * 256) + ((byte)(crcLocal >> 16) ^ array[offset + 2])] ^ Table[(12 * 256) + ((crcLocal >> 24) ^ array[offset + 3])]; crcLocal = d ^ c ^ b ^ a; offset += 16; count -= 16; } while (--count >= 0) { crcLocal = Table[(byte)(crcLocal ^ array[offset++])] ^ crcLocal >> 8; } return(crcLocal ^ uint.MaxValue); }
static unsafe bool TestUInt32Containment() { uint value = (uint)0; uint *ptr = &value; if (Lzcnt.IsSupported) { if (Lzcnt.LeadingZeroCount(*ptr) != 32) { Console.WriteLine("TestUInt32Containment failed on LeadingZeroCount"); return(false); } if (Lzcnt.LeadingZeroCount(uintArray[2]) != 32) { Console.WriteLine("TestUInt32Containment failed on LeadingZeroCount"); return(false); } if (Lzcnt.LeadingZeroCount(uintArray[*ptr + 2]) != 32) { Console.WriteLine("TestUInt32Containment failed on LeadingZeroCount"); return(false); } } uint *ptr1 = &value; if (Sse42.IsSupported) { if (Sse42.Crc32(0xffffffffU, (uint)0) != 0xb798b438U) { Console.WriteLine("TestUInt32Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, value) != 0xb798b438U) { Console.WriteLine("TestUInt32Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, *ptr1) != 0xb798b438U) { Console.WriteLine("TestUInt32Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, uintArray[1]) != 0xb798b438U) { Console.WriteLine("TestUInt32Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, uintArray[*ptr + 1]) != 0xb798b438U) { Console.WriteLine("TestUInt32Containment failed on Crc32"); return(false); } if (Sse42.Crc32(0xffffffffU, uintSF) != 0xb798b438U) { Console.WriteLine("TestUInt32Containment failed on Crc32"); return(false); } } return(true); }
static uint Problem5(uint crc, double data) => Sse42.Crc32(crc, (uint)data);
static uint Problem6(uint crc, float data) => Sse42.Crc32(crc, (uint)data);
static uint Problem4(uint crc, ulong data) => Sse42.Crc32(crc, (uint)(data >> 16));
internal static uint AppendCopy(uint crc, byte *data, int len, byte *copyTarget) { #if NETCOREAPP3_0 if (IsHardwareAccelerated) { byte *next = data; //// TODO see for parallelism https://stackoverflow.com/questions/17645167/implementing-sse-4-2s-crc32c-in-software/17646775#17646775 var crc0 = uint.MaxValue ^ crc; // We use Unsafe.ReadUnaligned instead of manual alignment //while (len > 0 && ((ulong)next & 7) != 0) //{ // crc0 = Sse42.Crc32(crc0, *next); // next++; // len--; //} if (Sse42.X64.IsSupported) { while (len >= 32) { crc0 = (uint)Sse42.X64.Crc32(crc0, ReadUnaligned <ulong>(next)); crc0 = (uint)Sse42.X64.Crc32(crc0, ReadUnaligned <ulong>(next + 8)); crc0 = (uint)Sse42.X64.Crc32(crc0, ReadUnaligned <ulong>(next + 16)); crc0 = (uint)Sse42.X64.Crc32(crc0, ReadUnaligned <ulong>(next + 24)); CopyBlockUnaligned(copyTarget, next, 32); copyTarget += 32; next += 32; len -= 32; } while (len >= 16) { crc0 = (uint)Sse42.X64.Crc32(crc0, ReadUnaligned <ulong>(next)); crc0 = (uint)Sse42.X64.Crc32(crc0, ReadUnaligned <ulong>(next + 8)); CopyBlockUnaligned(copyTarget, next, 16); copyTarget += 16; next += 16; len -= 16; } while (len >= 8) { crc0 = (uint)Sse42.X64.Crc32(crc0, ReadUnaligned <ulong>(next)); CopyBlockUnaligned(copyTarget, next, 8); copyTarget += 8; next += 8; len -= 8; } } // NB do not unroll anything for x86 case, it doesn't matter much while (len >= 4) { crc0 = Sse42.Crc32(crc0, ReadUnaligned <uint>(next)); CopyBlockUnaligned(copyTarget, next, 4); copyTarget += 4; next += 4; len -= 4; } while (len >= 2) { crc0 = Sse42.Crc32(crc0, ReadUnaligned <ushort>(next)); CopyBlockUnaligned(copyTarget, next, 2); copyTarget += 2; next += 2; len -= 2; } while (len > 0) { crc0 = Sse42.Crc32(crc0, *next); *copyTarget = *next; copyTarget++; next++; len--; } return(crc0 ^ uint.MaxValue); } else { var crc0 = AppendManaged(crc, data, len); CopyBlockUnaligned(copyTarget, data, (uint)len); return(crc0); } #else var crc0 = AppendManaged(crc, data, len); CopyBlockUnaligned(copyTarget, data, (uint)len); return(crc0); #endif }
public static uint Append(uint crc, ReadOnlySpan <byte> source) { uint crcLocal = uint.MaxValue ^ crc; #if NETCOREAPP3_0 // If available on the current CPU, use Intel CRC32C intrinsic operations. // The Sse42 if statements are optimized out by the JIT compiler based on CPU support. if (Sse42.IsSupported) { // Process in 8-byte chunks first if 64-bit if (Sse42.X64.IsSupported) { if (source.Length >= 8) { // work with a ulong local during the loop to reduce typecasts ulong crcLocalLong = crcLocal; do { crcLocalLong = Sse42.X64.Crc32(crcLocalLong, MemoryMarshal.Read <ulong>(source)); source = source.Slice(8); } while (source.Length >= 8); crcLocal = (uint)crcLocalLong; } } // Process in 4-byte chunks while (source.Length >= 4) { crcLocal = Sse42.Crc32(crcLocal, MemoryMarshal.Read <uint>(source)); source = source.Slice(4); } // Process the remainder var j = 0; while (j < source.Length) { crcLocal = Sse42.Crc32(crcLocal, source[j++]); } return(crcLocal ^ uint.MaxValue); } #endif uint[] table = Table; while (source.Length >= 16) { var a = table[(3 * 256) + source[12]] ^ table[(2 * 256) + source[13]] ^ table[(1 * 256) + source[14]] ^ table[(0 * 256) + source[15]]; var b = table[(7 * 256) + source[8]] ^ table[(6 * 256) + source[9]] ^ table[(5 * 256) + source[10]] ^ table[(4 * 256) + source[11]]; var c = table[(11 * 256) + source[4]] ^ table[(10 * 256) + source[5]] ^ table[(9 * 256) + source[6]] ^ table[(8 * 256) + source[7]]; var d = table[(15 * 256) + ((byte)crcLocal ^ source[0])] ^ table[(14 * 256) + ((byte)(crcLocal >> 8) ^ source[1])] ^ table[(13 * 256) + ((byte)(crcLocal >> 16) ^ source[2])] ^ table[(12 * 256) + ((crcLocal >> 24) ^ source[3])]; crcLocal = d ^ c ^ b ^ a; source = source.Slice(16); } for (int offset = 0; offset < source.Length; offset++) { crcLocal = table[(byte)(crcLocal ^ source[offset])] ^ crcLocal >> 8; } return(crcLocal ^ uint.MaxValue); }
/// <summary> /// Compute CRC32C for data /// </summary> /// <param name="input">input data</param> /// <param name="offset">offset</param> /// <param name="length">length</param> /// <returns>CRC32C checksum</returns> public static uint Compute(byte[] input, int offset, int length) { uint crcLocal = uint.MaxValue; #if NETCOREAPP3_0_OR_GREATER || NETCOREAPP3_1 || NET5_0 if (Sse42.IsSupported) { var data = new ReadOnlySpan <byte>(input, offset, length); int processed = 0; if (Sse42.X64.IsSupported && data.Length > sizeof(ulong)) { processed = data.Length / sizeof(ulong) * sizeof(ulong); var ulongs = MemoryMarshal.Cast <byte, ulong>(data.Slice(0, processed)); ulong crclong = crcLocal; for (int i = 0; i < ulongs.Length; i++) { crclong = Sse42.X64.Crc32(crclong, ulongs[i]); } crcLocal = (uint)crclong; } else if (data.Length > sizeof(uint)) { processed = data.Length / sizeof(uint) * sizeof(uint); var uints = MemoryMarshal.Cast <byte, uint>(data.Slice(0, processed)); for (int i = 0; i < uints.Length; i++) { crcLocal = Sse42.Crc32(crcLocal, uints[i]); } } for (int i = processed; i < data.Length; i++) { crcLocal = Sse42.Crc32(crcLocal, data[i]); } return(crcLocal ^ uint.MaxValue); } #endif #if NET5_0_OR_GREATER || NET5_0 if (Crc32.IsSupported) { var data = new ReadOnlySpan <byte>(input, offset, length); int processed = 0; if (Crc32.Arm64.IsSupported && data.Length > sizeof(ulong)) { processed = data.Length / sizeof(ulong) * sizeof(ulong); var ulongs = MemoryMarshal.Cast <byte, ulong>(data.Slice(0, processed)); for (int i = 0; i < ulongs.Length; i++) { crcLocal = Crc32.Arm64.ComputeCrc32C(crcLocal, ulongs[i]); } } else if (data.Length > sizeof(uint)) { processed = data.Length / sizeof(uint) * sizeof(uint); var uints = MemoryMarshal.Cast <byte, uint>(data.Slice(0, processed)); for (int i = 0; i < uints.Length; i++) { crcLocal = Crc32.ComputeCrc32C(crcLocal, uints[i]); } } for (int i = processed; i < data.Length; i++) { crcLocal = Crc32.ComputeCrc32C(crcLocal, data[i]); } return(crcLocal ^ uint.MaxValue); } #endif while (length >= 16) { var a = Table[(3 * 256) + input[offset + 12]] ^ Table[(2 * 256) + input[offset + 13]] ^ Table[(1 * 256) + input[offset + 14]] ^ Table[(0 * 256) + input[offset + 15]]; var b = Table[(7 * 256) + input[offset + 8]] ^ Table[(6 * 256) + input[offset + 9]] ^ Table[(5 * 256) + input[offset + 10]] ^ Table[(4 * 256) + input[offset + 11]]; var c = Table[(11 * 256) + input[offset + 4]] ^ Table[(10 * 256) + input[offset + 5]] ^ Table[(9 * 256) + input[offset + 6]] ^ Table[(8 * 256) + input[offset + 7]]; var d = Table[(15 * 256) + ((byte)crcLocal ^ input[offset])] ^ Table[(14 * 256) + ((byte)(crcLocal >> 8) ^ input[offset + 1])] ^ Table[(13 * 256) + ((byte)(crcLocal >> 16) ^ input[offset + 2])] ^ Table[(12 * 256) + ((crcLocal >> 24) ^ input[offset + 3])]; crcLocal = d ^ c ^ b ^ a; offset += 16; length -= 16; } while (--length >= 0) { crcLocal = Table[(byte)(crcLocal ^ input[offset++])] ^ crcLocal >> 8; } return(crcLocal ^ uint.MaxValue); }
static int Main(string[] args) { ulong s1l = 0, s2l = 0, resl; int testResult = Pass; if (!Sse42.IsSupported || !Environment.Is64BitProcess) { try { resl = Sse42.Crc32(s1l, s2l); Console.WriteLine("Intrinsic Sse42.Crc32 is called on non-supported hardware."); Console.WriteLine("Sse42.IsSupported " + Sse42.IsSupported); Console.WriteLine("Environment.Is64BitProcess " + Environment.Is64BitProcess); testResult = Fail; } catch (PlatformNotSupportedException) { } try { resl = Convert.ToUInt64(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { s1l.GetType(), s2l.GetType() }).Invoke(null, new object[] { s1l, s2l })); Console.WriteLine("Intrinsic Sse42.Crc32 is called via reflection on non-supported hardware."); Console.WriteLine("Sse42.IsSupported " + Sse42.IsSupported); Console.WriteLine("Environment.Is64BitProcess " + Environment.Is64BitProcess); testResult = Fail; } catch (TargetInvocationException e) when(e.InnerException is PlatformNotSupportedException) { } } if (Sse42.IsSupported) { if (Environment.Is64BitProcess) { for (int i = 0; i < longCrcTable.Length; i++) { s1l = longCrcTable[i].s1; s2l = longCrcTable[i].s2; resl = Sse42.Crc32(s1l, s2l); if (resl != longCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,16:x}, 0x{2,16:x} Expected: 0x{3,16:x} actual: 0x{4,16:x}", i, s1l, s2l, longCrcTable[i].res, resl); testResult = Fail; } resl = Convert.ToUInt64(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { s1l.GetType(), s2l.GetType() }).Invoke(null, new object[] { s1l, s2l })); if (resl != longCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,16:x}, 0x{2,16:x} Expected: 0x{3,16:x} actual: 0x{4,16:x} - Reflection", i, s1l, s2l, longCrcTable[i].res, resl); testResult = Fail; } } } uint s1i, s2i, resi; for (int i = 0; i < intCrcTable.Length; i++) { s1i = intCrcTable[i].s1; s2i = intCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2i); if (resi != intCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2i, intCrcTable[i].res, resi); testResult = Fail; } resi = Convert.ToUInt32(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { s1i.GetType(), s2i.GetType() }).Invoke(null, new object[] { s1i, s2i })); if (resi != intCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x} - Reflection", i, s1i, s2i, intCrcTable[i].res, resi); testResult = Fail; } } ushort s2s; for (int i = 0; i < shortCrcTable.Length; i++) { s1i = shortCrcTable[i].s1; s2s = shortCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2s); if (resi != shortCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2s, shortCrcTable[i].res, resi); testResult = Fail; } resi = Convert.ToUInt32(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { s1i.GetType(), s2s.GetType() }).Invoke(null, new object[] { s1i, s2s })); if (resi != shortCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x} - Reflection", i, s1i, s2s, shortCrcTable[i].res, resi); testResult = Fail; } } byte s2b; for (int i = 0; i < byteCrcTable.Length; i++) { s1i = byteCrcTable[i].s1; s2b = byteCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2b); if (resi != byteCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2b, byteCrcTable[i].res, resi); testResult = Fail; } resi = Convert.ToUInt32(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { s1i.GetType(), s2b.GetType() }).Invoke(null, new object[] { s1i, s2b })); if (resi != byteCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2b, byteCrcTable[i].res, resi); testResult = Fail; } } } return(testResult); }
static int Main(string[] args) { ulong s1l = 0, s2l = 0, resl; int testResult = Pass; if (Sse42.IsSupported) { uint s1i, s2i, resi; for (int i = 0; i < intCrcTable.Length; i++) { s1i = intCrcTable[i].s1; s2i = intCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2i); if (resi != intCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2i, intCrcTable[i].res, resi); testResult = Fail; } resi = Convert.ToUInt32(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { s1i.GetType(), s2i.GetType() }).Invoke(null, new object[] { s1i, s2i })); if (resi != intCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x} - Reflection", i, s1i, s2i, intCrcTable[i].res, resi); testResult = Fail; } } ushort s2s; for (int i = 0; i < shortCrcTable.Length; i++) { s1i = shortCrcTable[i].s1; s2s = shortCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2s); if (resi != shortCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2s, shortCrcTable[i].res, resi); testResult = Fail; } resi = Convert.ToUInt32(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { s1i.GetType(), s2s.GetType() }).Invoke(null, new object[] { s1i, s2s })); if (resi != shortCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x} - Reflection", i, s1i, s2s, shortCrcTable[i].res, resi); testResult = Fail; } } byte s2b; for (int i = 0; i < byteCrcTable.Length; i++) { s1i = byteCrcTable[i].s1; s2b = byteCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2b); if (resi != byteCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2b, byteCrcTable[i].res, resi); testResult = Fail; } resi = Convert.ToUInt32(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { s1i.GetType(), s2b.GetType() }).Invoke(null, new object[] { s1i, s2b })); if (resi != byteCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2b, byteCrcTable[i].res, resi); testResult = Fail; } } } return(testResult); }
static uint Problem3(uint crc, uint data) => Sse42.Crc32(crc, (uint)(byte)data);
static uint Problem1(byte *pSrc, uint data) => Sse42.Crc32(*pSrc, data);
static int Main(string[] args) { ulong s1l = 0, s2l = 0, resl; int testResult = Pass; if (!Sse42.IsSupported || !Environment.Is64BitProcess) { try { resl = Sse42.Crc32(s1l, s2l); Console.WriteLine("Intrinsic Sse42.Crc32 is called on non-supported hardware."); Console.WriteLine("Sse42.IsSupported " + Sse42.IsSupported); Console.WriteLine("Environment.Is64BitProcess " + Environment.Is64BitProcess); return(Fail); } catch (PlatformNotSupportedException) { testResult = Pass; } } if (Sse42.IsSupported) { if (Environment.Is64BitProcess) { for (int i = 0; i < longCrcTable.Length; i++) { s1l = longCrcTable[i].s1; s2l = longCrcTable[i].s2; resl = Sse42.Crc32(s1l, s2l); if (resl != longCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,16:x}, 0x{2,16:x} Expected: 0x{3,16:x} actual: 0x{4,16:x}", i, s1l, s2l, longCrcTable[i].res, resl); testResult = Fail; } } } uint s1i, s2i, resi; for (int i = 0; i < intCrcTable.Length; i++) { s1i = intCrcTable[i].s1; s2i = intCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2i); if (resi != intCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2i, intCrcTable[i].res, resi); testResult = Fail; } } ushort s2s; for (int i = 0; i < shortCrcTable.Length; i++) { s1i = shortCrcTable[i].s1; s2s = shortCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2s); if (resi != shortCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2s, shortCrcTable[i].res, resi); testResult = Fail; } } byte s2b; for (int i = 0; i < byteCrcTable.Length; i++) { s1i = byteCrcTable[i].s1; s2b = byteCrcTable[i].s2; resi = Sse42.Crc32(s1i, s2b); if (resi != byteCrcTable[i].res) { Console.WriteLine("{0}: Inputs: 0x{1,8:x}, 0x{2,8:x} Expected: 0x{3,8:x} actual: 0x{4,8:x}", i, s1i, s2b, byteCrcTable[i].res, resi); testResult = Fail; } } } return(testResult); }