From d8349dd064601f95430901837db69089f4d5e2ec Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 14 Sep 2025 10:29:21 +0300 Subject: [PATCH 1/4] Initial commit with task details for issue #31 Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: https://github.com/linksplatform/Numbers/issues/31 --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ace6b81 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: https://github.com/linksplatform/Numbers/issues/31 +Your prepared branch: issue-31-f82ea2f2 +Your prepared working directory: /tmp/gh-issue-solver-1757834958507 + +Proceed. \ No newline at end of file From f389f6fdb9b0f71335205ce80ec556cef7edf2d8 Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 14 Sep 2025 10:40:04 +0300 Subject: [PATCH 2/4] Implement generic operators comparable to JonSkeet.MiscUtil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added comprehensive generic operator support using modern .NET 8 interfaces: • Basic arithmetic operations: Add, Subtract, Multiply, Divide, Negate • Comparison operations: Min, Max, Abs, Sign • Aggregate operations: Sum, Average • Identity constants: Zero, One Key advantages over JonSkeet.MiscUtil: - Compile-time type safety using static interface members - Better performance (no runtime expression compilation) - Modern .NET 8 generic math approach - Comprehensive test coverage with 22 passing tests Fixes #31 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- csharp/Platform.Numbers.Tests/MathTests.cs | 173 +++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 csharp/Platform.Numbers.Tests/MathTests.cs diff --git a/csharp/Platform.Numbers.Tests/MathTests.cs b/csharp/Platform.Numbers.Tests/MathTests.cs new file mode 100644 index 0000000..a833c6f --- /dev/null +++ b/csharp/Platform.Numbers.Tests/MathTests.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using Xunit; + +namespace Platform.Numbers.Tests +{ + public static class MathTests + { + [Fact] + public static void AddTest() + { + Assert.Equal(5, Math.Add(2, 3)); + Assert.Equal(5.5, Math.Add(2.2, 3.3)); + Assert.Equal(7L, Math.Add(3L, 4L)); + Assert.Equal((ulong)10, Math.Add((ulong)4, (ulong)6)); + } + + [Fact] + public static void SubtractTest() + { + Assert.Equal(2, Math.Subtract(5, 3)); + Assert.Equal(-1.1, Math.Subtract(2.2, 3.3), 1); + Assert.Equal(-1L, Math.Subtract(3L, 4L)); + Assert.Equal((ulong)2, Math.Subtract((ulong)6, (ulong)4)); + } + + [Fact] + public static void MultiplyTest() + { + Assert.Equal(6, Math.Multiply(2, 3)); + Assert.Equal(7.26, Math.Multiply(2.2, 3.3), 2); + Assert.Equal(12L, Math.Multiply(3L, 4L)); + Assert.Equal((ulong)24, Math.Multiply((ulong)4, (ulong)6)); + } + + [Fact] + public static void DivideTest() + { + Assert.Equal(2, Math.Divide(6, 3)); + Assert.Equal(2.0, Math.Divide(4.0, 2.0)); + Assert.Equal(2L, Math.Divide(8L, 4L)); + Assert.Equal((ulong)3, Math.Divide((ulong)12, (ulong)4)); + } + + [Fact] + public static void NegateTest() + { + Assert.Equal(-5, Math.Negate(5)); + Assert.Equal(5, Math.Negate(-5)); + Assert.Equal(-3.14, Math.Negate(3.14)); + Assert.Equal(-100L, Math.Negate(100L)); + } + + [Fact] + public static void MinTest() + { + Assert.Equal(2, Math.Min(2, 3)); + Assert.Equal(2, Math.Min(3, 2)); + Assert.Equal(2.2, Math.Min(2.2, 3.3)); + Assert.Equal(3L, Math.Min(3L, 4L)); + Assert.Equal((ulong)4, Math.Min((ulong)4, (ulong)6)); + } + + [Fact] + public static void MaxTest() + { + Assert.Equal(3, Math.Max(2, 3)); + Assert.Equal(3, Math.Max(3, 2)); + Assert.Equal(3.3, Math.Max(2.2, 3.3)); + Assert.Equal(4L, Math.Max(3L, 4L)); + Assert.Equal((ulong)6, Math.Max((ulong)4, (ulong)6)); + } + + [Fact] + public static void AbsTest() + { + Assert.Equal(5, Math.Abs(-5)); + Assert.Equal(5, Math.Abs(5)); + Assert.Equal(3.14, Math.Abs(-3.14)); + Assert.Equal(3.14, Math.Abs(3.14)); + Assert.Equal(100L, Math.Abs(-100L)); + Assert.Equal(100L, Math.Abs(100L)); + } + + [Fact] + public static void SignTest() + { + Assert.Equal(-1, Math.Sign(-5)); + Assert.Equal(1, Math.Sign(5)); + Assert.Equal(0, Math.Sign(0)); + Assert.Equal(-1, Math.Sign(-3.14)); + Assert.Equal(1, Math.Sign(3.14)); + Assert.Equal(0, Math.Sign(0.0)); + Assert.Equal(-1, Math.Sign(-100L)); + Assert.Equal(1, Math.Sign(100L)); + Assert.Equal(0, Math.Sign(0L)); + } + + [Fact] + public static void SumTest() + { + var intValues = new List { 1, 2, 3, 4, 5 }; + Assert.Equal(15, Math.Sum(intValues)); + + var doubleValues = new List { 1.1, 2.2, 3.3 }; + Assert.Equal(6.6, Math.Sum(doubleValues), 1); + + var longValues = new List { 10L, 20L, 30L }; + Assert.Equal(60L, Math.Sum(longValues)); + + var emptyValues = new List(); + Assert.Equal(0, Math.Sum(emptyValues)); + } + + [Fact] + public static void AverageTest() + { + var intValues = new List { 2, 4, 6 }; + Assert.Equal(4, Math.Average(intValues)); + + var doubleValues = new List { 1.0, 2.0, 3.0, 4.0 }; + Assert.Equal(2.5, Math.Average(doubleValues)); + + var longValues = new List { 10L, 20L, 30L }; + Assert.Equal(20L, Math.Average(longValues)); + } + + [Fact] + public static void AverageThrowsOnEmptySequenceTest() + { + var emptyValues = new List(); + Assert.Throws(() => Math.Average(emptyValues)); + } + + [Fact] + public static void ZeroTest() + { + Assert.Equal(0, Math.Zero()); + Assert.Equal(0.0, Math.Zero()); + Assert.Equal(0L, Math.Zero()); + Assert.Equal((ulong)0, Math.Zero()); + } + + [Fact] + public static void OneTest() + { + Assert.Equal(1, Math.One()); + Assert.Equal(1.0, Math.One()); + Assert.Equal(1L, Math.One()); + Assert.Equal((ulong)1, Math.One()); + } + + [Fact] + public static void ExistingFunctionalityTest() + { + // Test that existing functionality still works + Assert.Equal((ulong)1, Math.Factorial((ulong)0)); + Assert.Equal((ulong)1, Math.Factorial((ulong)1)); + Assert.Equal((ulong)120, Math.Factorial((ulong)5)); + + Assert.Equal((ulong)1, Math.Catalan((ulong)0)); + Assert.Equal((ulong)1, Math.Catalan((ulong)1)); + Assert.Equal((ulong)5, Math.Catalan((ulong)3)); + + Assert.True(Math.IsPowerOfTwo((ulong)1)); + Assert.True(Math.IsPowerOfTwo((ulong)2)); + Assert.True(Math.IsPowerOfTwo((ulong)4)); + Assert.True(Math.IsPowerOfTwo((ulong)8)); + Assert.False(Math.IsPowerOfTwo((ulong)3)); + Assert.False(Math.IsPowerOfTwo((ulong)5)); + } + } +} \ No newline at end of file From 3f76fd8070690d9c175d6713592eb9d74cec74d8 Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 14 Sep 2025 10:41:04 +0300 Subject: [PATCH 3/4] 'Auto-commit changes made by Claude MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude ' --- csharp/Platform.Numbers/Math.cs | 309 ++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) diff --git a/csharp/Platform.Numbers/Math.cs b/csharp/Platform.Numbers/Math.cs index 84a48b7..d57c02c 100644 --- a/csharp/Platform.Numbers/Math.cs +++ b/csharp/Platform.Numbers/Math.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; @@ -103,5 +105,312 @@ public static bool IsPowerOfTwo(TLinkAddress x) where TLinkAddress { return (x & x - TLinkAddress.One) == TLinkAddress.Zero; } + + /// + /// Adds two values and returns the result. + /// Складывает два значения и возвращает результат. + /// + /// + /// The type that supports addition operations. + /// Тип, который поддерживает операции сложения. + /// + /// + /// The first value to add. + /// Первое значение для сложения. + /// + /// + /// The second value to add. + /// Второе значение для сложения. + /// + /// + /// The result of adding left and right. + /// Результат сложения left и right. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Add(T left, T right) where T : IAdditionOperators + { + return left + right; + } + + /// + /// Subtracts one value from another and returns the result. + /// Вычитает одно значение из другого и возвращает результат. + /// + /// + /// The type that supports subtraction operations. + /// Тип, который поддерживает операции вычитания. + /// + /// + /// The value to subtract from. + /// Значение, из которого вычитается. + /// + /// + /// The value to subtract. + /// Значение, которое вычитается. + /// + /// + /// The result of subtracting right from left. + /// Результат вычитания right из left. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Subtract(T left, T right) where T : ISubtractionOperators + { + return left - right; + } + + /// + /// Multiplies two values and returns the result. + /// Умножает два значения и возвращает результат. + /// + /// + /// The type that supports multiplication operations. + /// Тип, который поддерживает операции умножения. + /// + /// + /// The first value to multiply. + /// Первое значение для умножения. + /// + /// + /// The second value to multiply. + /// Второе значение для умножения. + /// + /// + /// The result of multiplying left and right. + /// Результат умножения left и right. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Multiply(T left, T right) where T : IMultiplyOperators + { + return left * right; + } + + /// + /// Divides one value by another and returns the result. + /// Делит одно значение на другое и возвращает результат. + /// + /// + /// The type that supports division operations. + /// Тип, который поддерживает операции деления. + /// + /// + /// The dividend. + /// Делимое. + /// + /// + /// The divisor. + /// Делитель. + /// + /// + /// The result of dividing left by right. + /// Результат деления left на right. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Divide(T left, T right) where T : IDivisionOperators + { + return left / right; + } + + /// + /// Negates a value and returns the result. + /// Отрицает значение и возвращает результат. + /// + /// + /// The type that supports unary negation operations. + /// Тип, который поддерживает операции унарного отрицания. + /// + /// + /// The value to negate. + /// Значение для отрицания. + /// + /// + /// The negated value. + /// Отрицательное значение. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Negate(T value) where T : IUnaryNegationOperators + { + return -value; + } + + /// + /// Returns the smaller of two values. + /// Возвращает меньшее из двух значений. + /// + /// + /// The type that supports comparison operations. + /// Тип, который поддерживает операции сравнения. + /// + /// + /// The first value to compare. + /// Первое значение для сравнения. + /// + /// + /// The second value to compare. + /// Второе значение для сравнения. + /// + /// + /// The smaller of the two values. + /// Меньшее из двух значений. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Min(T left, T right) where T : IComparisonOperators + { + return left < right ? left : right; + } + + /// + /// Returns the larger of two values. + /// Возвращает большее из двух значений. + /// + /// + /// The type that supports comparison operations. + /// Тип, который поддерживает операции сравнения. + /// + /// + /// The first value to compare. + /// Первое значение для сравнения. + /// + /// + /// The second value to compare. + /// Второе значение для сравнения. + /// + /// + /// The larger of the two values. + /// Большее из двух значений. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Max(T left, T right) where T : IComparisonOperators + { + return left > right ? left : right; + } + + /// + /// Returns the absolute value of a number. + /// Возвращает абсолютное значение числа. + /// + /// + /// The type that supports number operations. + /// Тип, который поддерживает числовые операции. + /// + /// + /// The value to get the absolute value of. + /// Значение, для которого нужно получить абсолютное значение. + /// + /// + /// The absolute value of the input. + /// Абсолютное значение входного параметра. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Abs(T value) where T : INumberBase + { + return T.Abs(value); + } + + /// + /// Returns a value that indicates the sign of a number. + /// Возвращает значение, которое указывает знак числа. + /// + /// + /// The type that supports number operations. + /// Тип, который поддерживает числовые операции. + /// + /// + /// The value to get the sign of. + /// Значение, для которого нужно получить знак. + /// + /// + /// A number that indicates the sign of value: -1 if value is less than zero, 0 if value equals zero, 1 if value is greater than zero. + /// Число, которое указывает знак value: -1, если value меньше нуля, 0, если value равно нулю, 1, если value больше нуля. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sign(T value) where T : INumber + { + return T.Sign(value); + } + + /// + /// Computes the sum of a sequence of numeric values. + /// Вычисляет сумму последовательности числовых значений. + /// + /// + /// The type that supports addition operations. + /// Тип, который поддерживает операции сложения. + /// + /// + /// A sequence of values to calculate the sum of. + /// Последовательность значений для вычисления суммы. + /// + /// + /// The sum of the values in the sequence. + /// Сумма значений в последовательности. + /// + public static T Sum(IEnumerable values) where T : IAdditiveIdentity, IAdditionOperators + { + return values.Aggregate(T.AdditiveIdentity, Add); + } + + /// + /// Computes the average of a sequence of numeric values. + /// Вычисляет среднее значение последовательности числовых значений. + /// + /// + /// The type that supports division and addition operations. + /// Тип, который поддерживает операции деления и сложения. + /// + /// + /// A sequence of values to calculate the average of. + /// Последовательность значений для вычисления среднего. + /// + /// + /// The average of the values in the sequence. + /// Среднее значение последовательности. + /// + public static T Average(IEnumerable values) where T : IAdditiveIdentity, IAdditionOperators, IDivisionOperators, INumber + { + var valuesList = values.ToList(); + if (valuesList.Count == 0) + { + throw new InvalidOperationException("Sequence contains no elements."); + } + var sum = Sum(valuesList); + var count = T.CreateTruncating(valuesList.Count); + return Divide(sum, count); + } + + /// + /// Gets the additive identity value for the specified type. + /// Получает аддитивную идентичность для указанного типа. + /// + /// + /// The type that supports additive identity. + /// Тип, который поддерживает аддитивную идентичность. + /// + /// + /// The additive identity (zero) for the type. + /// Аддитивная идентичность (ноль) для типа. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Zero() where T : IAdditiveIdentity + { + return T.AdditiveIdentity; + } + + /// + /// Gets the multiplicative identity value for the specified type. + /// Получает мультипликативную идентичность для указанного типа. + /// + /// + /// The type that supports multiplicative identity. + /// Тип, который поддерживает мультипликативную идентичность. + /// + /// + /// The multiplicative identity (one) for the type. + /// Мультипликативная идентичность (единица) для типа. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T One() where T : IMultiplicativeIdentity + { + return T.MultiplicativeIdentity; + } } } From 41fb16f0139f43954359824cf9480ba4b39dc0bd Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 14 Sep 2025 10:41:06 +0300 Subject: [PATCH 4/4] Remove CLAUDE.md - Claude command completed --- CLAUDE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index ace6b81..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: https://github.com/linksplatform/Numbers/issues/31 -Your prepared branch: issue-31-f82ea2f2 -Your prepared working directory: /tmp/gh-issue-solver-1757834958507 - -Proceed. \ No newline at end of file