test: bring coverage to 100% for integer Unpack (#70)

This commit is contained in:
Oliver Booth 2023-04-01 21:56:45 +01:00
parent 5f21a2102d
commit 87b6dbdd56
No known key found for this signature in database
GPG Key ID: 20BEB9DC87961025
13 changed files with 390 additions and 149 deletions

View File

@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
@ -7,7 +8,7 @@ namespace X10D.Tests.Collections;
public class ByteTests public class ByteTests
{ {
[TestMethod] [TestMethod]
public void UnpackBits_ShouldUnpackToArrayCorrectly() public void Unpack_ShouldUnpackToArrayCorrectly()
{ {
bool[] bits = ((byte)0b11010100).Unpack(); bool[] bits = ((byte)0b11010100).Unpack();
@ -24,7 +25,7 @@ public class ByteTests
} }
[TestMethod] [TestMethod]
public void UnpackBits_ShouldUnpackToSpanCorrectly() public void Unpack_ShouldUnpackToSpanCorrectly()
{ {
Span<bool> bits = stackalloc bool[8]; Span<bool> bits = stackalloc bool[8];
((byte)0b11010100).Unpack(bits); ((byte)0b11010100).Unpack(bits);
@ -39,14 +40,35 @@ public class ByteTests
Assert.IsTrue(bits[7]); Assert.IsTrue(bits[7]);
} }
#if NET5_0_OR_GREATER
[TestMethod] [TestMethod]
public void UnpackBits_ShouldRepackEqually() public void Unpack_ShouldUnpackToSpanCorrectly_GivenFallbackImplementation()
{
var mock = new Mock<ISsse3SupportProvider>();
mock.Setup(provider => provider.IsSupported).Returns(false);
Span<bool> bits = stackalloc bool[8];
((byte)0b11010100).UnpackInternal(bits, mock.Object);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
}
#endif
[TestMethod]
public void Unpack_ShouldRepackEqually()
{ {
Assert.AreEqual(0b11010100, ((byte)0b11010100).Unpack().PackByte()); Assert.AreEqual(0b11010100, ((byte)0b11010100).Unpack().PackByte());
} }
[TestMethod] [TestMethod]
public void UnpackBits_ShouldThrow_GivenTooSmallSpan() public void Unpack_ShouldThrow_GivenTooSmallSpan()
{ {
Assert.ThrowsException<ArgumentException>(() => Assert.ThrowsException<ArgumentException>(() =>
{ {

View File

@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
@ -7,7 +8,7 @@ namespace X10D.Tests.Collections;
public class Int16Tests public class Int16Tests
{ {
[TestMethod] [TestMethod]
public void UnpackBits_ShouldUnpackToArrayCorrectly() public void Unpack_ShouldUnpackToArrayCorrectly()
{ {
bool[] bits = ((short)0b11010100).Unpack(); bool[] bits = ((short)0b11010100).Unpack();
@ -29,7 +30,7 @@ public class Int16Tests
} }
[TestMethod] [TestMethod]
public void UnpackBits_ShouldUnpackToSpanCorrectly() public void Unpack_ShouldUnpackToSpanCorrectly()
{ {
Span<bool> bits = stackalloc bool[16]; Span<bool> bits = stackalloc bool[16];
((short)0b11010100).Unpack(bits); ((short)0b11010100).Unpack(bits);
@ -49,14 +50,40 @@ public class Int16Tests
} }
} }
#if NET5_0_OR_GREATER
[TestMethod] [TestMethod]
public void UnpackBits_ShouldRepackEqually() public void Unpack_ShouldUnpackToSpanCorrectly_GivenFallbackImplementation()
{
var mock = new Mock<ISsse3SupportProvider>();
mock.Setup(provider => provider.IsSupported).Returns(false);
Span<bool> bits = stackalloc bool[16];
((short)0b11010100).UnpackInternal(bits, mock.Object);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 16; index++)
{
Assert.IsFalse(bits[index]);
}
}
#endif
[TestMethod]
public void Unpack_ShouldRepackEqually()
{ {
Assert.AreEqual(0b11010100, ((short)0b11010100).Unpack().PackInt16()); Assert.AreEqual(0b11010100, ((short)0b11010100).Unpack().PackInt16());
} }
[TestMethod] [TestMethod]
public void UnpackBits_ShouldThrow_GivenTooSmallSpan() public void Unpack_ShouldThrow_GivenTooSmallSpan()
{ {
Assert.ThrowsException<ArgumentException>(() => Assert.ThrowsException<ArgumentException>(() =>
{ {

View File

@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
@ -7,7 +8,7 @@ namespace X10D.Tests.Collections;
public class Int32Tests public class Int32Tests
{ {
[TestMethod] [TestMethod]
public void UnpackBits_ShouldUnpackToArrayCorrectly() public void Unpack_ShouldUnpackToArrayCorrectly()
{ {
bool[] bits = 0b11010100.Unpack(); bool[] bits = 0b11010100.Unpack();
@ -29,7 +30,7 @@ public class Int32Tests
} }
[TestMethod] [TestMethod]
public void UnpackBits_ShouldUnpackToSpanCorrectly() public void Unpack_ShouldUnpackToSpanCorrectly()
{ {
Span<bool> bits = stackalloc bool[32]; Span<bool> bits = stackalloc bool[32];
0b11010100.Unpack(bits); 0b11010100.Unpack(bits);
@ -49,14 +50,69 @@ public class Int32Tests
} }
} }
#if NET5_0_OR_GREATER
[TestMethod] [TestMethod]
public void UnpackBits_ShouldRepackEqually() public void Unpack_ShouldUnpackToSpanCorrectly_GivenFallbackFromAvx2()
{
var ssse3Mock = new Mock<ISsse3SupportProvider>();
var avx2Mock = new Mock<IAvx2SupportProvider>();
avx2Mock.Setup(provider => provider.IsSupported).Returns(false);
ssse3Mock.Setup(provider => provider.IsSupported).Returns(true);
Span<bool> bits = stackalloc bool[32];
0b11010100.UnpackInternal(bits, ssse3Mock.Object, avx2Mock.Object);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 32; index++)
{
Assert.IsFalse(bits[index]);
}
}
[TestMethod]
public void Unpack_ShouldUnpackToSpanCorrectly_GivenFallback()
{
var ssse3Mock = new Mock<ISsse3SupportProvider>();
var avx2Mock = new Mock<IAvx2SupportProvider>();
ssse3Mock.Setup(provider => provider.IsSupported).Returns(false);
avx2Mock.Setup(provider => provider.IsSupported).Returns(false);
Span<bool> bits = stackalloc bool[32];
0b11010100.UnpackInternal(bits, ssse3Mock.Object, avx2Mock.Object);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 32; index++)
{
Assert.IsFalse(bits[index]);
}
}
#endif
[TestMethod]
public void Unpack_ShouldRepackEqually()
{ {
Assert.AreEqual(0b11010100, 0b11010100.Unpack().PackInt32()); Assert.AreEqual(0b11010100, 0b11010100.Unpack().PackInt32());
} }
[TestMethod] [TestMethod]
public void UnpackBits_ShouldThrow_GivenTooSmallSpan() public void Unpack_ShouldThrow_GivenTooSmallSpan()
{ {
Assert.ThrowsException<ArgumentException>(() => Assert.ThrowsException<ArgumentException>(() =>
{ {

View File

@ -1,4 +1,5 @@
using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
#if NETCOREAPP3_0_OR_GREATER #if NETCOREAPP3_0_OR_GREATER
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
@ -33,25 +34,51 @@ public static class ByteExtensions
/// <param name="value">The value to unpack.</param> /// <param name="value">The value to unpack.</param>
/// <param name="destination">When this method returns, contains the unpacked booleans from <paramref name="value" />.</param> /// <param name="destination">When this method returns, contains the unpacked booleans from <paramref name="value" />.</param>
/// <exception cref="ArgumentException"><paramref name="destination" /> is not large enough to contain the result.</exception> /// <exception cref="ArgumentException"><paramref name="destination" /> is not large enough to contain the result.</exception>
[ExcludeFromCodeCoverage]
public static void Unpack(this byte value, Span<bool> destination) public static void Unpack(this byte value, Span<bool> destination)
{ {
if (destination.Length < Size) #if NETCOREAPP3_0_OR_GREATER
{ UnpackInternal(value, destination, new SystemSsse3SupportProvider());
throw new ArgumentException($"Destination must be at least {Size} in length.", nameof(destination)); #else
UnpackInternal(value, destination);
#endif
} }
#if NETCOREAPP3_0_OR_GREATER #if NETCOREAPP3_0_OR_GREATER
if (Ssse3.IsSupported) internal static void UnpackInternal(this byte value, Span<bool> destination, ISsse3SupportProvider? ssse3SupportProvider)
#else
internal static void UnpackInternal(this byte value, Span<bool> destination)
#endif
{ {
Ssse3Implementation(value, destination); if (destination.Length < Size)
{
throw new ArgumentException(ExceptionMessages.DestinationSpanLengthTooShort, nameof(destination));
}
#if NETCOREAPP3_0_OR_GREATER
ssse3SupportProvider ??= new SystemSsse3SupportProvider();
if (ssse3SupportProvider.IsSupported)
{
UnpackInternal_Ssse3(value, destination);
return; return;
} }
#endif #endif
FallbackImplementation(value, destination); UnpackInternal_Fallback(value, destination);
}
private static void UnpackInternal_Fallback(byte value, Span<bool> destination)
{
for (var index = 0; index < Size; index++)
{
destination[index] = (value & (1 << index)) != 0;
}
}
#if NETCOREAPP3_0_OR_GREATER #if NETCOREAPP3_0_OR_GREATER
unsafe static void Ssse3Implementation(byte value, Span<bool> destination)
private unsafe static void UnpackInternal_Ssse3(byte value, Span<bool> destination)
{ {
fixed (bool* pDestination = destination) fixed (bool* pDestination = destination)
{ {
@ -71,12 +98,4 @@ public static class ByteExtensions
} }
} }
#endif #endif
static void FallbackImplementation(byte value, Span<bool> destination)
{
for (var index = 0; index < Size; index++)
{
destination[index] = (value & (1 << index)) != 0;
}
}
}
} }

View File

@ -35,23 +35,56 @@ public static class Int16Extensions
/// <exception cref="ArgumentException"><paramref name="destination" /> is not large enough to contain the result.</exception> /// <exception cref="ArgumentException"><paramref name="destination" /> is not large enough to contain the result.</exception>
public static void Unpack(this short value, Span<bool> destination) public static void Unpack(this short value, Span<bool> destination)
{ {
if (destination.Length < Size) #if NETCOREAPP3_0_OR_GREATER
{ UnpackInternal(value, destination, new SystemSsse3SupportProvider());
throw new ArgumentException($"Destination must be at least {Size} in length.", nameof(destination)); #else
UnpackInternal(value, destination);
#endif
} }
#if NETCOREAPP3_0_OR_GREATER #if NETCOREAPP3_0_OR_GREATER
if (Ssse3.IsSupported) internal static void UnpackInternal(this short value, Span<bool> destination, ISsse3SupportProvider? ssse3SupportProvider)
#else
internal static void UnpackInternal(this short value, Span<bool> destination)
#endif
{ {
Ssse3Implementation(value, destination); if (destination.Length < Size)
{
throw new ArgumentException(ExceptionMessages.DestinationSpanLengthTooShort, nameof(destination));
}
#if NETCOREAPP3_0_OR_GREATER
ssse3SupportProvider ??= new SystemSsse3SupportProvider();
if (ssse3SupportProvider.IsSupported)
{
UnpackInternal_Ssse3(value, destination);
return; return;
} }
#endif #endif
FallbackImplementation(value, destination); UnpackInternal_Fallback(value, destination);
}
private static void UnpackInternal_Fallback(short value, Span<bool> destination)
{
for (var index = 0; index < Size; index++)
{
destination[index] = (value & (1 << index)) != 0;
}
}
#if NETCOREAPP3_0_OR_GREATER #if NETCOREAPP3_0_OR_GREATER
unsafe static void Ssse3Implementation(short value, Span<bool> destination) private struct SystemSsse3SupportProvider : ISsse3SupportProvider
{
/// <inheritdoc />
public bool IsSupported
{
get => Sse3.IsSupported;
}
}
private unsafe static void UnpackInternal_Ssse3(short value, Span<bool> destination)
{ {
fixed (bool* pDestination = destination) fixed (bool* pDestination = destination)
{ {
@ -59,26 +92,18 @@ public static class Int16Extensions
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
); );
var mask1Lo = Vector128.Create((byte)0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1);
var mask1Lo = Vector128.Create((byte)0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1);
var one = Vector128.Create((byte)0x01); var one = Vector128.Create((byte)0x01);
var vec = Vector128.Create(value).AsByte(); Vector128<byte> vec = Vector128.Create(value).AsByte();
var shuffle = Ssse3.Shuffle(vec, mask1Lo); Vector128<byte> shuffle = Ssse3.Shuffle(vec, mask1Lo);
var and = Sse2.AndNot(shuffle, mask2); Vector128<byte> and = Sse2.AndNot(shuffle, mask2);
var cmp = Sse2.CompareEqual(and, Vector128<byte>.Zero); Vector128<byte> cmp = Sse2.CompareEqual(and, Vector128<byte>.Zero);
var correctness = Sse2.And(cmp, one); Vector128<byte> correctness = Sse2.And(cmp, one);
Sse2.Store((byte*)pDestination, correctness); Sse2.Store((byte*)pDestination, correctness);
} }
} }
#endif #endif
static void FallbackImplementation(short value, Span<bool> destination)
{
for (var index = 0; index < Size; index++)
{
destination[index] = (value & (1 << index)) != 0;
}
}
}
} }

View File

@ -1,4 +1,5 @@
using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
#if NETCOREAPP3_0_OR_GREATER #if NETCOREAPP3_0_OR_GREATER
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
@ -33,34 +34,90 @@ public static class Int32Extensions
/// <param name="value">The value to unpack.</param> /// <param name="value">The value to unpack.</param>
/// <param name="destination">When this method returns, contains the unpacked booleans from <paramref name="value" />.</param> /// <param name="destination">When this method returns, contains the unpacked booleans from <paramref name="value" />.</param>
/// <exception cref="ArgumentException"><paramref name="destination" /> is not large enough to contain the result.</exception> /// <exception cref="ArgumentException"><paramref name="destination" /> is not large enough to contain the result.</exception>
[ExcludeFromCodeCoverage]
public static void Unpack(this int value, Span<bool> destination) public static void Unpack(this int value, Span<bool> destination)
{
#if NETCOREAPP3_0_OR_GREATER
UnpackInternal(value, destination, new SystemSsse3SupportProvider(), new SystemAvx2SupportProvider());
#else
UnpackInternal(value, destination);
#endif
}
internal static void UnpackInternal(this int value,
Span<bool> destination
#if NETCOREAPP3_0_OR_GREATER
,
ISsse3SupportProvider? ssse3SupportProvider,
IAvx2SupportProvider? avx2SupportProvider
#endif
)
{ {
if (destination.Length < Size) if (destination.Length < Size)
{ {
throw new ArgumentException($"Destination must be at least {Size} in length.", nameof(destination)); throw new ArgumentException(ExceptionMessages.DestinationSpanLengthTooShort, nameof(destination));
} }
#if NETCOREAPP3_0_OR_GREATER #if NETCOREAPP3_0_OR_GREATER
// TODO: AdvSimd support. ssse3SupportProvider ??= new SystemSsse3SupportProvider();
avx2SupportProvider ??= new SystemAvx2SupportProvider();
// https://stackoverflow.com/questions/24225786/fastest-way-to-unpack-32-bits-to-a-32-byte-simd-vector if (avx2SupportProvider.IsSupported)
if (Avx2.IsSupported)
{ {
Avx2Implementation(value, destination); UnpackInternal_Avx2(value, destination);
return; return;
} }
if (Ssse3.IsSupported) if (ssse3SupportProvider.IsSupported)
{ {
Ssse3Implementation(value, destination); UnpackInternal_Ssse3(value, destination);
return; return;
} }
#endif #endif
FallbackImplementation(value, destination); UnpackInternal_Fallback(value, destination);
}
private static void UnpackInternal_Fallback(int value, Span<bool> destination)
{
for (var index = 0; index < Size; index++)
{
destination[index] = (value & (1 << index)) != 0;
}
}
#if NETCOREAPP3_0_OR_GREATER #if NETCOREAPP3_0_OR_GREATER
unsafe static void Avx2Implementation(int value, Span<bool> destination) private static unsafe void UnpackInternal_Ssse3(int value, Span<bool> destination)
{
fixed (bool* pDestination = destination)
{
var mask2 = Vector128.Create(
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
);
var mask1Lo = Vector128.Create((byte)0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1);
var mask1Hi = Vector128.Create((byte)2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3);
var one = Vector128.Create((byte)0x01);
Vector128<byte> vec = Vector128.Create(value).AsByte();
Vector128<byte> shuffle = Ssse3.Shuffle(vec, mask1Lo);
Vector128<byte> and = Sse2.AndNot(shuffle, mask2);
Vector128<byte> cmp = Sse2.CompareEqual(and, Vector128<byte>.Zero);
Vector128<byte> correctness = Sse2.And(cmp, one);
Sse2.Store((byte*)pDestination, correctness);
shuffle = Ssse3.Shuffle(vec, mask1Hi);
and = Sse2.AndNot(shuffle, mask2);
cmp = Sse2.CompareEqual(and, Vector128<byte>.Zero);
correctness = Sse2.And(cmp, one);
Sse2.Store((byte*)pDestination + 16, correctness);
}
}
private static unsafe void UnpackInternal_Avx2(int value, Span<bool> destination)
{ {
fixed (bool* pDestination = destination) fixed (bool* pDestination = destination)
{ {
@ -77,52 +134,14 @@ public static class Int32Extensions
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
); );
var vec = Vector256.Create(value).AsByte(); Vector256<byte> vec = Vector256.Create(value).AsByte();
var shuffle = Avx2.Shuffle(vec, mask1); Vector256<byte> shuffle = Avx2.Shuffle(vec, mask1);
var and = Avx2.AndNot(shuffle, mask2); Vector256<byte> and = Avx2.AndNot(shuffle, mask2);
var cmp = Avx2.CompareEqual(and, Vector256<byte>.Zero); Vector256<byte> cmp = Avx2.CompareEqual(and, Vector256<byte>.Zero);
var correctness = Avx2.And(cmp, Vector256.Create((byte)0x01)); Vector256<byte> correctness = Avx2.And(cmp, Vector256.Create((byte)0x01));
Avx.Store((byte*)pDestination, correctness); Avx.Store((byte*)pDestination, correctness);
} }
} }
unsafe static void Ssse3Implementation(int value, Span<bool> destination)
{
fixed (bool* pDestination = destination)
{
var mask2 = Vector128.Create(
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
);
var mask1Lo = Vector128.Create((byte)0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1);
var mask1Hi = Vector128.Create((byte)2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3);
var one = Vector128.Create((byte)0x01);
var vec = Vector128.Create(value).AsByte();
var shuffle = Ssse3.Shuffle(vec, mask1Lo);
var and = Sse2.AndNot(shuffle, mask2);
var cmp = Sse2.CompareEqual(and, Vector128<byte>.Zero);
var correctness = Sse2.And(cmp, one);
Sse2.Store((byte*)pDestination, correctness);
shuffle = Ssse3.Shuffle(vec, mask1Hi);
and = Sse2.AndNot(shuffle, mask2);
cmp = Sse2.CompareEqual(and, Vector128<byte>.Zero);
correctness = Sse2.And(cmp, one);
Sse2.Store((byte*)pDestination + 16, correctness);
}
}
#endif #endif
static void FallbackImplementation(int value, Span<bool> destination)
{
for (var index = 0; index < Size; index++)
{
destination[index] = (value & (1 << index)) != 0;
}
}
}
} }

View File

@ -32,7 +32,7 @@ public static class Int64Extensions
{ {
if (destination.Length < Size) if (destination.Length < Size)
{ {
throw new ArgumentException($"Destination must be at least {Size} in length.", nameof(destination)); throw new ArgumentException(ExceptionMessages.DestinationSpanLengthTooShort, nameof(destination));
} }
for (var index = 0; index < Size; index++) for (var index = 0; index < Size; index++)

View File

@ -1,7 +1,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
@ -87,6 +86,15 @@ namespace X10D {
} }
} }
/// <summary>
/// Looks up a localized string similar to The destination span is too short to contain the data..
/// </summary>
internal static string DestinationSpanLengthTooShort {
get {
return ResourceManager.GetString("DestinationSpanLengthTooShort", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to The end index must be less than the list count.. /// Looks up a localized string similar to The end index must be less than the list count..
/// </summary> /// </summary>

View File

@ -123,6 +123,9 @@
<data name="CountMustBeInRange" xml:space="preserve"> <data name="CountMustBeInRange" xml:space="preserve">
<value>Count must be positive and count must refer to a location within the string/array/collection.</value> <value>Count must be positive and count must refer to a location within the string/array/collection.</value>
</data> </data>
<data name="DestinationSpanLengthTooShort" xml:space="preserve">
<value>The destination span is too short to contain the data.</value>
</data>
<data name="EndIndexLessThanStartIndex" xml:space="preserve"> <data name="EndIndexLessThanStartIndex" xml:space="preserve">
<value>The end index must be greater than or equal to the start index.</value> <value>The end index must be greater than or equal to the start index.</value>
</data> </data>

View File

@ -0,0 +1,13 @@
namespace X10D;
/// <summary>
/// Represents an object which provides the status of the support of AVX2 instructions.
/// </summary>
public interface IAvx2SupportProvider
{
/// <summary>
/// Gets a value indicating whether AVX2 instructions are supported on this platform.
/// </summary>
/// <value><see langword="true" /> if AVX2 instructions are supported; otherwise, <see langword="false" />.</value>
bool IsSupported { get; }
}

View File

@ -0,0 +1,13 @@
namespace X10D;
/// <summary>
/// Represents an object which provides the status of the support of SSSE3 instructions.
/// </summary>
public interface ISsse3SupportProvider
{
/// <summary>
/// Gets a value indicating whether SSSE3 instructions are supported on this platform.
/// </summary>
/// <value><see langword="true" /> if SSSE3 instructions are supported; otherwise, <see langword="false" />.</value>
bool IsSupported { get; }
}

View File

@ -0,0 +1,18 @@
#if NETCOREAPP3_0_OR_GREATER
using System.Runtime.Intrinsics.X86;
#endif
namespace X10D;
internal struct SystemAvx2SupportProvider : IAvx2SupportProvider
{
/// <inheritdoc />
public bool IsSupported
{
#if NETCOREAPP3_0_OR_GREATER
get => Avx2.IsSupported;
#else
get => false;
#endif
}
}

View File

@ -0,0 +1,18 @@
#if NETCOREAPP3_0_OR_GREATER
using System.Runtime.Intrinsics.X86;
#endif
namespace X10D;
internal struct SystemSsse3SupportProvider : ISsse3SupportProvider
{
/// <inheritdoc />
public bool IsSupported
{
#if NETCOREAPP3_0_OR_GREATER
get => Sse3.IsSupported;
#else
get => false;
#endif
}
}