diff --git a/X10D.Tests/src/Core/IntrinsicTests.cs b/X10D.Tests/src/Core/IntrinsicTests.cs index d0b1485..8e9e8ae 100644 --- a/X10D.Tests/src/Core/IntrinsicTests.cs +++ b/X10D.Tests/src/Core/IntrinsicTests.cs @@ -82,5 +82,33 @@ public class IntrinsicTests Assert.AreEqual(expectedResult, result); } + + [TestMethod] + public void ReverseElements_ShouldReturnExpectedVector128Result_GivenInputVector() + { + var mock = new Mock(); + mock.Setup(provider => provider.IsSupported).Returns(true); + + var inputVector = Vector128.Create(42UL, 69UL); + var expectedResult = Vector128.Create(69UL, 42UL); + + Vector128 result = inputVector.ReverseElementsInternal(mock.Object); + + Assert.AreEqual(expectedResult, result); + } + + [TestMethod] + public void ReverseElements_ShouldReturnExpectedVector128Result_WhenSse2NotSupported() + { + var mock = new Mock(); + mock.Setup(provider => provider.IsSupported).Returns(false); + + var inputVector = Vector128.Create(42UL, 69UL); + var expectedResult = Vector128.Create(69UL, 42UL); + + Vector128 result = inputVector.ReverseElementsInternal(mock.Object); + + Assert.AreEqual(expectedResult, result); + } } #endif diff --git a/X10D/src/Core/IntrinsicExtensions.cs b/X10D/src/Core/IntrinsicExtensions.cs index 5ef9d3c..11832b7 100644 --- a/X10D/src/Core/IntrinsicExtensions.cs +++ b/X10D/src/Core/IntrinsicExtensions.cs @@ -1,4 +1,4 @@ -#if NETCOREAPP3_0_OR_GREATER +#if NETCOREAPP3_0_OR_GREATER using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; @@ -115,19 +115,10 @@ public static class IntrinsicExtensions [Pure] [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + [ExcludeFromCodeCoverage] public static Vector128 ReverseElements(this Vector128 vector) { - if (Sse2.IsSupported) - { - return Sse2.Shuffle(vector.AsDouble(), vector.AsDouble(), 0b01).AsUInt64(); - } - - Vector128 output = IntrinsicUtility.GetUninitializedVector128(); - - Unsafe.As, ulong>(ref output) = Unsafe.Add(ref Unsafe.As, ulong>(ref vector), 1); - Unsafe.Add(ref Unsafe.As, ulong>(ref output), 1) = Unsafe.As, ulong>(ref vector); - - return output; + return ReverseElementsInternal(vector, new SystemSse2SupportProvider()); } [Pure] @@ -182,5 +173,25 @@ public static class IntrinsicExtensions return output; } + + [Pure] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + internal static Vector128 ReverseElementsInternal(this Vector128 vector, ISse2SupportProvider? supportProvider) + { + supportProvider ??= new SystemSse2SupportProvider(); + + if (supportProvider.IsSupported) + { + return Sse2.Shuffle(vector.AsDouble(), vector.AsDouble(), 0b01).AsUInt64(); + } + + Vector128 output = IntrinsicUtility.GetUninitializedVector128(); + + Unsafe.As, ulong>(ref output) = Unsafe.Add(ref Unsafe.As, ulong>(ref vector), 1); + Unsafe.Add(ref Unsafe.As, ulong>(ref output), 1) = Unsafe.As, ulong>(ref vector); + + return output; + } } #endif