From b32f89aa4fa0fd2be9cf40319ff6aa23e2b93ea6 Mon Sep 17 00:00:00 2001 From: DdeadliestT <93347396+DdeadliestT@users.noreply.github.com> Date: Fri, 2 Jun 2023 20:44:21 +0000 Subject: [PATCH 1/2] Update Bit[T].cs Replaced 32 with BitsSize --- csharp/Platform.Numbers/Bit[T].cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/csharp/Platform.Numbers/Bit[T].cs b/csharp/Platform.Numbers/Bit[T].cs index 8e8b752..ec6ee07 100644 --- a/csharp/Platform.Numbers/Bit[T].cs +++ b/csharp/Platform.Numbers/Bit[T].cs @@ -26,11 +26,11 @@ public static T PartialWrite(T target, T source, int shift, int limit) { if (shift < 0) { - shift = 32 + shift; + shift = BitsSize + shift; } if (limit < 0) { - limit = 32 + limit; + limit = BitsSize + limit; } var sourceMask = ~(T.MaxValue << limit) & T.MaxValue; var targetMask = ~(sourceMask << shift); @@ -40,11 +40,11 @@ public static T PartialRead(T target, int shift, int limit) { if (shift < 0) { - shift = 32 + shift; + shift = BitsSize + shift; } if (limit < 0) { - limit = 32 + limit; + limit = BitsSize + limit; } var sourceMask = ~(T.MaxValue << limit) & T.MaxValue; var targetMask = sourceMask << shift; From d2441b77a6cabc57f66a4e96c300a947afff11c3 Mon Sep 17 00:00:00 2001 From: DdeadliestT <93347396+DdeadliestT@users.noreply.github.com> Date: Sun, 4 Jun 2023 18:44:07 +0000 Subject: [PATCH 2/2] Update BitTests.cs Add tests for long --- csharp/Platform.Numbers.Tests/BitTests.cs | 179 +++++++++++++++++++++- 1 file changed, 171 insertions(+), 8 deletions(-) diff --git a/csharp/Platform.Numbers.Tests/BitTests.cs b/csharp/Platform.Numbers.Tests/BitTests.cs index 3a3079b..607b199 100644 --- a/csharp/Platform.Numbers.Tests/BitTests.cs +++ b/csharp/Platform.Numbers.Tests/BitTests.cs @@ -11,13 +11,13 @@ public static class BitTests [InlineData(01, 00)] // 0000 0001 (first, 0) [InlineData(08, 03)] // 0000 1000 (forth, 3) [InlineData(88, 03)] // 0101 1000 (forth, 3) - public static void GetLowestBitPositionTest(ulong value, int expectedPosition) + public static void GetLowestBitPositionTestForUint(uint value, int expectedPosition) { Assert.True(Bit.GetLowestPosition(value) == expectedPosition); } [Fact] - public static void PartialReadWriteTest() + public static void PartialReadWriteTestForUint() { { uint firstValue = 1; @@ -87,10 +87,10 @@ public static void PartialReadWriteTest() Assert.True(secondValue == unpackagedSecondValue); // Using universal functions: - var readMasksAndShiftFor0And1 = GetReadMaskAndShift(0, 1); - var readMasksAndShiftFor1AndMinus1 = GetReadMaskAndShift(1, -1); - var writeMasksAndShiftFor0And1 = GetWriteMasksAndShift(0, 1); - var writeMasksAndShiftFor1AndMinus1 = GetWriteMasksAndShift(1, -1); + var readMasksAndShiftFor0And1 = GetReadMaskAndShiftForUint(0, 1); + var readMasksAndShiftFor1AndMinus1 = GetReadMaskAndShiftForUint(1, -1); + var writeMasksAndShiftFor0And1 = GetWriteMasksAndShiftForUint(0, 1); + var writeMasksAndShiftFor1AndMinus1 = GetWriteMasksAndShiftForUint(1, -1); Assert.True(PartialRead(value, readMasksAndShiftFor0And1) == firstValue); Assert.True(PartialRead(value, readMasksAndShiftFor1AndMinus1) == secondValue); @@ -135,7 +135,7 @@ private static uint PartialRead(uint target, int shift, int limit) var targetMask = sourceMask << shift; return (target & targetMask) >> shift; } - private static Tuple GetWriteMasksAndShift(int shift, int limit) + private static Tuple GetWriteMasksAndShiftForUint(int shift, int limit) { if (shift < 0) { @@ -149,7 +149,7 @@ private static Tuple GetWriteMasksAndShift(int shift, int limit var targetMask = ~(sourceMask << shift); return new Tuple(targetMask, sourceMask, shift); } - private static Tuple GetReadMaskAndShift(int shift, int limit) + private static Tuple GetReadMaskAndShiftForUint(int shift, int limit) { if (shift < 0) { @@ -173,5 +173,168 @@ public static void BugWithLoadingConstantOf8Test() { Bit.PartialWrite(0, 1, 5, -5); } + + // TESTS FOR ULONG + [Theory] + [InlineData(00, -1)] // 0000 0000 (none, -1) + [InlineData(01, 00)] // 0000 0001 (first, 0) + [InlineData(08, 03)] // 0000 1000 (forth, 3) + [InlineData(88, 03)] // 0101 1000 (forth, 3) + public static void GetLowestBitPositionTestForUlong(ulong value, int expectedPosition) + { + Assert.True(Bit.GetLowestPosition(value) == expectedPosition); + } + + [Fact] + public static void PartialReadWriteTestForUlong() + { + { + ulong firstValue = 1; + ulong secondValue = 1543; + + // Pack (join) two values at the same time + ulong value = secondValue << 1 | firstValue; + + ulong unpackagedFirstValue = value & 1; + ulong unpackagedSecondValue = (value & 0xFFFFFFFE) >> 1; + + Assert.True(firstValue == unpackagedFirstValue); + Assert.True(secondValue == unpackagedSecondValue); + + // Using universal functions: + Assert.True(PartialRead(value, 0, 1) == firstValue); + Assert.True(PartialRead(value, 1, -1) == secondValue); + + firstValue = 0; + secondValue = 6892; + + value = PartialWrite(value, firstValue, 0, 1); + value = PartialWrite(value, secondValue, 1, -1); + + Assert.True(PartialRead(value, 0, 1) == firstValue); + Assert.True(PartialRead(value, 1, -1) == secondValue); + } + + { + ulong firstValue = 1; + ulong secondValue = 1543; + + // Pack (join) two values at the same time + ulong value = secondValue << 1 | firstValue; + + ulong unpackagedFirstValue = value & 1; + ulong unpackagedSecondValue = (value & 0xFFFFFFFE) >> 1; + + Assert.True(firstValue == unpackagedFirstValue); + Assert.True(secondValue == unpackagedSecondValue); + + // Using universal functions: + Assert.True(Bit.PartialRead(value, 0, 1) == firstValue); + Assert.True(Bit.PartialRead(value, 1, -1) == secondValue); + + firstValue = 0; + secondValue = 6892; + + value = Bit.PartialWrite(value, firstValue, 0, 1); + value = Bit.PartialWrite(value, secondValue, 1, -1); + + Assert.True(Bit.PartialRead(value, 0, 1) == firstValue); + Assert.True(Bit.PartialRead(value, 1, -1) == secondValue); + } + + { + ulong firstValue = 1; + ulong secondValue = 1543; + + // Pack (join) two values at the same time + ulong value = secondValue << 1 | firstValue; + + ulong unpackagedFirstValue = value & 1; + ulong unpackagedSecondValue = (value & 0xFFFFFFFE) >> 1; + + Assert.True(firstValue == unpackagedFirstValue); + Assert.True(secondValue == unpackagedSecondValue); + + // Using universal functions: + var readMasksAndShiftFor0And1 = GetReadMaskAndShiftForUlong(0, 1); + var readMasksAndShiftFor1AndMinus1 = GetReadMaskAndShiftForUlong(1, -1); + var writeMasksAndShiftFor0And1 = GetWriteMasksAndShiftForUlong(0, 1); + var writeMasksAndShiftFor1AndMinus1 = GetWriteMasksAndShiftForUlong(1, -1); + + Assert.True(PartialRead(value, readMasksAndShiftFor0And1) == firstValue); + Assert.True(PartialRead(value, readMasksAndShiftFor1AndMinus1) == secondValue); + + firstValue = 0; + secondValue = 6892; + + value = PartialWrite(value, firstValue, writeMasksAndShiftFor0And1); + value = PartialWrite(value, secondValue, writeMasksAndShiftFor1AndMinus1); + + Assert.True(PartialRead(value, readMasksAndShiftFor0And1) == firstValue); + Assert.True(PartialRead(value, readMasksAndShiftFor1AndMinus1) == secondValue); + } + } + + // TODO: Can be optimized using precalculation of TargetMask and SourceMask + private static ulong PartialWrite(ulong target, ulong source, int shift, int limit) + { + if (shift < 0) + { + shift = 64 + shift; + } + if (limit < 0) + { + limit = 64 + limit; + } + var sourceMask = ~(ulong.MaxValue << limit) & ulong.MaxValue; + var targetMask = ~(sourceMask << shift); + return target & targetMask | (source & sourceMask) << shift; + } + private static ulong PartialRead(ulong target, int shift, int limit) + { + if (shift < 0) + { + shift = 64 + shift; + } + if (limit < 0) + { + limit = 64 + limit; + } + var sourceMask = ~(ulong.MaxValue << limit) & ulong.MaxValue; + var targetMask = sourceMask << shift; + return (target & targetMask) >> shift; + } + private static Tuple GetWriteMasksAndShiftForUlong(int shift, int limit) + { + if (shift < 0) + { + shift = 64 + shift; + } + if (limit < 0) + { + limit = 64 + limit; + } + var sourceMask = ~(ulong.MaxValue << limit) & ulong.MaxValue; + var targetMask = ~(sourceMask << shift); + return new Tuple(targetMask, sourceMask, shift); + } + private static Tuple GetReadMaskAndShiftForUlong(int shift, int limit) + { + if (shift < 0) + { + shift = 64 + shift; + } + if (limit < 0) + { + limit = 64 + limit; + } + var sourceMask = ~(ulong.MaxValue << limit) & ulong.MaxValue; + var targetMask = sourceMask << shift; + return new Tuple(targetMask, shift); + } + private static ulong PartialWrite(ulong target, ulong targetMask, ulong source, ulong sourceMask, int shift) => target & targetMask | (source & sourceMask) << shift; + private static ulong PartialWrite(ulong target, ulong source, Tuple masksAndShift) => PartialWrite(target, masksAndShift.Item1, source, masksAndShift.Item2, masksAndShift.Item3); + private static ulong PartialRead(ulong target, ulong targetMask, int shift) => (target & targetMask) >> shift; + private static ulong PartialRead(ulong target, Tuple masksAndShift) => PartialRead(target, masksAndShift.Item1, masksAndShift.Item2); } }