mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 19:28:48 +00:00
test: add tests for CorrectBoolean (#73)
This commit is contained in:
parent
34c49a2228
commit
6f16c0df3c
86
X10D.Tests/src/Core/IntrinsicTests.cs
Normal file
86
X10D.Tests/src/Core/IntrinsicTests.cs
Normal file
@ -0,0 +1,86 @@
|
||||
#if NET6_0_OR_GREATER
|
||||
using System.Runtime.Intrinsics;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using X10D.Core;
|
||||
|
||||
namespace X10D.Tests.Core;
|
||||
|
||||
[TestClass]
|
||||
public class IntrinsicTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CorrectBoolean_ShouldReturnExpectedVector64Result_GivenInputVector()
|
||||
{
|
||||
var mock = new Mock<ISse2SupportProvider>();
|
||||
mock.Setup(provider => provider.IsSupported).Returns(true);
|
||||
|
||||
var inputVector = Vector64.Create(0, 1, 2, 0, 3, 0, 0, (byte)4);
|
||||
var expectedResult = Vector64.Create(0, 1, 1, 0, 1, 0, 0, (byte)1);
|
||||
|
||||
Vector64<byte> result = inputVector.CorrectBoolean();
|
||||
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CorrectBoolean_ShouldReturnExpectedVector128Result_GivenInputVector()
|
||||
{
|
||||
var mock = new Mock<ISse2SupportProvider>();
|
||||
mock.Setup(provider => provider.IsSupported).Returns(true);
|
||||
|
||||
var inputVector = Vector128.Create(0, 1, 2, 0, 3, 0, 0, 4, 5, 0, 0, 6, 0, 0, 7, (byte)8);
|
||||
var expectedResult = Vector128.Create(0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, (byte)1);
|
||||
|
||||
Vector128<byte> result = inputVector.CorrectBooleanInternal(mock.Object);
|
||||
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CorrectBoolean_ShouldReturnExpectedVector128Result_WhenSse2NotSupported()
|
||||
{
|
||||
var mock = new Mock<ISse2SupportProvider>();
|
||||
mock.Setup(provider => provider.IsSupported).Returns(false);
|
||||
|
||||
var inputVector = Vector128.Create(0, 1, 2, 0, 3, 0, 0, 4, 5, 0, 0, 6, 0, 0, 7, (byte)8);
|
||||
var expectedResult = Vector128.Create(0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, (byte)1);
|
||||
|
||||
Vector128<byte> result = inputVector.CorrectBooleanInternal(mock.Object);
|
||||
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CorrectBoolean_ShouldReturnExpectedVector256Result_GivenInputVector()
|
||||
{
|
||||
var mock = new Mock<IAvx2SupportProvider>();
|
||||
mock.Setup(provider => provider.IsSupported).Returns(true);
|
||||
|
||||
var inputVector = Vector256.Create(0, 1, 2, 0, 3, 0, 0, 4, 5, 0, 0, 6, 0, 0, 7, 8, 0, 1, 2, 0, 3, 0, 0, 4, 5, 0, 0, 6, 0,
|
||||
0, 7, (byte)8);
|
||||
var expectedResult = Vector256.Create(0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1,
|
||||
0, 0, 1, (byte)1);
|
||||
|
||||
Vector256<byte> result = inputVector.CorrectBooleanInternal(mock.Object);
|
||||
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CorrectBoolean_ShouldReturnExpectedVector256Result_WhenSse2NotSupported()
|
||||
{
|
||||
var mock = new Mock<IAvx2SupportProvider>();
|
||||
mock.Setup(provider => provider.IsSupported).Returns(false);
|
||||
|
||||
var inputVector = Vector256.Create(0, 1, 2, 0, 3, 0, 0, 4, 5, 0, 0, 6, 0, 0, 7, 8, 0, 1, 2, 0, 3, 0, 0, 4, 5, 0, 0, 6, 0,
|
||||
0, 7, (byte)8);
|
||||
var expectedResult = Vector256.Create(0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1,
|
||||
0, 0, 1, (byte)1);
|
||||
|
||||
Vector256<byte> result = inputVector.CorrectBooleanInternal(mock.Object);
|
||||
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
#if NETCOREAPP3_0_OR_GREATER
|
||||
|
||||
#if NETCOREAPP3_0_OR_GREATER
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
@ -35,15 +35,15 @@ public static class IntrinsicExtensions
|
||||
// TODO: AdvSimd implementation.
|
||||
// TODO: WasmSimd implementation. (?)
|
||||
|
||||
var output = IntrinsicUtility.GetUninitializedVector64<byte>();
|
||||
Vector64<byte> output = IntrinsicUtility.GetUninitializedVector64<byte>();
|
||||
|
||||
for (int i = 0; i < Vector64<byte>.Count; i++)
|
||||
for (var i = 0; i < Vector64<byte>.Count; i++)
|
||||
{
|
||||
ref var writeElement = ref Unsafe.Add(ref Unsafe.As<Vector64<byte>, byte>(ref output), i);
|
||||
ref byte writeElement = ref Unsafe.Add(ref Unsafe.As<Vector64<byte>, byte>(ref output), i);
|
||||
#if NET7_0_OR_GREATER
|
||||
writeElement = vector[i] == 0 ? (byte)0 : (byte)1;
|
||||
#else
|
||||
var element = Unsafe.Add(ref Unsafe.As<Vector64<byte>, byte>(ref vector), i);
|
||||
byte element = Unsafe.Add(ref Unsafe.As<Vector64<byte>, byte>(ref vector), i);
|
||||
writeElement = element == 0 ? (byte)0 : (byte)1;
|
||||
#endif
|
||||
}
|
||||
@ -68,28 +68,10 @@ public static class IntrinsicExtensions
|
||||
/// </returns>
|
||||
[Pure]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public static Vector128<byte> CorrectBoolean(this Vector128<byte> vector)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
var cmp = Sse2.CompareEqual(vector, Vector128<byte>.Zero);
|
||||
var result = Sse2.AndNot(cmp, Vector128.Create((byte)1));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: AdvSimd implementation.
|
||||
// TODO: WasmSimd implementation.
|
||||
|
||||
var output = IntrinsicUtility.GetUninitializedVector128<byte>();
|
||||
|
||||
for (int i = 0; i < Vector128<byte>.Count; i++)
|
||||
{
|
||||
Unsafe.Add(ref Unsafe.As<Vector128<byte>, byte>(ref output), i) =
|
||||
Unsafe.Add(ref Unsafe.As<Vector128<byte>, byte>(ref vector), i) == 0 ? (byte)0 : (byte)1;
|
||||
}
|
||||
|
||||
return output;
|
||||
return CorrectBooleanInternal(vector, new SystemSse2SupportProvider());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -109,25 +91,10 @@ public static class IntrinsicExtensions
|
||||
/// </returns>
|
||||
[Pure]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public static Vector256<byte> CorrectBoolean(this Vector256<byte> vector)
|
||||
{
|
||||
if (Avx2.IsSupported)
|
||||
{
|
||||
var cmp = Avx2.CompareEqual(vector, Vector256<byte>.Zero);
|
||||
var result = Avx2.AndNot(cmp, Vector256.Create((byte)1));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var output = IntrinsicUtility.GetUninitializedVector256<byte>();
|
||||
|
||||
for (int i = 0; i < Vector256<byte>.Count; i++)
|
||||
{
|
||||
Unsafe.Add(ref Unsafe.As<Vector256<byte>, byte>(ref output), i) =
|
||||
Unsafe.Add(ref Unsafe.As<Vector256<byte>, byte>(ref vector), i) == 0 ? (byte)0 : (byte)1;
|
||||
}
|
||||
|
||||
return output;
|
||||
return CorrectBooleanInternal(vector, new SystemAvx2SupportProvider());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -162,5 +129,58 @@ public static class IntrinsicExtensions
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
internal static Vector128<byte> CorrectBooleanInternal(this Vector128<byte> vector, ISse2SupportProvider? sse2SupportProvider)
|
||||
{
|
||||
sse2SupportProvider ??= new SystemSse2SupportProvider();
|
||||
|
||||
if (sse2SupportProvider.IsSupported)
|
||||
{
|
||||
Vector128<byte> cmp = Sse2.CompareEqual(vector, Vector128<byte>.Zero);
|
||||
Vector128<byte> result = Sse2.AndNot(cmp, Vector128.Create((byte)1));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: AdvSimd implementation.
|
||||
// TODO: WasmSimd implementation.
|
||||
|
||||
Vector128<byte> output = IntrinsicUtility.GetUninitializedVector128<byte>();
|
||||
|
||||
for (var index = 0; index < Vector128<byte>.Count; index++)
|
||||
{
|
||||
Unsafe.Add(ref Unsafe.As<Vector128<byte>, byte>(ref output), index) =
|
||||
Unsafe.Add(ref Unsafe.As<Vector128<byte>, byte>(ref vector), index) == 0 ? (byte)0 : (byte)1;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
internal static Vector256<byte> CorrectBooleanInternal(this Vector256<byte> vector, IAvx2SupportProvider? supportProvider)
|
||||
{
|
||||
supportProvider ??= new SystemAvx2SupportProvider();
|
||||
|
||||
if (supportProvider.IsSupported)
|
||||
{
|
||||
Vector256<byte> cmp = Avx2.CompareEqual(vector, Vector256<byte>.Zero);
|
||||
Vector256<byte> result = Avx2.AndNot(cmp, Vector256.Create((byte)1));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector256<byte> output = IntrinsicUtility.GetUninitializedVector256<byte>();
|
||||
|
||||
for (var index = 0; index < Vector256<byte>.Count; index++)
|
||||
{
|
||||
Unsafe.Add(ref Unsafe.As<Vector256<byte>, byte>(ref output), index) =
|
||||
Unsafe.Add(ref Unsafe.As<Vector256<byte>, byte>(ref vector), index) == 0 ? (byte)0 : (byte)1;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -3,7 +3,6 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace X10D.Core;
|
||||
|
13
X10D/src/ISse2SupportProvider.cs
Normal file
13
X10D/src/ISse2SupportProvider.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace X10D;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an object which provides the status of the support of SSE2 instructions.
|
||||
/// </summary>
|
||||
public interface ISse2SupportProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether SSE2 instructions are supported on this platform.
|
||||
/// </summary>
|
||||
/// <value><see langword="true" /> if SSE2 instructions are supported; otherwise, <see langword="false" />.</value>
|
||||
bool IsSupported { get; }
|
||||
}
|
18
X10D/src/SystemSse2SupportProvider.cs
Normal file
18
X10D/src/SystemSse2SupportProvider.cs
Normal file
@ -0,0 +1,18 @@
|
||||
#if NETCOREAPP3_0_OR_GREATER
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
#endif
|
||||
|
||||
namespace X10D;
|
||||
|
||||
internal struct SystemSse2SupportProvider : ISse2SupportProvider
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public bool IsSupported
|
||||
{
|
||||
#if NETCOREAPP3_0_OR_GREATER
|
||||
get => Sse2.IsSupported;
|
||||
#else
|
||||
get => false;
|
||||
#endif
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user