mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-09 16:55:41 +00:00
feat: convert DigitalRoot and Mod to generic math
This commit is contained in:
parent
87a85b82d9
commit
b91aad6305
@ -11,8 +11,14 @@ public partial class UInt32Tests
|
||||
public void DigitalRootShouldBeCorrect()
|
||||
{
|
||||
const uint value = 238;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
Assert.AreEqual(4, value.DigitalRoot());
|
||||
Assert.AreEqual(4, (-value).DigitalRoot());
|
||||
#else
|
||||
Assert.AreEqual(4U, value.DigitalRoot());
|
||||
Assert.AreEqual(4U, (-value).DigitalRoot());
|
||||
#endif
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -11,12 +11,18 @@ public partial class UInt64Tests
|
||||
public void DigitalRootShouldBeCorrect()
|
||||
{
|
||||
const ulong value = 238;
|
||||
Assert.AreEqual(4U, value.DigitalRoot());
|
||||
|
||||
// -ulong operator not defined because it might exceed long.MinValue,
|
||||
// so instead, cast to long and then negate.
|
||||
// HAX.
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
Assert.AreEqual(4, (-(long)value).DigitalRoot());
|
||||
Assert.AreEqual(4, value.DigitalRoot());
|
||||
#else
|
||||
Assert.AreEqual(4U, (-(long)value).DigitalRoot());
|
||||
Assert.AreEqual(4U, value.DigitalRoot());
|
||||
#endif
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -10,6 +10,7 @@ namespace X10D.Math;
|
||||
/// </summary>
|
||||
public static class BigIntegerExtensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of this 8-bit integer.
|
||||
/// </summary>
|
||||
@ -27,6 +28,7 @@ public static class BigIntegerExtensions
|
||||
BigInteger root = BigInteger.Abs(value).Mod(9);
|
||||
return (int)(root == 0 ? 9 : root);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 64-bit signed integer.
|
||||
@ -155,6 +157,7 @@ public static class BigIntegerExtensions
|
||||
return value * other / value.GreatestCommonFactor(other);
|
||||
}
|
||||
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Performs a modulo operation which supports a negative dividend.
|
||||
/// </summary>
|
||||
@ -176,6 +179,7 @@ public static class BigIntegerExtensions
|
||||
BigInteger r = dividend % divisor;
|
||||
return r < 0 ? r + divisor : r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the multiplicative persistence of a specified value.
|
||||
|
58
X10D/src/Math/BinaryIntegerExtensions.cs
Normal file
58
X10D/src/Math/BinaryIntegerExtensions.cs
Normal file
@ -0,0 +1,58 @@
|
||||
#if NET7_0_OR_GREATER
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using X10D.CompilerServices;
|
||||
|
||||
namespace X10D.Math;
|
||||
|
||||
/// <summary>
|
||||
/// Math-related extension methods for <see cref="IBinaryInteger{TSelf}" />.
|
||||
/// </summary>
|
||||
public static class BinaryIntegerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Computes the digital root of this 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<TInteger>(this TInteger value)
|
||||
where TInteger : IBinaryInteger<TInteger>
|
||||
{
|
||||
var nine = TInteger.CreateChecked(9);
|
||||
TInteger root = TInteger.Abs(value).Mod(nine);
|
||||
return int.CreateChecked(root == TInteger.Zero ? nine : root);
|
||||
}
|
||||
|
||||
/// <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 TInteger Mod<TInteger>(this TInteger dividend, TInteger divisor)
|
||||
where TInteger : IBinaryInteger<TInteger>
|
||||
{
|
||||
TInteger r = dividend % divisor;
|
||||
return r < TInteger.Zero ? r + divisor : r;
|
||||
}
|
||||
}
|
||||
#endif
|
@ -9,6 +9,7 @@ namespace X10D.Math;
|
||||
/// </summary>
|
||||
public static class ByteExtensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of this 8-bit integer.
|
||||
/// </summary>
|
||||
@ -26,6 +27,7 @@ public static class ByteExtensions
|
||||
int root = value % 9;
|
||||
return (byte)(root == 0 ? 9 : root);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 8-bit unsigned integer.
|
||||
|
@ -9,6 +9,7 @@ namespace X10D.Math;
|
||||
/// </summary>
|
||||
public static class Int16Extensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of this 16-bit integer.
|
||||
/// </summary>
|
||||
@ -25,6 +26,7 @@ public static class Int16Extensions
|
||||
short root = System.Math.Abs(value).Mod(9);
|
||||
return root < 1 ? (short)(9 - root) : root;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 16-bit signed integer.
|
||||
@ -125,6 +127,7 @@ public static class Int16Extensions
|
||||
return (short)((long)value).LowestCommonMultiple(other);
|
||||
}
|
||||
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Performs a modulo operation which supports a negative dividend.
|
||||
/// </summary>
|
||||
@ -146,6 +149,7 @@ public static class Int16Extensions
|
||||
int r = dividend % divisor;
|
||||
return (short)(r < 0 ? r + divisor : r);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the multiplicative persistence of a specified value.
|
||||
|
@ -9,6 +9,7 @@ namespace X10D.Math;
|
||||
/// </summary>
|
||||
public static class Int32Extensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of this 32-bit integer.
|
||||
/// </summary>
|
||||
@ -25,6 +26,7 @@ public static class Int32Extensions
|
||||
int root = System.Math.Abs(value).Mod(9);
|
||||
return root < 1 ? 9 - root : root;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 32-bit signed integer.
|
||||
@ -125,6 +127,7 @@ public static class Int32Extensions
|
||||
return (int)((long)value).LowestCommonMultiple(other);
|
||||
}
|
||||
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Performs a modulo operation which supports a negative dividend.
|
||||
/// </summary>
|
||||
@ -146,6 +149,7 @@ public static class Int32Extensions
|
||||
int r = dividend % divisor;
|
||||
return r < 0 ? r + divisor : r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the multiplicative persistence of a specified value.
|
||||
|
@ -9,6 +9,7 @@ namespace X10D.Math;
|
||||
/// </summary>
|
||||
public static class Int64Extensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of this 64-bit integer.
|
||||
/// </summary>
|
||||
@ -25,6 +26,7 @@ public static class Int64Extensions
|
||||
long root = System.Math.Abs(value).Mod(9L);
|
||||
return root < 1L ? 9L - root : root;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 64-bit signed integer.
|
||||
@ -164,6 +166,7 @@ public static class Int64Extensions
|
||||
return value * other / value.GreatestCommonFactor(other);
|
||||
}
|
||||
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Performs a modulo operation which supports a negative dividend.
|
||||
/// </summary>
|
||||
@ -185,6 +188,7 @@ public static class Int64Extensions
|
||||
long r = dividend % divisor;
|
||||
return r < 0 ? r + divisor : r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the multiplicative persistence of a specified value.
|
||||
|
@ -10,6 +10,7 @@ namespace X10D.Math;
|
||||
[CLSCompliant(false)]
|
||||
public static class SByteExtensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of this 32-bit integer.
|
||||
/// </summary>
|
||||
@ -26,6 +27,7 @@ public static class SByteExtensions
|
||||
int root = System.Math.Abs(value).Mod(9);
|
||||
return (sbyte)(root < 1 ? 9 - root : root);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 8-bit signed integer.
|
||||
@ -126,6 +128,7 @@ public static class SByteExtensions
|
||||
return (sbyte)((long)value).LowestCommonMultiple(other);
|
||||
}
|
||||
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Performs a modulo operation which supports a negative dividend.
|
||||
/// </summary>
|
||||
@ -147,6 +150,7 @@ public static class SByteExtensions
|
||||
int r = dividend % divisor;
|
||||
return (sbyte)(r < 0 ? r + divisor : r);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the multiplicative persistence of a specified value.
|
||||
|
@ -10,6 +10,7 @@ namespace X10D.Math;
|
||||
[CLSCompliant(false)]
|
||||
public static class UInt16Extensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of the current 16-bit unsigned integer.
|
||||
/// </summary>
|
||||
@ -26,6 +27,7 @@ public static class UInt16Extensions
|
||||
var root = (ushort)(value % 9);
|
||||
return (ushort)(root == 0 ? 9 : root);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 16-bit unsigned integer.
|
||||
|
@ -10,6 +10,7 @@ namespace X10D.Math;
|
||||
[CLSCompliant(false)]
|
||||
public static class UInt32Extensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of the current 32-bit unsigned integer.
|
||||
/// </summary>
|
||||
@ -26,6 +27,7 @@ public static class UInt32Extensions
|
||||
uint root = value % 9;
|
||||
return root == 0 ? 9 : root;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 32-bit unsigned integer.
|
||||
|
@ -10,6 +10,7 @@ namespace X10D.Math;
|
||||
[CLSCompliant(false)]
|
||||
public static class UInt64Extensions
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Computes the digital root of the current 64-bit unsigned integer.
|
||||
/// </summary>
|
||||
@ -26,6 +27,7 @@ public static class UInt64Extensions
|
||||
ulong root = value % 9;
|
||||
return root == 0 ? 9 : root;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the factorial of the current 64-bit unsigned integer.
|
||||
|
@ -32,7 +32,7 @@ public static class Int16Extensions
|
||||
value++;
|
||||
}
|
||||
|
||||
return value.Mod(4) == 0 && (value.Mod(100) != 0 || value.Mod(400) == 0);
|
||||
return value.Mod((short)4) == 0 && (value.Mod((short)100) != 0 || value.Mod((short)400) == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -33,7 +33,7 @@ public static class SByteExtensions
|
||||
value++;
|
||||
}
|
||||
|
||||
return value.Mod(4) == 0 && value.Mod(100) != 0; // mod 400 not required, sbyte.MaxValue is 127 anyway
|
||||
return value.Mod((sbyte)4) == 0 && value.Mod((sbyte)100) != 0; // mod 400 not required, sbyte.MaxValue is 127 anyway
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
Loading…
Reference in New Issue
Block a user