diff --git a/csharp/Platform.Numbers.Tests/BitTests.cs b/csharp/Platform.Numbers.Tests/BitTests.cs index 3a3079b..fc4a5ce 100644 --- a/csharp/Platform.Numbers.Tests/BitTests.cs +++ b/csharp/Platform.Numbers.Tests/BitTests.cs @@ -173,5 +173,122 @@ public static void BugWithLoadingConstantOf8Test() { Bit.PartialWrite(0, 1, 5, -5); } + + [Theory] + [InlineData(0L, 0)] + [InlineData(1L, 1)] + [InlineData(2L, 1)] + [InlineData(3L, 2)] + [InlineData(4L, 1)] + [InlineData(5L, 2)] + [InlineData(7L, 3)] + [InlineData(8L, 1)] + [InlineData(15L, 4)] + [InlineData(255L, 8)] + [InlineData(1023L, 10)] + [InlineData(-1L, 64)] + [InlineData(long.MaxValue, 63)] + public static void BitCountTest(long value, int expectedCount) + { + Assert.Equal(expectedCount, Bit.Count(value)); + } + + [Fact] + public static void BitGenericPartialWriteWithNegativeShiftTest() + { + uint target = 0xFFFFFFFF; + uint source = 0b101; + + uint result = Bit.PartialWrite(target, source, -5, 3); + + // -5 becomes 32-5=27, so we write 101 at positions 27-29 + uint expected = 0xEFFFFFFF; // 11101111111111111111111111111111 + Assert.Equal(expected, result); + } + + [Fact] + public static void BitGenericPartialReadWithNegativeShiftTest() + { + uint target = 0xEFFFFFFF; // 11101111111111111111111111111111 + + uint result = Bit.PartialRead(target, -5, 3); + + // -5 becomes 27, read 3 bits at position 27-29 should give 101 + uint expected = 0b101; + Assert.Equal(expected, result); + } + + [Fact] + public static void BitGenericPartialWriteWithNegativeLimitTest() + { + uint target = 0; + uint source = 0b111; + + uint result = Bit.PartialWrite(target, source, 0, -29); + + uint expected = 0b111; + Assert.Equal(expected, result); + } + + [Fact] + public static void BitGenericPartialReadWithNegativeLimitTest() + { + uint target = 0b111; + + uint result = Bit.PartialRead(target, 0, -29); + + uint expected = 0b111; + Assert.Equal(expected, result); + } + + [Fact] + public static void BitGenericPartialWriteReadRoundTripTest() + { + uint original = 0b10110101; + uint value1 = 0b011; + uint value2 = 0b1010; + + uint packed = Bit.PartialWrite(original, value1, 2, 3); + packed = Bit.PartialWrite(packed, value2, 8, 4); + + uint extracted1 = Bit.PartialRead(packed, 2, 3); + uint extracted2 = Bit.PartialRead(packed, 8, 4); + + Assert.Equal(value1, extracted1); + Assert.Equal(value2, extracted2); + } + + [Theory] + [InlineData(typeof(byte))] + [InlineData(typeof(ushort))] + [InlineData(typeof(uint))] + [InlineData(typeof(ulong))] + public static void BitGenericWorksWithDifferentTypes(Type numericType) + { + if (numericType == typeof(byte)) + { + byte result = Bit.PartialWrite(0, 3, 1, 2); + Assert.Equal((byte)6, result); + Assert.Equal((byte)3, Bit.PartialRead(result, 1, 2)); + } + else if (numericType == typeof(ushort)) + { + ushort result = Bit.PartialWrite(0, 3, 1, 2); + Assert.Equal((ushort)6, result); + Assert.Equal((ushort)3, Bit.PartialRead(result, 1, 2)); + } + else if (numericType == typeof(uint)) + { + uint result = Bit.PartialWrite(0, 3, 1, 2); + Assert.Equal(6u, result); + Assert.Equal(3u, Bit.PartialRead(result, 1, 2)); + } + else if (numericType == typeof(ulong)) + { + ulong result = Bit.PartialWrite(0, 3, 1, 2); + Assert.Equal(6ul, result); + Assert.Equal(3ul, Bit.PartialRead(result, 1, 2)); + } + } } } diff --git a/csharp/Platform.Numbers.Tests/MathTests.cs b/csharp/Platform.Numbers.Tests/MathTests.cs new file mode 100644 index 0000000..b5f38cd --- /dev/null +++ b/csharp/Platform.Numbers.Tests/MathTests.cs @@ -0,0 +1,111 @@ +using System; +using Xunit; + +namespace Platform.Numbers.Tests +{ + public static class MathTests + { + [Theory] + [InlineData(0ul, 1ul)] + [InlineData(1ul, 1ul)] + [InlineData(2ul, 2ul)] + [InlineData(3ul, 6ul)] + [InlineData(4ul, 24ul)] + [InlineData(5ul, 120ul)] + [InlineData(6ul, 720ul)] + [InlineData(10ul, 3628800ul)] + [InlineData(20ul, 2432902008176640000ul)] + public static void FactorialTest(ulong input, ulong expected) + { + Assert.Equal(expected, Math.Factorial(input)); + } + + [Theory] + [InlineData(21ul)] + [InlineData(100ul)] + [InlineData(ulong.MaxValue)] + public static void FactorialOutOfRangeTest(ulong input) + { + Assert.Throws(() => Math.Factorial(input)); + } + + [Theory] + [InlineData(0ul, 1ul)] + [InlineData(1ul, 1ul)] + [InlineData(2ul, 2ul)] + [InlineData(3ul, 5ul)] + [InlineData(4ul, 14ul)] + [InlineData(5ul, 42ul)] + [InlineData(6ul, 132ul)] + [InlineData(10ul, 16796ul)] + [InlineData(36ul, 11959798385860453492ul)] + public static void CatalanTest(ulong input, ulong expected) + { + Assert.Equal(expected, Math.Catalan(input)); + } + + [Theory] + [InlineData(37ul)] + [InlineData(100ul)] + [InlineData(ulong.MaxValue)] + public static void CatalanOutOfRangeTest(ulong input) + { + Assert.Throws(() => Math.Catalan(input)); + } + + [Theory] + [InlineData(0ul, true)] + [InlineData(1ul, true)] + [InlineData(2ul, true)] + [InlineData(3ul, false)] + [InlineData(4ul, true)] + [InlineData(5ul, false)] + [InlineData(8ul, true)] + [InlineData(16ul, true)] + [InlineData(32ul, true)] + [InlineData(64ul, true)] + [InlineData(128ul, true)] + [InlineData(256ul, true)] + [InlineData(512ul, true)] + [InlineData(1024ul, true)] + [InlineData(1023ul, false)] + [InlineData(1025ul, false)] + [InlineData(9ul, false)] + [InlineData(15ul, false)] + [InlineData(17ul, false)] + public static void IsPowerOfTwoTest(ulong input, bool expected) + { + Assert.Equal(expected, Math.IsPowerOfTwo(input)); + } + + [Fact] + public static void FactorialGenericTest() + { + Assert.Equal(6u, Math.Factorial(3u)); + Assert.Equal(24ul, Math.Factorial(4ul)); + } + + [Fact] + public static void CatalanGenericTest() + { + Assert.Equal(5u, Math.Catalan(3u)); + Assert.Equal(14ul, Math.Catalan(4ul)); + } + + [Fact] + public static void IsPowerOfTwoGenericTest() + { + Assert.True(Math.IsPowerOfTwo(8u)); + Assert.False(Math.IsPowerOfTwo(9u)); + Assert.True(Math.IsPowerOfTwo(16ul)); + Assert.False(Math.IsPowerOfTwo(15ul)); + } + + [Fact] + public static void MaximumConstantsTest() + { + Assert.Equal(20ul, Math.MaximumFactorialNumber); + Assert.Equal(36ul, Math.MaximumCatalanIndex); + } + } +} \ No newline at end of file diff --git a/csharp/Platform.Numbers/Math.cs b/csharp/Platform.Numbers/Math.cs index 84a48b7..8c085bf 100644 --- a/csharp/Platform.Numbers/Math.cs +++ b/csharp/Platform.Numbers/Math.cs @@ -52,7 +52,7 @@ public static class Math /// public static TLinkAddress Factorial(TLinkAddress n) where TLinkAddress : IUnsignedNumber, IComparisonOperators { - if (n >= TLinkAddress.Zero && n <= TLinkAddress.CreateTruncating(MaximumCatalanIndex)) + if (n >= TLinkAddress.Zero && n <= TLinkAddress.CreateTruncating(MaximumFactorialNumber)) { return TLinkAddress.CreateTruncating(_factorials[ulong.CreateTruncating(n)]); }