Skip to content

Commit

Permalink
Add Binomal, GCD, and Multinomial methods
Browse files Browse the repository at this point in the history
  • Loading branch information
HamletTanyavong committed Nov 29, 2023
1 parent 0fc1411 commit a50ab46
Showing 1 changed file with 89 additions and 0 deletions.
89 changes: 89 additions & 0 deletions src/Mathematics.NET/Mathematics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
// SOFTWARE.
// </copyright>

using System.Numerics;
using System.Runtime.CompilerServices;
using Complex = Mathematics.NET.Core.Complex;

namespace Mathematics.NET;

/// <summary>Provides Mathematics.NET functionality</summary>
Expand Down Expand Up @@ -84,4 +88,89 @@ public static class Mathematics

/// <inheritdoc cref="Constants.ZetaOf4"/>
public static Real ZetaOf4 => Real.ZetaOf4;

//
// Methods
//

// Integer-related

/// <summary>The binomial coefficient</summary>
/// <remarks>This method works with <c>BigInteger</c>. Be aware that this method may take a long time.</remarks>
/// <typeparam name="T">A type that implements <see cref="IBinaryInteger{TSelf}"/></typeparam>
/// <param name="n">A total of <paramref name="n"/> elements</param>
/// <param name="k">An unordered subset of <paramref name="k"/> elements</param>
/// <param name="cancellationToken">A cancellation token</param>
/// <returns><paramref name="n"/> choose <paramref name="k"/></returns>
/// <exception cref="OverflowException"></exception>
public static T Binomial<T>(T n, T k, CancellationToken cancellationToken)
where T : IBinaryInteger<T>
{
var result = T.One;
checked
{
T u = T.One;
for (T i = T.Zero; i < k; i++)
{
cancellationToken.ThrowIfCancellationRequested();
result *= n - i;
u *= i + T.One;

var gcd = GCD(result, u);
if (gcd != T.One)
{
result /= gcd;
u /= gcd;
}
}
}
return result;
}

/// <summary>Compute the greatest common divisor of two integers.</summary>
/// <typeparam name="T">A type that implements <see cref="IBinaryInteger{TSelf}"/></typeparam>
/// <param name="p">An integer</param>
/// <param name="q">An integer</param>
/// <returns>The GCD of the two values</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T GCD<T>(T p, T q)
where T : IBinaryInteger<T>
{
p = T.Abs(p);
q = T.Abs(q);
while (p != T.Zero && q != T.Zero)
{
if (p > q)
{
p %= q;
}
else
{
q %= p;
}
}
return p | q;
}

/// <summary>The multinomial coefficient</summary>
/// <param name="α">An array of positive integers</param>
/// <param name="cancellationToken">A cancellation token</param>
/// <returns>The coefficient associated with a term with powers given by <paramref name="α"/></returns>
/// <exception cref="OverflowException"></exception>
public static T Multinomial<T>(ReadOnlySpan<T> α, CancellationToken cancellationToken)
where T : IBinaryInteger<T>
{
var result = T.One;
checked
{
var partialSum = α[0];
for (int i = 1; i < α.Length; i++)
{
var element = α[i];
partialSum += element;
result *= Binomial(partialSum, element, cancellationToken);
}
}
return result;
}
}

0 comments on commit a50ab46

Please sign in to comment.