mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-23 01:18:46 +00:00
Add Pack/Unpack bits
Allows a bool list (no more than 64 in length) to be packed to an integer, which can be unpacked again
This commit is contained in:
parent
b743adb445
commit
e08274189a
56
X10D.Tests/src/Collections/BoolListTests.cs
Normal file
56
X10D.Tests/src/Collections/BoolListTests.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using X10D.Collections;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Collections;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class BoolListTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void Pack8Bit_Should_Pack_Correctly()
|
||||||
|
{
|
||||||
|
var array = new[] {true, false, true, false, true, false, true, false};
|
||||||
|
Assert.AreEqual(85, array.Pack8Bit()); // 01010101
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Pack16Bit_Should_Pack_Correctly()
|
||||||
|
{
|
||||||
|
var array = new[] {true, false, true, false, true, false, true, false, true, true, false, true};
|
||||||
|
Assert.AreEqual(2901, array.Pack16Bit()); // 101101010101
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Pack32Bit_Should_Pack_Correctly()
|
||||||
|
{
|
||||||
|
var array = new[] {true, false, true, false, true, false, true, false, true, true, false, true};
|
||||||
|
Assert.AreEqual(2901, array.Pack32Bit()); // 101101010101
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Pack64Bit_Should_Pack_Correctly()
|
||||||
|
{
|
||||||
|
var array = new[] {true, false, true, false, true, false, true, false, true, true, false, true};
|
||||||
|
Assert.AreEqual(2901, array.Pack64Bit()); // 101101010101
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Pack_ShouldThrow_GivenLargeArray()
|
||||||
|
{
|
||||||
|
bool[] array = Enumerable.Repeat(false, 65).ToArray();
|
||||||
|
Assert.ThrowsException<ArgumentException>(() => array.Pack8Bit());
|
||||||
|
Assert.ThrowsException<ArgumentException>(() => array.Pack16Bit());
|
||||||
|
Assert.ThrowsException<ArgumentException>(() => array.Pack32Bit());
|
||||||
|
Assert.ThrowsException<ArgumentException>(() => array.Pack64Bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Pack_ShouldThrow_GivenNull()
|
||||||
|
{
|
||||||
|
bool[]? array = null;
|
||||||
|
Assert.ThrowsException<ArgumentNullException>(() => array!.Pack8Bit());
|
||||||
|
Assert.ThrowsException<ArgumentNullException>(() => array!.Pack16Bit());
|
||||||
|
Assert.ThrowsException<ArgumentNullException>(() => array!.Pack32Bit());
|
||||||
|
Assert.ThrowsException<ArgumentNullException>(() => array!.Pack64Bit());
|
||||||
|
}
|
||||||
|
}
|
57
X10D.Tests/src/Collections/ByteTests.cs
Normal file
57
X10D.Tests/src/Collections/ByteTests.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using X10D.Collections;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Collections;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class ByteTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldUnpackToArrayCorrectly()
|
||||||
|
{
|
||||||
|
bool[] bits = ((byte)0b11010100).UnpackBits();
|
||||||
|
|
||||||
|
Assert.AreEqual(8, bits.Length);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldUnpackToSpanCorrectly()
|
||||||
|
{
|
||||||
|
Span<bool> bits = stackalloc bool[8];
|
||||||
|
((byte)0b11010100).UnpackBits(bits);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldRepackEqually()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(0b11010100, ((byte)0b11010100).UnpackBits().Pack8Bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldThrow_GivenTooSmallSpan()
|
||||||
|
{
|
||||||
|
Assert.ThrowsException<ArgumentException>(() =>
|
||||||
|
{
|
||||||
|
Span<bool> bits = stackalloc bool[0];
|
||||||
|
((byte)0b11010100).UnpackBits(bits);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
67
X10D.Tests/src/Collections/Int16Tests.cs
Normal file
67
X10D.Tests/src/Collections/Int16Tests.cs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using X10D.Collections;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Collections;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class Int16Tests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldUnpackToArrayCorrectly()
|
||||||
|
{
|
||||||
|
bool[] bits = ((short)0b11010100).UnpackBits();
|
||||||
|
|
||||||
|
Assert.AreEqual(16, bits.Length);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldUnpackToSpanCorrectly()
|
||||||
|
{
|
||||||
|
Span<bool> bits = stackalloc bool[16];
|
||||||
|
((short)0b11010100).UnpackBits(bits);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldRepackEqually()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(0b11010100, ((short)0b11010100).UnpackBits().Pack16Bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldThrow_GivenTooSmallSpan()
|
||||||
|
{
|
||||||
|
Assert.ThrowsException<ArgumentException>(() =>
|
||||||
|
{
|
||||||
|
Span<bool> bits = stackalloc bool[0];
|
||||||
|
((short)0b11010100).UnpackBits(bits);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
67
X10D.Tests/src/Collections/Int32Tests.cs
Normal file
67
X10D.Tests/src/Collections/Int32Tests.cs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using X10D.Collections;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Collections;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class Int32Tests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldUnpackToArrayCorrectly()
|
||||||
|
{
|
||||||
|
bool[] bits = 0b11010100.UnpackBits();
|
||||||
|
|
||||||
|
Assert.AreEqual(32, bits.Length);
|
||||||
|
|
||||||
|
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 UnpackBits_ShouldUnpackToSpanCorrectly()
|
||||||
|
{
|
||||||
|
Span<bool> bits = stackalloc bool[32];
|
||||||
|
0b11010100.UnpackBits(bits);
|
||||||
|
|
||||||
|
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 UnpackBits_ShouldRepackEqually()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(0b11010100, 0b11010100.UnpackBits().Pack32Bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldThrow_GivenTooSmallSpan()
|
||||||
|
{
|
||||||
|
Assert.ThrowsException<ArgumentException>(() =>
|
||||||
|
{
|
||||||
|
Span<bool> bits = stackalloc bool[0];
|
||||||
|
0b11010100.UnpackBits(bits);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
72
X10D.Tests/src/Collections/Int64Tests.cs
Normal file
72
X10D.Tests/src/Collections/Int64Tests.cs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using X10D.Collections;
|
||||||
|
using X10D.Linq;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Collections;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class Int64Tests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldUnpackToArrayCorrectly()
|
||||||
|
{
|
||||||
|
bool[] bits = 0b11010100L.UnpackBits();
|
||||||
|
|
||||||
|
Assert.AreEqual(64, bits.Length);
|
||||||
|
|
||||||
|
Trace.WriteLine(Convert.ToString(0b11010100L, 2));
|
||||||
|
Trace.WriteLine(string.Join("", bits.Select(b => b ? "1" : "0")));
|
||||||
|
|
||||||
|
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 < 64; index++)
|
||||||
|
{
|
||||||
|
Assert.IsFalse(bits[index], index.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldUnpackToSpanCorrectly()
|
||||||
|
{
|
||||||
|
Span<bool> bits = stackalloc bool[64];
|
||||||
|
0b11010100L.UnpackBits(bits);
|
||||||
|
|
||||||
|
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 < 64; index++)
|
||||||
|
{
|
||||||
|
Assert.IsFalse(bits[index], index.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldRepackEqually()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(0b11010100L, 0b11010100L.UnpackBits().Pack64Bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnpackBits_ShouldThrow_GivenTooSmallSpan()
|
||||||
|
{
|
||||||
|
Assert.ThrowsException<ArgumentException>(() =>
|
||||||
|
{
|
||||||
|
Span<bool> bits = stackalloc bool[0];
|
||||||
|
0b11010100L.UnpackBits(bits);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
123
X10D/src/Collections/BoolListExtensions.cs
Normal file
123
X10D/src/Collections/BoolListExtensions.cs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
namespace X10D.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collection-related extension methods for <see cref="IReadOnlyList{T}" /> of <see cref="bool" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class BoolListExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Packs a collection of booleans into a <see cref="byte" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The collection of booleans to pack.</param>
|
||||||
|
/// <returns>An 8-bit unsigned integer containing the packed booleans.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="source" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ArgumentException"><paramref name="source" /> contains more than 8 elements.</exception>
|
||||||
|
/// <author>Alpha Anar</author>
|
||||||
|
public static byte Pack8Bit(this IReadOnlyList<bool> source)
|
||||||
|
{
|
||||||
|
if (source is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.Count > 8)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Source cannot contain more than than 8 elements.", nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (bool* p = source.ToArray())
|
||||||
|
{
|
||||||
|
return (byte)(*(ulong*)p * 72624976668147840L >> 56); // evil fucking bit hack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Packs a collection of booleans into a <see cref="short" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The collection of booleans to pack.</param>
|
||||||
|
/// <returns>A 16-bit signed integer containing the packed booleans.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="source" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ArgumentException"><paramref name="source" /> contains more than 16 elements.</exception>
|
||||||
|
public static short Pack16Bit(this IReadOnlyList<bool> source)
|
||||||
|
{
|
||||||
|
if (source is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.Count > 16)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Source cannot contain more than than 16 elements.", nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
short result = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < source.Count; i++)
|
||||||
|
{
|
||||||
|
result |= (short)(source[i] ? 1 << i : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Packs a collection of booleans into a <see cref="int" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The collection of booleans to pack.</param>
|
||||||
|
/// <returns>A 32-bit signed integer containing the packed booleans.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="source" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ArgumentException"><paramref name="source" /> contains more than 32 elements.</exception>
|
||||||
|
public static int Pack32Bit(this IReadOnlyList<bool> source)
|
||||||
|
{
|
||||||
|
if (source is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.Count > 32)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Source cannot contain more than than 32 elements.", nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < source.Count; i++)
|
||||||
|
{
|
||||||
|
result |= source[i] ? 1 << i : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Packs a collection of booleans into a <see cref="long" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The collection of booleans to pack.</param>
|
||||||
|
/// <returns>A 64-bit signed integer containing the packed booleans.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="source" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ArgumentException"><paramref name="source" /> contains more than 64 elements.</exception>
|
||||||
|
public static long Pack64Bit(this IReadOnlyList<bool> source)
|
||||||
|
{
|
||||||
|
if (source is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.Count > 64)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Source cannot contain more than than 64 elements.", nameof(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = 0L;
|
||||||
|
|
||||||
|
for (var i = 0; i < source.Count; i++)
|
||||||
|
{
|
||||||
|
result |= source[i] ? 1L << i : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
44
X10D/src/Collections/ByteExtensions.cs
Normal file
44
X10D/src/Collections/ByteExtensions.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
namespace X10D.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collection-related extension methods for <see cref="byte" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class ByteExtensions
|
||||||
|
{
|
||||||
|
private const int Size = sizeof(byte) * 8;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this 8-bit unsigned integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</param>
|
||||||
|
/// <returns>An array of <see cref="bool" /> with length 8.</returns>
|
||||||
|
public static bool[] UnpackBits(this byte value)
|
||||||
|
{
|
||||||
|
Span<bool> buffer = stackalloc bool[Size];
|
||||||
|
value.UnpackBits(buffer);
|
||||||
|
return buffer.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this 8-bit unsigned integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</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>
|
||||||
|
/// <author>Alpha Anar</author>
|
||||||
|
public static void UnpackBits(this byte value, Span<bool> destination)
|
||||||
|
{
|
||||||
|
if (destination.Length < Size)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Destination must be at least {Size} in length.", nameof(destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (bool* p = destination)
|
||||||
|
{
|
||||||
|
*(ulong*)p = ((ulong)value * 567382630219905) & 72340172838076673UL; // evil fucking bit hack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
X10D/src/Collections/Int16Extensions.cs
Normal file
40
X10D/src/Collections/Int16Extensions.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
namespace X10D.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collection-related extension methods for <see cref="short" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class Int16Extensions
|
||||||
|
{
|
||||||
|
private const int Size = sizeof(short) * 8;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this 16-bit signed integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</param>
|
||||||
|
/// <returns>An array of <see cref="bool" /> with length 16.</returns>
|
||||||
|
public static bool[] UnpackBits(this short value)
|
||||||
|
{
|
||||||
|
Span<bool> buffer = stackalloc bool[Size];
|
||||||
|
value.UnpackBits(buffer);
|
||||||
|
return buffer.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this 16-bit signed integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</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>
|
||||||
|
public static void UnpackBits(this short value, Span<bool> destination)
|
||||||
|
{
|
||||||
|
if (destination.Length < Size)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Destination must be at least {Size} in length.", nameof(destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var index = 0; index < Size; index++)
|
||||||
|
{
|
||||||
|
destination[index] = (value & (1 << index)) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
X10D/src/Collections/Int32Extensions.cs
Normal file
40
X10D/src/Collections/Int32Extensions.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
namespace X10D.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collection-related extension methods for <see cref="int" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class Int32Extensions
|
||||||
|
{
|
||||||
|
private const int Size = sizeof(int) * 8;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this 32-bit signed integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</param>
|
||||||
|
/// <returns>An array of <see cref="bool" /> with length 32.</returns>
|
||||||
|
public static bool[] UnpackBits(this int value)
|
||||||
|
{
|
||||||
|
Span<bool> buffer = stackalloc bool[Size];
|
||||||
|
value.UnpackBits(buffer);
|
||||||
|
return buffer.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this 32-bit signed integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</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>
|
||||||
|
public static void UnpackBits(this int value, Span<bool> destination)
|
||||||
|
{
|
||||||
|
if (destination.Length < Size)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Destination must be at least {Size} in length.", nameof(destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var index = 0; index < Size; index++)
|
||||||
|
{
|
||||||
|
destination[index] = (value & (1 << index)) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
X10D/src/Collections/Int64Extensions.cs
Normal file
40
X10D/src/Collections/Int64Extensions.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
namespace X10D.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collection-related extension methods for <see cref="long" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class Int64Extensions
|
||||||
|
{
|
||||||
|
private const int Size = sizeof(long) * 8;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this 64-bit signed integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</param>
|
||||||
|
/// <returns>An array of <see cref="bool" /> with length 64.</returns>
|
||||||
|
public static bool[] UnpackBits(this long value)
|
||||||
|
{
|
||||||
|
Span<bool> buffer = stackalloc bool[Size];
|
||||||
|
value.UnpackBits(buffer);
|
||||||
|
return buffer.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this 64-bit signed integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</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>
|
||||||
|
public static void UnpackBits(this long value, Span<bool> destination)
|
||||||
|
{
|
||||||
|
if (destination.Length < Size)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Destination must be at least {Size} in length.", nameof(destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var index = 0; index < Size; index++)
|
||||||
|
{
|
||||||
|
destination[index] = (value & (1L << index)) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user