public void RunStructLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); var result = Sse42.CompareGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); }
public void RunBasicScenario_LoadAligned() { var result = Sse42.CompareGreaterThan( Sse2.LoadAlignedVector128((Int64 *)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Int64 *)(_dataTable.inArray2Ptr)) ); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); }
public void RunClsVarScenario() { var result = Sse42.CompareGreaterThan( _clsVar1, _clsVar2 ); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); }
public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); var test = new SimpleBinaryOpTest__CompareGreaterThanInt64(); var result = Sse42.CompareGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); }
public void RunBasicScenario_UnsafeRead() { var result = Sse42.CompareGreaterThan( Unsafe.Read <Vector128 <Int64> >(_dataTable.inArray1Ptr), Unsafe.Read <Vector128 <Int64> >(_dataTable.inArray2Ptr) ); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); }
private static unsafe void FillRowSSe(ushort *previousRow, int length) { var one = Vector128.CreateScalar((ushort)1); var j = one; for (int i = 0; i < length; ++i) { previousRow[i] = j.GetElement(0); j = Sse42.AddSaturate(j, one); } }
public void RunLclVarScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); var op1 = Sse2.LoadVector128((Int64 *)(_dataTable.inArray1Ptr)); var op2 = Sse2.LoadVector128((Int64 *)(_dataTable.inArray2Ptr)); var result = Sse42.CompareGreaterThan(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); }
public void RunLclVarScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); var left = Sse2.LoadAlignedVector128((Int64 *)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Int64 *)(_dataTable.inArray2Ptr)); var result = Sse42.CompareGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); }
static uint Hash(uint val, byte other) { if (Sse.IsSupported) { return(Sse42.Crc32(val, other)); } else { return((uint)HashCode.Combine(val, other)); } }
public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); var result = Sse42.CompareGreaterThan( Unsafe.Read <Vector128 <Int64> >(_dataTable.inArray1Ptr), Unsafe.Read <Vector128 <Int64> >(_dataTable.inArray2Ptr) ); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); }
public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); var result = Sse42.CompareGreaterThan( _clsVar1, _clsVar2 ); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); }
public void RunStructLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); var result = Sse42.CompareGreaterThan( Sse2.LoadVector128((Int64 *)(&test._fld1)), Sse2.LoadVector128((Int64 *)(&test._fld2)) ); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); }
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); }
public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanInt64 testClass) { fixed(Vector128 <Int64> *pFld1 = &_fld1) fixed(Vector128 <Int64> *pFld2 = &_fld2) { var result = Sse42.CompareGreaterThan( Sse2.LoadVector128((Int64 *)(pFld1)), Sse2.LoadVector128((Int64 *)(pFld2)) ); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } }
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 RunClassFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); fixed(Vector128 <Int64> *pFld1 = &_fld1) fixed(Vector128 <Int64> *pFld2 = &_fld2) { var result = Sse42.CompareGreaterThan( Sse2.LoadVector128((Int64 *)(pFld1)), Sse2.LoadVector128((Int64 *)(pFld2)) ); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); } }
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 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); }
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); }
/// <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--; } }
private static unsafe void FillRow3(ushort *previousRow, int length) { ushort *bytes = stackalloc ushort[] { 1, 2, 3, 4, 5, 6, 7, 8 }; var counter = Sse41.LoadVector128(bytes); var step = Vector128.Create((ushort)8); int i = 0; for (; i < (length & 7); i += 8) { Sse42.Store(previousRow + i, counter); counter = Sse42.AddSaturate(counter, step); } //step = Sse42.ShiftRightArithmetic step = Vector128.Create((ushort)1); for (; i < length; ++i) { previousRow[i] = counter.GetElement(0); counter = Sse42.AddSaturate(counter, step); } }
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); }
private static unsafe void FillRowSSeVector2(int *previousRow, int length) { const int LENGHT = 4; int i = 0; //int initialCount = Math.Min(count, previousRow.Length); for (i = 0; i < 2 * LENGHT;) { previousRow[i] = ++i; } var counter1 = Sse41.LoadVector128(previousRow); var counter2 = Sse41.LoadVector128(previousRow + LENGHT); var step = Vector128.Create(i); int *pDest = previousRow + i; for (; i < (length - (2 * LENGHT - 1)); i += 2 * LENGHT) { counter1 = Sse42.Add(counter1, step); counter2 = Sse42.Add(counter2, step); Sse42.Store(pDest, counter1); Sse42.Store(pDest + LENGHT, counter2); pDest += 2 * LENGHT; } if (i < (length - (LENGHT - 1))) { counter1 = Sse42.Add(counter1, step); Sse42.Store(previousRow + i, counter1); i += LENGHT; } for (; i < length;) { previousRow[i] = ++i; } }
public static void SplitFraction(Vector128 <double> d, out Vector128 <double> i, out Vector128 <double> f) { if (Avx2.IsSupported) { i = Avx2.RoundToZero(d); f = Avx2.Subtract(d, i); } else if (Avx.IsSupported) { i = Avx.RoundToZero(d); f = Avx.Subtract(d, i); } else if (Sse42.IsSupported) { i = Sse42.RoundToZero(d); f = Sse42.Subtract(d, i); } else { throw new Exception("Need Sse42, Avx or Avx2"); } }
public unsafe Tuple <int, int> MinMaxSse() { var vmin = Vector128.Create(int.MaxValue); var vmax = Vector128.Create(int.MinValue); int vecSize = Vector128 <int> .Count; fixed(int *pNumbers = numbers) { int i; for (i = 0; i < numbers.Length; i += vecSize) { var d = Sse42.LoadVector128(pNumbers + i); vmin = Sse42.Min(vmin, d); vmax = Sse42.Max(vmax, d); } // tail is pretty much irrelevant int tailLen = (numbers.Length % vecSize); for (i = 0; i < tailLen; ++i) { var d = Sse42.LoadScalarVector128(pNumbers + numbers.Length - i - 1); vmin = Sse42.Min(vmin, d); vmax = Sse42.Max(vmax, d); } } int min = int.MaxValue, max = int.MinValue; for (int i = 0; i < vecSize; ++i) { min = Math.Min(min, vmin.GetElement(i)); max = Math.Max(max, vmax.GetElement(i)); } return(new Tuple <int, int>(min, max)); }
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); }
/// <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); }
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); }
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); }