--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddDouble()
+ {
+ var test = new SimpleBinaryOpTest__AddDouble();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__AddDouble
+ {
+ private const int VectorSize = 32;
+ private const int ElementCount = VectorSize / sizeof(Double);
+
+ private static Double[] _data1 = new Double[ElementCount];
+ private static Double[] _data2 = new Double[ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Double> _dataTable;
+
+ static SimpleBinaryOpTest__AddDouble()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddDouble()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Double>(_data1, _data2, new Double[ElementCount]);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Avx.Add(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Avx).GetMethod(nameof(Avx.Add), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Avx.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddDouble();
+ var result = Avx.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Avx.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> left, Vector256<Double> right, Double[] result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[ElementCount];
+ Double[] inArray2 = new Double[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ if (BitConverter.DoubleToInt64Bits(left[0] + right[0]) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(left[i] + right[i]) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Add)}<Double>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddSingle()
+ {
+ var test = new SimpleBinaryOpTest__AddSingle();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__AddSingle
+ {
+ private const int VectorSize = 32;
+ private const int ElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data1 = new Single[ElementCount];
+ private static Single[] _data2 = new Single[ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+
+ static SimpleBinaryOpTest__AddSingle()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddSingle()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Single>(_data1, _data2, new Single[ElementCount]);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Avx.Add(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Avx).GetMethod(nameof(Avx.Add), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Avx.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddSingle();
+ var result = Avx.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Avx.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> left, Vector256<Single> right, Single[] result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[ElementCount];
+ Single[] inArray2 = new Single[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ if (BitConverter.SingleToInt32Bits(left[0] + right[0]) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(left[i] + right[i]) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Add)}<Single>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-//
-
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics.X86;
-using System.Runtime.Intrinsics;
-
-namespace IntelHardwareIntrinsicTest
-{
- class Program
- {
- const int Pass = 100;
- const int Fail = 0;
-
- static unsafe int Main(string[] args)
- {
- int testResult = Pass;
-
- if (Avx.IsSupported)
- {
- using (TestTable<float> floatTable = new TestTable<float>(new float[8] { 1, -5, 100, 0, 1, -5, 100, 0 }, new float[8] { 22, -1, -50, 0, 22, -1, -50, 0 }, new float[8]))
- using (TestTable<double> doubleTable = new TestTable<double>(new double[4] { 1, -5, 100, 0 }, new double[4] { 22, -1, -50, 0 }, new double[4]))
- {
- var vf1 = Unsafe.Read<Vector256<float>>(floatTable.inArray1Ptr);
- var vf2 = Unsafe.Read<Vector256<float>>(floatTable.inArray2Ptr);
- var vf3 = Avx.Add(vf1, vf2);
- Unsafe.Write(floatTable.outArrayPtr, vf3);
-
- if (!floatTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("AVX Add failed on float:");
- foreach (var item in floatTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vf3 = (Vector256<float>)typeof(Avx).GetMethod(nameof(Avx.Add), new Type[] { vf1.GetType(), vf2.GetType() }).Invoke(null, new object[] { vf1, vf2 });
- Unsafe.Write(floatTable.outArrayPtr, vf3);
-
- if (!floatTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("AVX Add failed via reflection on float:");
- foreach (var item in floatTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vd1 = Unsafe.Read<Vector256<double>>(doubleTable.inArray1Ptr);
- var vd2 = Unsafe.Read<Vector256<double>>(doubleTable.inArray2Ptr);
- var vd3 = Avx.Add(vd1, vd2);
- Unsafe.Write(doubleTable.outArrayPtr, vd3);
-
- if (!doubleTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("AVX Add failed on double:");
- foreach (var item in doubleTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vd3 = (Vector256<double>)typeof(Avx).GetMethod(nameof(Avx.Add), new Type[] { vd1.GetType(), vd2.GetType() }).Invoke(null, new object[] { vd1, vd2 });
- Unsafe.Write(doubleTable.outArrayPtr, vd3);
-
- if (!doubleTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("AVX Add failed via reflection on double:");
- foreach (var item in doubleTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
- }
- }
-
- return testResult;
- }
-
- public unsafe struct TestTable<T> : IDisposable where T : struct
- {
- public T[] inArray1;
- public T[] inArray2;
- public T[] outArray;
-
- public void* inArray1Ptr => inHandle1.AddrOfPinnedObject().ToPointer();
- public void* inArray2Ptr => inHandle2.AddrOfPinnedObject().ToPointer();
- public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();
-
- GCHandle inHandle1;
- GCHandle inHandle2;
- GCHandle outHandle;
- public TestTable(T[] a, T[] b, T[] c)
- {
- this.inArray1 = a;
- this.inArray2 = b;
- this.outArray = c;
-
- inHandle1 = GCHandle.Alloc(inArray1, GCHandleType.Pinned);
- inHandle2 = GCHandle.Alloc(inArray2, GCHandleType.Pinned);
- outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
- }
- public bool CheckResult(Func<T, T, T, bool> check)
- {
- for (int i = 0; i < inArray1.Length; i++)
- {
- if (!check(inArray1[i], inArray2[i], outArray[i]))
- {
- return false;
- }
- }
- return true;
- }
-
- public void Dispose()
- {
- inHandle1.Free();
- inHandle2.Free();
- outHandle.Free();
- }
- }
-
- }
-}
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
- <Compile Include="Add.cs" />
+ <Compile Include="Add.Double.cs" />
+ <Compile Include="Add.Single.cs" />
+ <Compile Include="Multiply.Double.cs" />
+ <Compile Include="Multiply.Single.cs" />
+ <Compile Include="Program.Avx.cs" />
+ <Compile Include="..\Shared\Program.cs" />
+ <Compile Include="..\Shared\SimpleBinOpTest_DataTable.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
- <Compile Include="Add.cs" />
+ <Compile Include="Add.Double.cs" />
+ <Compile Include="Add.Single.cs" />
+ <Compile Include="Multiply.Double.cs" />
+ <Compile Include="Multiply.Single.cs" />
+ <Compile Include="Program.Avx.cs" />
+ <Compile Include="..\Shared\Program.cs" />
+ <Compile Include="..\Shared\SimpleBinOpTest_DataTable.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void MultiplyDouble()
+ {
+ var test = new SimpleBinaryOpTest__MultiplyDouble();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__MultiplyDouble
+ {
+ private const int VectorSize = 32;
+ private const int ElementCount = VectorSize / sizeof(Double);
+
+ private static Double[] _data1 = new Double[ElementCount];
+ private static Double[] _data2 = new Double[ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Double> _dataTable;
+
+ static SimpleBinaryOpTest__MultiplyDouble()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__MultiplyDouble()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Double>(_data1, _data2, new Double[ElementCount]);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Avx.Multiply(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Avx).GetMethod(nameof(Avx.Multiply), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Avx.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.Multiply(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__MultiplyDouble();
+ var result = Avx.Multiply(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Avx.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> left, Vector256<Double> right, Double[] result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[ElementCount];
+ Double[] inArray2 = new Double[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ if (BitConverter.DoubleToInt64Bits(left[0] * right[0]) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(left[i] * right[i]) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Multiply)}<Double>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void MultiplySingle()
+ {
+ var test = new SimpleBinaryOpTest__MultiplySingle();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__MultiplySingle
+ {
+ private const int VectorSize = 32;
+ private const int ElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data1 = new Single[ElementCount];
+ private static Single[] _data2 = new Single[ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+
+ static SimpleBinaryOpTest__MultiplySingle()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__MultiplySingle()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Single>(_data1, _data2, new Single[ElementCount]);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Avx.Multiply(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Avx).GetMethod(nameof(Avx.Multiply), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Avx.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.Multiply(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__MultiplySingle();
+ var result = Avx.Multiply(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Avx.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> left, Vector256<Single> right, Single[] result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[ElementCount];
+ Single[] inArray2 = new Single[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ if (BitConverter.SingleToInt32Bits(left[0] * right[0]) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(left[i] * right[i]) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Multiply)}<Single>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-//
-
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics.X86;
-using System.Runtime.Intrinsics;
-
-namespace IntelHardwareIntrinsicTest
-{
- class Program
- {
- const int Pass = 100;
- const int Fail = 0;
-
- static unsafe int Main(string[] args)
- {
- int testResult = Pass;
-
- if (Avx.IsSupported)
- {
- using (TestTable<float, float, float> floatTable = new TestTable<float, float, float>(new float[8] { 1, -5, 100, 0, 1, -5, 100, 0 }, new float[8] { 22, -1, -50, 0, 22, -1, -50, 0 }, new float[8]))
- using (TestTable<double, double, double> doubleTable = new TestTable<double, double, double>(new double[4] { 1, -5, 100, 0 }, new double[4] { 22, -1, -50, 0 }, new double[4]))
- {
- var vf1 = Unsafe.Read<Vector256<float>>(floatTable.inArray1Ptr);
- var vf2 = Unsafe.Read<Vector256<float>>(floatTable.inArray2Ptr);
- var vf3 = Avx.Multiply(vf1, vf2);
- Unsafe.Write(floatTable.outArrayPtr, vf3);
-
- var vd1 = Unsafe.Read<Vector256<double>>(doubleTable.inArray1Ptr);
- var vd2 = Unsafe.Read<Vector256<double>>(doubleTable.inArray2Ptr);
- var vd3 = Avx.Multiply(vd1, vd2);
- Unsafe.Write(doubleTable.outArrayPtr, vd3);
-
- if (!floatTable.CheckResult((x, y, z) => x * y == z))
- {
- Console.WriteLine("AVX Multiply failed on float:");
- foreach (var item in floatTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- if (!doubleTable.CheckResult((x, y, z) => x * y == z))
- {
- Console.WriteLine("AVX Multiply failed on double:");
- foreach (var item in doubleTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
- }
- }
- return testResult;
- }
-
- public unsafe struct TestTable<T1, T2, T3> : IDisposable where T1 : struct where T2 : struct where T3 : struct
- {
- public T1[] inArray1;
- public T2[] inArray2;
- public T3[] outArray;
-
- public void* inArray1Ptr => inHandle1.AddrOfPinnedObject().ToPointer();
- public void* inArray2Ptr => inHandle2.AddrOfPinnedObject().ToPointer();
- public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();
-
- GCHandle inHandle1;
- GCHandle inHandle2;
- GCHandle outHandle;
- public TestTable(T1[] a, T2[] b, T3[] c)
- {
- this.inArray1 = a;
- this.inArray2 = b;
- this.outArray = c;
-
- inHandle1 = GCHandle.Alloc(inArray1, GCHandleType.Pinned);
- inHandle2 = GCHandle.Alloc(inArray2, GCHandleType.Pinned);
- outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
- }
- public bool CheckResult(Func<T1, T2, T3, bool> check)
- {
- for (int i = 0; i < inArray1.Length; i++)
- {
- if (!check(inArray1[i], inArray2[i], outArray[i]))
- {
- return false;
- }
- }
- return true;
- }
-
- public void Dispose()
- {
- inHandle1.Free();
- inHandle2.Free();
- outHandle.Free();
- }
- }
-
- }
-}
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
- <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
- <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- </PropertyGroup>
- <!-- Default configurations to help VS understand the configurations -->
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
- <ItemGroup>
- <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
- <Visible>False</Visible>
- </CodeAnalysisDependentAssemblyPaths>
- </ItemGroup>
- <PropertyGroup>
- <DebugType>None</DebugType>
- <Optimize></Optimize>
- </PropertyGroup>
- <ItemGroup>
- <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Multiply.cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
- <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
- <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- </PropertyGroup>
- <!-- Default configurations to help VS understand the configurations -->
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
- <ItemGroup>
- <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
- <Visible>False</Visible>
- </CodeAnalysisDependentAssemblyPaths>
- </ItemGroup>
- <PropertyGroup>
- <DebugType>None</DebugType>
- <Optimize>true</Optimize>
- </PropertyGroup>
- <ItemGroup>
- <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Multiply.cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ static Program()
+ {
+ TestList = new Dictionary<string, Action>() {
+ ["Add.Double"] = AddDouble,
+ ["Add.Single"] = AddSingle,
+ ["Multiply.Double"] = MultiplyDouble,
+ ["Multiply.Single"] = MultiplySingle,
+ };
+ }
+ }
+}
("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "UInt64", "Vector128", "16", "(ulong)(random.Next(0, int.MaxValue))", "(ulong)(left[0] + right[0]) != result[0]", "(ulong)(left[i] + right[i]) != result[i]"}),
};
+private static readonly (string templateFileName, string[] templateData)[] AvxInputs = new []
+{
+ // TemplateName Isa, Method, BaseType, VectorType, VectorSize, NextValue, ValidateFirstResult, ValidateRemainingResults
+ ("SimpleBinOpTest.template", new string[] { "Avx", "Add", "Double", "Vector256", "32", "(double)(random.NextDouble())", "BitConverter.DoubleToInt64Bits(left[0] + right[0]) != BitConverter.DoubleToInt64Bits(result[0])", "BitConverter.DoubleToInt64Bits(left[i] + right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new string[] { "Avx", "Add", "Single", "Vector256", "32", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(left[0] + right[0]) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(left[i] + right[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new string[] { "Avx", "Multiply", "Double", "Vector256", "32", "(double)(random.NextDouble())", "BitConverter.DoubleToInt64Bits(left[0] * right[0]) != BitConverter.DoubleToInt64Bits(result[0])", "BitConverter.DoubleToInt64Bits(left[i] * right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new string[] { "Avx", "Multiply", "Single", "Vector256", "32", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(left[0] * right[0]) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(left[i] * right[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
+};
+
private static void ProcessInputs(string isa, (string templateFileName, string[] templateData)[] inputs)
{
var testListFileName = Path.Combine("..", isa, $"Program.{isa}.cs");
}
ProcessInputs("Sse2", Sse2Inputs);
+ProcessInputs("Avx", AvxInputs);