mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 08:58:48 +00:00
feat: add math extensions for BigInteger
This commit is contained in:
parent
5e4af9a9e1
commit
dc1b9d6c04
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
- X10D: Added extension methods for `DateOnly`, for parity with `DateTime` and `DateTimeOffset`.
|
||||
- X10D: Added math-related extension methods for `BigInteger`.
|
||||
|
||||
### Changed
|
||||
- X10D: `DateTime.Age(DateTime)` and `DateTimeOffset.Age(DateTimeOffset)` parameter renamed from `asOf` to `referenceDate`.
|
||||
|
105
X10D.Tests/src/Math/BigIntegerTests.Wrap.cs
Normal file
105
X10D.Tests/src/Math/BigIntegerTests.Wrap.cs
Normal file
@ -0,0 +1,105 @@
|
||||
using System.Numerics;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using X10D.Math;
|
||||
|
||||
namespace X10D.Tests.Math;
|
||||
|
||||
public partial class BigIntegerTests
|
||||
{
|
||||
[TestClass]
|
||||
public class WrapTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void Wrap_ShouldReturnLow_WhenValueIsEqualToLow()
|
||||
{
|
||||
BigInteger value = 10;
|
||||
BigInteger low = 10;
|
||||
BigInteger high = 20;
|
||||
|
||||
BigInteger result = value.Wrap(low, high);
|
||||
|
||||
Assert.AreEqual(low, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wrap_ShouldReturnHigh_WhenValueIsEqualToHigh()
|
||||
{
|
||||
BigInteger value = 20;
|
||||
BigInteger low = 10;
|
||||
BigInteger high = 20;
|
||||
|
||||
BigInteger result = value.Wrap(low, high);
|
||||
|
||||
Assert.AreEqual(low, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wrap_ShouldReturnCorrectResult_WhenValueIsGreaterThanHigh()
|
||||
{
|
||||
BigInteger value = 30;
|
||||
BigInteger low = 10;
|
||||
BigInteger high = 20;
|
||||
|
||||
BigInteger result = value.Wrap(low, high);
|
||||
|
||||
Assert.AreEqual(low, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wrap_ShouldReturnCorrectResult_WhenValueIsLessThanLow()
|
||||
{
|
||||
BigInteger value = 5;
|
||||
BigInteger low = 10;
|
||||
BigInteger high = 20;
|
||||
|
||||
BigInteger result = value.Wrap(low, high);
|
||||
|
||||
Assert.AreEqual(15L, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wrap_ShouldReturnCorrectResult_WhenValueIsInBetweenLowAndHigh()
|
||||
{
|
||||
BigInteger value = 15;
|
||||
BigInteger low = 10;
|
||||
BigInteger high = 20;
|
||||
|
||||
BigInteger result = value.Wrap(low, high);
|
||||
|
||||
Assert.AreEqual(value, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wrap_ShouldReturnZero_WhenValueIsEqualToLength()
|
||||
{
|
||||
BigInteger value = 10;
|
||||
BigInteger length = 10;
|
||||
|
||||
BigInteger result = value.Wrap(length);
|
||||
|
||||
Assert.AreEqual(0L, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wrap_ShouldReturnValue_WhenValueIsLessThanLength()
|
||||
{
|
||||
BigInteger value = 5;
|
||||
BigInteger length = 10;
|
||||
|
||||
BigInteger result = value.Wrap(length);
|
||||
|
||||
Assert.AreEqual(value, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wrap_ShouldReturnCorrectResult_WhenValueIsGreaterThanLength()
|
||||
{
|
||||
BigInteger value = 15;
|
||||
BigInteger length = 10;
|
||||
|
||||
BigInteger result = value.Wrap(length);
|
||||
|
||||
Assert.AreEqual(5L, result);
|
||||
}
|
||||
}
|
||||
}
|
159
X10D.Tests/src/Math/BigIntegerTests.cs
Normal file
159
X10D.Tests/src/Math/BigIntegerTests.cs
Normal file
@ -0,0 +1,159 @@
|
||||
using System.Numerics;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using X10D.Math;
|
||||
|
||||
namespace X10D.Tests.Math;
|
||||
|
||||
[TestClass]
|
||||
public partial class BigIntegerTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void DigitalRootShouldBeCorrect()
|
||||
{
|
||||
BigInteger value = 238;
|
||||
Assert.AreEqual(4, value.DigitalRoot());
|
||||
Assert.AreEqual(4, (-value).DigitalRoot());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FactorialShouldBeCorrect()
|
||||
{
|
||||
Assert.AreEqual(1, ((BigInteger)0).Factorial());
|
||||
Assert.AreEqual(1, ((BigInteger)1).Factorial());
|
||||
Assert.AreEqual(2, ((BigInteger)2).Factorial());
|
||||
Assert.AreEqual(6, ((BigInteger)3).Factorial());
|
||||
Assert.AreEqual(24, ((BigInteger)4).Factorial());
|
||||
Assert.AreEqual(120, ((BigInteger)5).Factorial());
|
||||
Assert.AreEqual(720, ((BigInteger)6).Factorial());
|
||||
Assert.AreEqual(5040, ((BigInteger)7).Factorial());
|
||||
Assert.AreEqual(40320, ((BigInteger)8).Factorial());
|
||||
Assert.AreEqual(362880, ((BigInteger)9).Factorial());
|
||||
Assert.AreEqual(3628800, ((BigInteger)10).Factorial());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
|
||||
{
|
||||
BigInteger first = 5L;
|
||||
BigInteger second = 7L;
|
||||
|
||||
BigInteger multiple = first.GreatestCommonFactor(second);
|
||||
|
||||
Assert.AreEqual(1L, multiple);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GreatestCommonFactor_ShouldBe6_Given12And18()
|
||||
{
|
||||
BigInteger first = 12L;
|
||||
BigInteger second = 18L;
|
||||
|
||||
BigInteger multiple = first.GreatestCommonFactor(second);
|
||||
|
||||
Assert.AreEqual(6L, multiple);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsOddShouldBeCorrect()
|
||||
{
|
||||
BigInteger one = 1;
|
||||
BigInteger two = 2;
|
||||
|
||||
Assert.IsTrue(one.IsOdd());
|
||||
Assert.IsFalse(two.IsOdd());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LowestCommonMultiple_ShouldReturnCorrectValue_WhenCalledWithValidInput()
|
||||
{
|
||||
BigInteger value1 = 2;
|
||||
BigInteger value2 = 3;
|
||||
BigInteger expected = 6;
|
||||
|
||||
BigInteger result = value1.LowestCommonMultiple(value2);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LowestCommonMultiple_ShouldReturnZero_WhenCalledWithZero()
|
||||
{
|
||||
BigInteger value1 = 0;
|
||||
BigInteger value2 = 10;
|
||||
BigInteger expected = 0;
|
||||
|
||||
BigInteger result = value1.LowestCommonMultiple(value2);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LowestCommonMultiple_ShouldReturnGreaterValue_WhenCalledWithOne()
|
||||
{
|
||||
BigInteger value1 = 1;
|
||||
BigInteger value2 = 10;
|
||||
BigInteger expected = 10;
|
||||
|
||||
BigInteger result1 = value1.LowestCommonMultiple(value2);
|
||||
BigInteger result2 = value2.LowestCommonMultiple(value1);
|
||||
|
||||
Assert.AreEqual(expected, result1);
|
||||
Assert.AreEqual(expected, result2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LowestCommonMultiple_ShouldReturnOtherValue_WhenCalledWithSameValue()
|
||||
{
|
||||
BigInteger value1 = 5;
|
||||
BigInteger value2 = 5;
|
||||
BigInteger expected = 5;
|
||||
|
||||
BigInteger result = value1.LowestCommonMultiple(value2);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LowestCommonMultiple_ShouldReturnCorrectValue_WhenCalledWithNegativeValues()
|
||||
{
|
||||
BigInteger value1 = -2;
|
||||
BigInteger value2 = 3;
|
||||
BigInteger expected = -6;
|
||||
|
||||
BigInteger result = value1.LowestCommonMultiple(value2);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplicativePersistence_ShouldReturn1_ForAnyDigitBeing0()
|
||||
{
|
||||
Assert.AreEqual(1, ((BigInteger)10).MultiplicativePersistence());
|
||||
Assert.AreEqual(1, ((BigInteger)201).MultiplicativePersistence());
|
||||
Assert.AreEqual(1, ((BigInteger)200).MultiplicativePersistence());
|
||||
Assert.AreEqual(1, ((BigInteger)20007).MultiplicativePersistence());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
|
||||
{
|
||||
Assert.AreEqual(0, ((BigInteger)0).MultiplicativePersistence());
|
||||
Assert.AreEqual(1, ((BigInteger)10).MultiplicativePersistence());
|
||||
Assert.AreEqual(2, ((BigInteger)25).MultiplicativePersistence());
|
||||
Assert.AreEqual(3, ((BigInteger)39).MultiplicativePersistence());
|
||||
Assert.AreEqual(4, ((BigInteger)77).MultiplicativePersistence());
|
||||
Assert.AreEqual(5, ((BigInteger)679).MultiplicativePersistence());
|
||||
Assert.AreEqual(6, ((BigInteger)6788).MultiplicativePersistence());
|
||||
Assert.AreEqual(7, ((BigInteger)68889).MultiplicativePersistence());
|
||||
Assert.AreEqual(8, ((BigInteger)2677889).MultiplicativePersistence());
|
||||
Assert.AreEqual(9, ((BigInteger)26888999).MultiplicativePersistence());
|
||||
Assert.AreEqual(10, ((BigInteger)3778888999).MultiplicativePersistence());
|
||||
Assert.AreEqual(11, ((BigInteger)277777788888899).MultiplicativePersistence());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NegativeFactorialShouldThrow()
|
||||
{
|
||||
Assert.ThrowsException<ArithmeticException>(() => ((BigInteger)(-1)).Factorial());
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System.Reflection;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using X10D.Math;
|
||||
@ -26,6 +27,7 @@ public class IsPrimeTests
|
||||
|
||||
Assert.IsTrue(value.IsPrime());
|
||||
Assert.IsTrue(((long)value).IsPrime());
|
||||
Assert.IsTrue(((BigInteger)value).IsPrime());
|
||||
|
||||
if (value is >= byte.MinValue and <= byte.MaxValue)
|
||||
{
|
||||
@ -68,6 +70,7 @@ public class IsPrimeTests
|
||||
Assert.IsFalse(value.IsPrime());
|
||||
Assert.IsFalse(((int)value).IsPrime());
|
||||
Assert.IsFalse(((long)value).IsPrime());
|
||||
Assert.IsFalse(((BigInteger)value).IsPrime());
|
||||
|
||||
if (value is >= sbyte.MinValue and <= sbyte.MaxValue)
|
||||
{
|
||||
@ -85,6 +88,7 @@ public class IsPrimeTests
|
||||
Assert.IsFalse(((byte)value).IsPrime());
|
||||
Assert.IsFalse(((short)value).IsPrime());
|
||||
Assert.IsFalse(((long)value).IsPrime());
|
||||
Assert.IsFalse(((BigInteger)value).IsPrime());
|
||||
|
||||
Assert.IsFalse(((sbyte)value).IsPrime());
|
||||
Assert.IsFalse(((ushort)value).IsPrime());
|
||||
@ -103,6 +107,7 @@ public class IsPrimeTests
|
||||
Assert.AreEqual(expected, ((short)value).IsPrime());
|
||||
Assert.AreEqual(expected, value.IsPrime());
|
||||
Assert.AreEqual(expected, ((long)value).IsPrime());
|
||||
Assert.AreEqual(expected, ((BigInteger)value).IsPrime());
|
||||
|
||||
Assert.AreEqual(expected, ((ushort)value).IsPrime());
|
||||
Assert.AreEqual(expected, ((uint)value).IsPrime());
|
||||
@ -121,6 +126,7 @@ public class IsPrimeTests
|
||||
Assert.AreEqual(expected, ((short)value).IsPrime());
|
||||
Assert.AreEqual(expected, ((int)value).IsPrime());
|
||||
Assert.AreEqual(expected, ((long)value).IsPrime());
|
||||
Assert.AreEqual(expected, ((BigInteger)value).IsPrime());
|
||||
|
||||
Assert.AreEqual(expected, ((ushort)value).IsPrime());
|
||||
Assert.AreEqual(expected, ((uint)value).IsPrime());
|
||||
|
253
X10D/src/Math/BigIntegerExtensions.cs
Normal file
253
X10D/src/Math/BigIntegerExtensions.cs
Normal file
@ -0,0 +1,253 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using X10D.CompilerServices;
|
||||
|
||||
namespace X10D.Math;
|
||||
|
||||
/// <summary>
|
||||
/// Math-related extension methods for <see cref="BigInteger" />.
|
||||
/// </summary>
|
||||
public static class BigIntegerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Computes the digital root of this 8-bit integer.
|
||||
/// </summary>
|
||||
/// <param name="value">The value whose digital root to compute.</param>
|
||||
/// <returns>The digital root of <paramref name="value" />.</returns>
|
||||
/// <remarks>The digital root is defined as the recursive sum of digits until that result is a single digit.</remarks>
|
||||
/// <remarks>
|
||||
/// <para>The digital root is defined as the recursive sum of digits until that result is a single digit.</para>
|
||||
/// <para>For example, the digital root of 239 is 5: <c>2 + 3 + 9 = 14</c>, then <c>1 + 4 = 5</c>.</para>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static int DigitalRoot(this BigInteger value)
|
||||
{
|
||||
BigInteger root = BigInteger.Abs(value).Mod(9);
|
||||
return (int)(root == 0 ? 9 : root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 64-bit signed integer.
|
||||
/// </summary>
|
||||
/// <param name="value">The value whose factorial to compute.</param>
|
||||
/// <returns>The factorial of <paramref name="value" />.</returns>
|
||||
/// <exception cref="ArithmeticException"><paramref name="value" /> is less than 0.</exception>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static BigInteger Factorial(this BigInteger value)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArithmeticException(nameof(value));
|
||||
}
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
BigInteger result = 1;
|
||||
for (var i = 1L; i <= value; i++)
|
||||
{
|
||||
result *= i;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the greatest common factor between this, and another, <see cref="BigInteger" />.
|
||||
/// </summary>
|
||||
/// <param name="value">The first value.</param>
|
||||
/// <param name="other">The second value.</param>
|
||||
/// <returns>The greatest common factor between <paramref name="value" /> and <paramref name="other" />.</returns>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static BigInteger GreatestCommonFactor(this BigInteger value, BigInteger other)
|
||||
{
|
||||
while (other != 0)
|
||||
{
|
||||
(value, other) = (other, value % other);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether the current value is not evenly divisible by 2.
|
||||
/// </summary>
|
||||
/// <param name="value">The value whose parity to check.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="value" /> is not evenly divisible by 2, or <see langword="false" />
|
||||
/// otherwise.
|
||||
/// </returns>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static bool IsOdd(this BigInteger value)
|
||||
{
|
||||
return !value.IsEven;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether the current value is a prime number.
|
||||
/// </summary>
|
||||
/// <param name="value">The value whose primality to check.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="value" /> is prime; otherwise, <see langword="false" />.
|
||||
/// </returns>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static bool IsPrime(this BigInteger value)
|
||||
{
|
||||
if (value <= 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value <= 3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value.IsEven || value % 3 == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var iterator = 5L; iterator * iterator <= value; iterator += 6)
|
||||
{
|
||||
if (value % iterator == 0 || value % (iterator + 2) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the lowest common multiple between the current 64-bit signed integer, and another 64-bit signed integer.
|
||||
/// </summary>
|
||||
/// <param name="value">The first value.</param>
|
||||
/// <param name="other">The second value.</param>
|
||||
/// <returns>The lowest common multiple between <paramref name="value" /> and <paramref name="other" />.</returns>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static BigInteger LowestCommonMultiple(this BigInteger value, BigInteger other)
|
||||
{
|
||||
if (value == 0 || other == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (value == 1)
|
||||
{
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other == 1)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return value * other / value.GreatestCommonFactor(other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a modulo operation which supports a negative dividend.
|
||||
/// </summary>
|
||||
/// <param name="dividend">The dividend.</param>
|
||||
/// <param name="divisor">The divisor.</param>
|
||||
/// <returns>The result of <c>dividend mod divisor</c>.</returns>
|
||||
/// <remarks>
|
||||
/// The <c>%</c> operator (commonly called the modulo operator) in C# is not defined to be modulo, but is instead
|
||||
/// remainder. This quirk inherently makes it difficult to use modulo in a negative context, as <c>x % y</c> where x is
|
||||
/// negative will return a negative value, akin to <c>-(x % y)</c>, even if precedence is forced. This method provides a
|
||||
/// modulo operation which supports negative dividends.
|
||||
/// </remarks>
|
||||
/// <author>ShreevatsaR, https://stackoverflow.com/a/1082938/1467293</author>
|
||||
/// <license>CC-BY-SA 2.5</license>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static BigInteger Mod(this BigInteger dividend, BigInteger divisor)
|
||||
{
|
||||
BigInteger r = dividend % divisor;
|
||||
return r < 0 ? r + divisor : r;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the multiplicative persistence of a specified value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value whose multiplicative persistence to calculate.</param>
|
||||
/// <returns>The multiplicative persistence.</returns>
|
||||
/// <remarks>
|
||||
/// Multiplicative persistence is defined as the recursive digital product until that product is a single digit.
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static int MultiplicativePersistence(this BigInteger value)
|
||||
{
|
||||
var persistence = 0;
|
||||
BigInteger product = BigInteger.Abs(value);
|
||||
|
||||
while (product > 9)
|
||||
{
|
||||
if (value % 10 == 0)
|
||||
{
|
||||
return persistence + 1;
|
||||
}
|
||||
|
||||
while (value > 9)
|
||||
{
|
||||
value /= 10;
|
||||
if (value % 10 == 0)
|
||||
{
|
||||
return persistence + 1;
|
||||
}
|
||||
}
|
||||
|
||||
BigInteger newProduct = 1;
|
||||
BigInteger currentProduct = product;
|
||||
while (currentProduct > 0)
|
||||
{
|
||||
newProduct *= currentProduct % 10;
|
||||
currentProduct /= 10;
|
||||
}
|
||||
|
||||
product = newProduct;
|
||||
persistence++;
|
||||
}
|
||||
|
||||
return persistence;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the current integer between a low and a high value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to wrap.</param>
|
||||
/// <param name="low">The inclusive lower bound.</param>
|
||||
/// <param name="high">The exclusive upper bound.</param>
|
||||
/// <returns>The wrapped value.</returns>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static BigInteger Wrap(this BigInteger value, BigInteger low, BigInteger high)
|
||||
{
|
||||
BigInteger difference = high - low;
|
||||
return low + (((value - low) % difference) + difference) % difference;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the current integer between 0 and a high value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to wrap.</param>
|
||||
/// <param name="length">The exclusive upper bound.</param>
|
||||
/// <returns>The wrapped value.</returns>
|
||||
[Pure]
|
||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||
public static BigInteger Wrap(this BigInteger value, BigInteger length)
|
||||
{
|
||||
return ((value % length) + length) % length;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user