("SimpleBinOpTest.template", new string[] { "Sse", "CompareUnorderedScalar", "Single", "Vector128", "16", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(result[0]) != ((float.IsNaN(left[0]) || float.IsNaN(right[0])) ? -1 : 0)", "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
("SimpleBinOpTest.template", new string[] { "Sse", "Divide", "Single", "Vector128", "16", "(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[] { "Sse", "DivideScalar", "Single", "Vector128", "16", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(left[0] / right[0]) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse", "Max", "Single", "Vector128", "16", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(Math.Max(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(Math.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse", "MaxScalar", "Single", "Vector128", "16", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(Math.Max(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse", "Min", "Single", "Vector128", "16", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(Math.Min(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(Math.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse", "MinScalar", "Single", "Vector128", "16", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(Math.Min(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
("SimpleBinOpTest.template", new string[] { "Sse", "Multiply", "Single", "Vector128", "16", "(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[] { "Sse", "MultiplyScalar", "Single", "Vector128", "16", "(float)(random.NextDouble())", "BitConverter.SingleToInt32Bits(left[0] * right[0]) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
("SimpleBinOpTest.template", new string[] { "Sse", "Or", "Single", "Vector128", "16", "(float)(random.NextDouble())", "(BitConverter.SingleToInt32Bits(left[0]) | BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])", "(BitConverter.SingleToInt32Bits(left[0]) | BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])"}),
--- /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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+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 MaxSingle()
+ {
+ var test = new SimpleBinaryOpTest__MaxSingle();
+
+ 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__MaxSingle
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data1 = new Single[ElementCount];
+ private static Single[] _data2 = new Single[ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+
+ static SimpleBinaryOpTest__MaxSingle()
+ {
+ 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<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__MaxSingle()
+ {
+ 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<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<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 => Sse.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse.Max(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse).GetMethod(nameof(Sse.Max), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = Sse.Max(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__MaxSingle();
+ var result = Sse.Max(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse.Max(_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(Vector128<Single> left, Vector128<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(Math.Max(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Math.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse)}.{nameof(Sse.Max)}<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 (Sse.IsSupported)
- {
- using (TestTable<float> floatTable = new TestTable<float>(new float[4] { 1, -5, 100, 0 }, new float[4] { 22, -1, -50, 0 }, new float[4]))
- {
-
- var vf1 = Unsafe.Read<Vector128<float>>(floatTable.inArray1Ptr);
- var vf2 = Unsafe.Read<Vector128<float>>(floatTable.inArray2Ptr);
- var vf3 = Sse.Max(vf1, vf2);
- Unsafe.Write(floatTable.outArrayPtr, vf3);
-
- if (!floatTable.CheckResult((x, y, z) => MathF.Max(x, y) == z))
- {
- Console.WriteLine("SSE Max failed on float:");
- foreach (var item in floatTable.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();
- }
- }
-
- }
-}
--- /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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+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 MaxScalarSingle()
+ {
+ var test = new SimpleBinaryOpTest__MaxScalarSingle();
+
+ 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__MaxScalarSingle
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data1 = new Single[ElementCount];
+ private static Single[] _data2 = new Single[ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+
+ static SimpleBinaryOpTest__MaxScalarSingle()
+ {
+ 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<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__MaxScalarSingle()
+ {
+ 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<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<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 => Sse.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse.MaxScalar(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse).GetMethod(nameof(Sse.MaxScalar), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse.MaxScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = Sse.MaxScalar(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__MaxScalarSingle();
+ var result = Sse.MaxScalar(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse.MaxScalar(_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(Vector128<Single> left, Vector128<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(Math.Max(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse)}.{nameof(Sse.MaxScalar)}<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 (Sse.IsSupported)
- {
- using (TestTable<float> floatTable = new TestTable<float>(new float[4] { 1, -5, 100, 0 }, new float[4] { 22, -1, -50, 3 }, new float[4]))
- {
-
- var vf1 = Unsafe.Read<Vector128<float>>(floatTable.inArray1Ptr);
- var vf2 = Unsafe.Read<Vector128<float>>(floatTable.inArray2Ptr);
- var vf3 = Sse.MaxScalar(vf1, vf2);
- Unsafe.Write(floatTable.outArrayPtr, vf3);
-
- if (!floatTable.CheckResult((x, y, z) => (z[0] == MathF.Max(x[0], y[0])) &&
- (z[1] == x[1]) && (z[2] == x[2]) && (z[3] == x[3])))
- {
- Console.WriteLine("SSE MaxScalar failed on float:");
- foreach (var item in floatTable.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)
- {
- return check(inArray1, inArray2, outArray);
- }
-
- public void Dispose()
- {
- inHandle1.Free();
- inHandle2.Free();
- outHandle.Free();
- }
- }
-
- }
-}
+++ /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="MaxScalar.cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
+++ /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="MaxScalar.cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
+++ /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>{CB11ECA5-6119-4E68-B036-7DFF909291F0}</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="Max.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>{8109234B-3F93-4F71-8968-942201A100E6}</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="Max.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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+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 MinSingle()
+ {
+ var test = new SimpleBinaryOpTest__MinSingle();
+
+ 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__MinSingle
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data1 = new Single[ElementCount];
+ private static Single[] _data2 = new Single[ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+
+ static SimpleBinaryOpTest__MinSingle()
+ {
+ 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<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__MinSingle()
+ {
+ 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<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<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 => Sse.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse.Min(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse).GetMethod(nameof(Sse.Min), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = Sse.Min(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__MinSingle();
+ var result = Sse.Min(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse.Min(_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(Vector128<Single> left, Vector128<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(Math.Min(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Math.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse)}.{nameof(Sse.Min)}<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 (Sse.IsSupported)
- {
- using (TestTable<float> floatTable = new TestTable<float>(new float[4] { 1, -5, 100, 0 }, new float[4] { 22, -1, -50, 0 }, new float[4]))
- {
-
- var vf1 = Unsafe.Read<Vector128<float>>(floatTable.inArray1Ptr);
- var vf2 = Unsafe.Read<Vector128<float>>(floatTable.inArray2Ptr);
- var vf3 = Sse.Min(vf1, vf2);
- Unsafe.Write(floatTable.outArrayPtr, vf3);
-
- if (!floatTable.CheckResult((x, y, z) => MathF.Min(x, y) == z))
- {
- Console.WriteLine("SSE Min failed on float:");
- foreach (var item in floatTable.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();
- }
- }
-
- }
-}
--- /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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+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 MinScalarSingle()
+ {
+ var test = new SimpleBinaryOpTest__MinScalarSingle();
+
+ 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__MinScalarSingle
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data1 = new Single[ElementCount];
+ private static Single[] _data2 = new Single[ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+
+ static SimpleBinaryOpTest__MinScalarSingle()
+ {
+ 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<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__MinScalarSingle()
+ {
+ 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<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<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 => Sse.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse.MinScalar(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse).GetMethod(nameof(Sse.MinScalar), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse.MinScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = Sse.MinScalar(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__MinScalarSingle();
+ var result = Sse.MinScalar(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse.MinScalar(_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(Vector128<Single> left, Vector128<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(Math.Min(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse)}.{nameof(Sse.MinScalar)}<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 (Sse.IsSupported)
- {
- using (TestTable<float> floatTable = new TestTable<float>(new float[4] { 1, -5, 100, 0 }, new float[4] { 22, -1, -50, 3 }, new float[4]))
- {
-
- var vf1 = Unsafe.Read<Vector128<float>>(floatTable.inArray1Ptr);
- var vf2 = Unsafe.Read<Vector128<float>>(floatTable.inArray2Ptr);
- var vf3 = Sse.MinScalar(vf1, vf2);
- Unsafe.Write(floatTable.outArrayPtr, vf3);
-
- if (!floatTable.CheckResult((x, y, z) => (z[0] == MathF.Min(x[0], y[0])) &&
- (z[1] == x[1]) && (z[2] == x[2]) && (z[3] == x[3])))
- {
- Console.WriteLine("SSE MinScalar failed on float:");
- foreach (var item in floatTable.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)
- {
- return check(inArray1, inArray2, outArray);
- }
-
- public void Dispose()
- {
- inHandle1.Free();
- inHandle2.Free();
- outHandle.Free();
- }
- }
-
- }
-}
+++ /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="MinScalar.cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
+++ /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="MinScalar.cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
+++ /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="Min.cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
+++ /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="Min.cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
["CompareUnorderedScalar.Single"] = CompareUnorderedScalarSingle,
["Divide.Single"] = DivideSingle,
["DivideScalar.Single"] = DivideScalarSingle,
+ ["Max.Single"] = MaxSingle,
+ ["MaxScalar.Single"] = MaxScalarSingle,
+ ["Min.Single"] = MinSingle,
+ ["MinScalar.Single"] = MinScalarSingle,
["Multiply.Single"] = MultiplySingle,
["MultiplyScalar.Single"] = MultiplyScalarSingle,
["Or.Single"] = OrSingle,
<Compile Include="CompareUnorderedScalar.Single.cs" />
<Compile Include="Divide.Single.cs" />
<Compile Include="DivideScalar.Single.cs" />
+ <Compile Include="Max.Single.cs" />
+ <Compile Include="MaxScalar.Single.cs" />
+ <Compile Include="Min.Single.cs" />
+ <Compile Include="MinScalar.Single.cs" />
<Compile Include="Multiply.Single.cs" />
<Compile Include="MultiplyScalar.Single.cs" />
<Compile Include="Or.Single.cs" />
<Compile Include="CompareUnorderedScalar.Single.cs" />
<Compile Include="Divide.Single.cs" />
<Compile Include="DivideScalar.Single.cs" />
+ <Compile Include="Max.Single.cs" />
+ <Compile Include="MaxScalar.Single.cs" />
+ <Compile Include="Min.Single.cs" />
+ <Compile Include="MinScalar.Single.cs" />
<Compile Include="Multiply.Single.cs" />
<Compile Include="MultiplyScalar.Single.cs" />
<Compile Include="Or.Single.cs" />