if (test.IsSupported)
{
- // Validates basic functionality works
- test.RunBasicScenario();
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
- // Validates calling via reflection works
- test.RunReflectionScenario();
+ if (Sse.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
// Validates passing a static member works
test.RunClsVarScenario();
- // Validates passing a local works
- test.RunLclVarScenario();
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
- // Validates passing the field of a local works
- test.RunLclFldScenario();
+ if (Sse.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
- // Validates passing an instance member works
- test.RunFldScenario();
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
}
else
{
public sealed unsafe class SimpleBinaryOpTest__CompareOrderedSingle
{
- private const int VectorSize = 16;
- private const int ElementCount = VectorSize / sizeof(Single);
+ private struct TestStruct
+ {
+ public Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareOrderedSingle testClass)
+ {
+ var result = Sse.CompareOrdered(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
- private static Single[] _data1 = new Single[ElementCount];
- private static Single[] _data2 = new Single[ElementCount];
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
private static Vector128<Single> _clsVar1;
private static Vector128<Single> _clsVar2;
private Vector128<Single> _fld1;
private Vector128<Single> _fld2;
- private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+ private SimpleBinaryOpTest__DataTable<Single, Single, Single> _dataTable;
static SimpleBinaryOpTest__CompareOrderedSingle()
{
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);
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
}
public SimpleBinaryOpTest__CompareOrderedSingle()
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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
- 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]);
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Single, Single, Single>(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
}
public bool IsSupported => Sse.IsSupported;
public bool Succeeded { get; set; }
- public void RunBasicScenario()
+ public void RunBasicScenario_UnsafeRead()
{
var result = Sse.CompareOrdered(
Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
);
Unsafe.Write(_dataTable.outArrayPtr, result);
- ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
}
- public void RunReflectionScenario()
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse.CompareOrdered(
+ Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse.CompareOrdered(
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)),
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
{
var result = typeof(Sse).GetMethod(nameof(Sse.CompareOrdered), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
.Invoke(null, new object[] {
});
Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
- ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse).GetMethod(nameof(Sse.CompareOrdered), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse).GetMethod(nameof(Sse.CompareOrdered), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)),
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
}
public void RunClsVarScenario()
);
Unsafe.Write(_dataTable.outArrayPtr, result);
- ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
}
- public void RunLclVarScenario()
+ public void RunLclVarScenario_UnsafeRead()
{
var left = Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr);
var right = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
var result = Sse.CompareOrdered(left, right);
Unsafe.Write(_dataTable.outArrayPtr, result);
- ValidateResult(left, right, _dataTable.outArray);
+ ValidateResult(left, right, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = Sse.CompareOrdered(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArrayPtr);
}
- public void RunLclFldScenario()
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr));
+ var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = Sse.CompareOrdered(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
{
var test = new SimpleBinaryOpTest__CompareOrderedSingle();
var result = Sse.CompareOrdered(test._fld1, test._fld2);
Unsafe.Write(_dataTable.outArrayPtr, result);
- ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
}
- public void RunFldScenario()
+ public void RunClassFldScenario()
{
var result = Sse.CompareOrdered(_fld1, _fld2);
Unsafe.Write(_dataTable.outArrayPtr, result);
- ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ var test = TestStruct.Create();
+ var result = Sse.CompareOrdered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
}
public void RunUnsupportedScenario()
try
{
- RunBasicScenario();
+ RunBasicScenario_UnsafeRead();
}
catch (PlatformNotSupportedException)
{
}
}
- private void ValidateResult(Vector128<Single> left, Vector128<Single> right, Single[] result, [CallerMemberName] string method = "")
+ private void ValidateResult(Vector128<Single> left, Vector128<Single> right, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), left);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), right);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "")
{
- Single[] inArray1 = new Single[ElementCount];
- Single[] inArray2 = new Single[ElementCount];
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
- Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
- Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
- ValidateResult(inArray1, inArray2, result, method);
+ ValidateResult(inArray1, inArray2, outArray, method);
}
private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
}
else
{
- for (var i = 1; i < left.Length; i++)
+ for (var i = 1; i < RetElementCount; i++)
{
if (BitConverter.SingleToInt32Bits(result[i]) != ((!float.IsNaN(left[i]) && !float.IsNaN(right[i])) ? -1 : 0))
{
if (!Succeeded)
{
- Console.WriteLine($"{nameof(Sse)}.{nameof(Sse.CompareOrdered)}<Single>: {method} failed:");
+ Console.WriteLine($"{nameof(Sse)}.{nameof(Sse.CompareOrdered)}<Single>(Vector128<Single>, Vector128<Single>): {method} failed:");
Console.WriteLine($" left: ({string.Join(", ", left)})");
Console.WriteLine($" right: ({string.Join(", ", right)})");
Console.WriteLine($" result: ({string.Join(", ", result)})");