Added Factorial method

This commit is contained in:
Oliver Booth 2022-04-23 10:21:07 +01:00
parent c1d19e650b
commit 7d227ad2a8
No known key found for this signature in database
GPG Key ID: 32A00B35503AF634
17 changed files with 473 additions and 0 deletions

View File

@ -9,6 +9,7 @@
- Added `All` and `Any` for `Span<T>` and `ReadOnlySpan<T>`, mimicking the corresponding methods in `System.Linq`
- Added time-related extension methods (`Ticks`, `Milliseconds`, `Seconds`, `Minutes`, `Hours`, `Days`, and `Weeks`) to all built-in numeric types
- Added `TimeSpan.Ago()` and `TimeSpan.FromNow()`
- Added `Factorial` extension method for built-in numeric types
- Added `FileInfo.GetHash<T>()`
- Added `FileInfo.TryWriteHash<T>(Span<byte>, out int)`
- Added `IEnumerable<TSource>.Product()` and `IEnumerable<TSource>.Product<TResult>(Func<TSource>, TResult)` for all built-in numeric types, computing the product of all (transformed) elements

View File

@ -0,0 +1,24 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class ByteTests
{
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, ((byte)0).Factorial());
Assert.AreEqual(1L, ((byte)1).Factorial());
Assert.AreEqual(2L, ((byte)2).Factorial());
Assert.AreEqual(6L, ((byte)3).Factorial());
Assert.AreEqual(24L, ((byte)4).Factorial());
Assert.AreEqual(120L, ((byte)5).Factorial());
Assert.AreEqual(720L, ((byte)6).Factorial());
Assert.AreEqual(5040L, ((byte)7).Factorial());
Assert.AreEqual(40320L, ((byte)8).Factorial());
Assert.AreEqual(362880L, ((byte)9).Factorial());
Assert.AreEqual(3628800L, ((byte)10).Factorial());
}
}

View File

@ -0,0 +1,30 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class Int16Tests
{
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, ((short)0).Factorial());
Assert.AreEqual(1L, ((short)1).Factorial());
Assert.AreEqual(2L, ((short)2).Factorial());
Assert.AreEqual(6L, ((short)3).Factorial());
Assert.AreEqual(24L, ((short)4).Factorial());
Assert.AreEqual(120L, ((short)5).Factorial());
Assert.AreEqual(720L, ((short)6).Factorial());
Assert.AreEqual(5040L, ((short)7).Factorial());
Assert.AreEqual(40320L, ((short)8).Factorial());
Assert.AreEqual(362880L, ((short)9).Factorial());
Assert.AreEqual(3628800L, ((short)10).Factorial());
}
[TestMethod]
public void NegativeFactorialShouldThrow()
{
Assert.ThrowsException<ArithmeticException>(() => ((short)-1).Factorial());
}
}

View File

@ -0,0 +1,30 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class Int32Tests
{
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, 0.Factorial());
Assert.AreEqual(1L, 1.Factorial());
Assert.AreEqual(2L, 2.Factorial());
Assert.AreEqual(6L, 3.Factorial());
Assert.AreEqual(24L, 4.Factorial());
Assert.AreEqual(120L, 5.Factorial());
Assert.AreEqual(720L, 6.Factorial());
Assert.AreEqual(5040L, 7.Factorial());
Assert.AreEqual(40320L, 8.Factorial());
Assert.AreEqual(362880L, 9.Factorial());
Assert.AreEqual(3628800L, 10.Factorial());
}
[TestMethod]
public void NegativeFactorialShouldThrow()
{
Assert.ThrowsException<ArithmeticException>(() => (-1).Factorial());
}
}

View File

@ -0,0 +1,30 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class Int64Tests
{
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, 0L.Factorial());
Assert.AreEqual(1L, 1L.Factorial());
Assert.AreEqual(2L, 2L.Factorial());
Assert.AreEqual(6L, 3L.Factorial());
Assert.AreEqual(24L, 4L.Factorial());
Assert.AreEqual(120L, 5L.Factorial());
Assert.AreEqual(720L, 6L.Factorial());
Assert.AreEqual(5040L, 7L.Factorial());
Assert.AreEqual(40320L, 8L.Factorial());
Assert.AreEqual(362880L, 9L.Factorial());
Assert.AreEqual(3628800L, 10L.Factorial());
}
[TestMethod]
public void NegativeFactorialShouldThrow()
{
Assert.ThrowsException<ArithmeticException>(() => (-1L).Factorial());
}
}

View File

@ -0,0 +1,31 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
[CLSCompliant(false)]
public class SByteTests
{
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, ((sbyte)0).Factorial());
Assert.AreEqual(1L, ((sbyte)1).Factorial());
Assert.AreEqual(2L, ((sbyte)2).Factorial());
Assert.AreEqual(6L, ((sbyte)3).Factorial());
Assert.AreEqual(24L, ((sbyte)4).Factorial());
Assert.AreEqual(120L, ((sbyte)5).Factorial());
Assert.AreEqual(720L, ((sbyte)6).Factorial());
Assert.AreEqual(5040L, ((sbyte)7).Factorial());
Assert.AreEqual(40320L, ((sbyte)8).Factorial());
Assert.AreEqual(362880L, ((sbyte)9).Factorial());
Assert.AreEqual(3628800L, ((sbyte)10).Factorial());
}
[TestMethod]
public void NegativeFactorialShouldThrow()
{
Assert.ThrowsException<ArithmeticException>(() => ((sbyte)-1).Factorial());
}
}

View File

@ -0,0 +1,25 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
[CLSCompliant(false)]
public class UInt16Tests
{
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1UL, ((ushort)0).Factorial());
Assert.AreEqual(1UL, ((ushort)1).Factorial());
Assert.AreEqual(2UL, ((ushort)2).Factorial());
Assert.AreEqual(6UL, ((ushort)3).Factorial());
Assert.AreEqual(24UL, ((ushort)4).Factorial());
Assert.AreEqual(120UL, ((ushort)5).Factorial());
Assert.AreEqual(720UL, ((ushort)6).Factorial());
Assert.AreEqual(5040UL, ((ushort)7).Factorial());
Assert.AreEqual(40320UL, ((ushort)8).Factorial());
Assert.AreEqual(362880UL, ((ushort)9).Factorial());
Assert.AreEqual(3628800UL, ((ushort)10).Factorial());
}
}

View File

@ -0,0 +1,25 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
[CLSCompliant(false)]
public class UInt32Tests
{
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1UL, 0U.Factorial());
Assert.AreEqual(1UL, 1U.Factorial());
Assert.AreEqual(2UL, 2U.Factorial());
Assert.AreEqual(6UL, 3U.Factorial());
Assert.AreEqual(24UL, 4U.Factorial());
Assert.AreEqual(120UL, 5U.Factorial());
Assert.AreEqual(720UL, 6U.Factorial());
Assert.AreEqual(5040UL, 7U.Factorial());
Assert.AreEqual(40320UL, 8U.Factorial());
Assert.AreEqual(362880UL, 9U.Factorial());
Assert.AreEqual(3628800UL, 10U.Factorial());
}
}

View File

@ -0,0 +1,25 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
[CLSCompliant(false)]
public class UInt64Tests
{
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1UL, 0UL.Factorial());
Assert.AreEqual(1UL, 1UL.Factorial());
Assert.AreEqual(2UL, 2UL.Factorial());
Assert.AreEqual(6UL, 3UL.Factorial());
Assert.AreEqual(24UL, 4UL.Factorial());
Assert.AreEqual(120UL, 5UL.Factorial());
Assert.AreEqual(720UL, 6UL.Factorial());
Assert.AreEqual(5040UL, 7UL.Factorial());
Assert.AreEqual(40320UL, 8UL.Factorial());
Assert.AreEqual(362880UL, 9UL.Factorial());
Assert.AreEqual(3628800UL, 10UL.Factorial());
}
}

View File

@ -0,0 +1,28 @@
namespace X10D.Math;
/// <summary>
/// Extension methods for <see cref="byte" />.
/// </summary>
public static class ByteExtensions
{
/// <summary>
/// Returns the factorial of the current 8-bit unsigned integer.
/// </summary>
/// <param name="value">The value whose factorial to compute.</param>
/// <returns>The factorial of <paramref name="value" />.</returns>
public static long Factorial(this byte value)
{
if (value == 0)
{
return 1;
}
var result = 1L;
for (byte i = 1; i <= value; i++)
{
result *= i;
}
return result;
}
}

View File

@ -0,0 +1,34 @@
namespace X10D.Math;
/// <summary>
/// Extension methods for <see cref="short" />.
/// </summary>
public static class Int16Extensions
{
/// <summary>
/// Returns the factorial of the current 16-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>
public static long Factorial(this short value)
{
if (value < 0)
{
throw new ArithmeticException(nameof(value));
}
if (value == 0)
{
return 1;
}
var result = 1L;
for (short i = 1; i <= value; i++)
{
result *= i;
}
return result;
}
}

View File

@ -0,0 +1,34 @@
namespace X10D.Math;
/// <summary>
/// Extension methods for <see cref="int" />.
/// </summary>
public static class Int32Extensions
{
/// <summary>
/// Returns the factorial of the current 32-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>
public static long Factorial(this int value)
{
if (value < 0)
{
throw new ArithmeticException(nameof(value));
}
if (value == 0)
{
return 1;
}
var result = 1L;
for (var i = 1; i <= value; i++)
{
result *= i;
}
return result;
}
}

View File

@ -0,0 +1,34 @@
namespace X10D.Math;
/// <summary>
/// Extension methods for <see cref="long" />.
/// </summary>
public static class Int64Extensions
{
/// <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>
public static long Factorial(this long value)
{
if (value < 0)
{
throw new ArithmeticException(nameof(value));
}
if (value == 0)
{
return 1;
}
var result = 1L;
for (var i = 1L; i <= value; i++)
{
result *= i;
}
return result;
}
}

View File

@ -0,0 +1,35 @@
namespace X10D.Math;
/// <summary>
/// Extension methods for <see cref="sbyte" />.
/// </summary>
[CLSCompliant(false)]
public static class SByteExtensions
{
/// <summary>
/// Returns the factorial of the current 8-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>
public static long Factorial(this sbyte value)
{
if (value < 0)
{
throw new ArithmeticException(nameof(value));
}
if (value == 0)
{
return 1;
}
var result = 1L;
for (ushort i = 1; i <= value; i++)
{
result *= i;
}
return result;
}
}

View File

@ -0,0 +1,29 @@
namespace X10D.Math;
/// <summary>
/// Extension methods for <see cref="ushort" />.
/// </summary>
[CLSCompliant(false)]
public static class UInt16Extensions
{
/// <summary>
/// Returns the factorial of the current 16-bit unsigned integer.
/// </summary>
/// <param name="value">The value whose factorial to compute.</param>
/// <returns>The factorial of <paramref name="value" />.</returns>
public static ulong Factorial(this ushort value)
{
if (value == 0)
{
return 1;
}
var result = 1UL;
for (ushort i = 1; i <= value; i++)
{
result *= i;
}
return result;
}
}

View File

@ -0,0 +1,29 @@
namespace X10D.Math;
/// <summary>
/// Extension methods for <see cref="uint" />.
/// </summary>
[CLSCompliant(false)]
public static class UInt32Extensions
{
/// <summary>
/// Returns the factorial of the current 32-bit unsigned integer.
/// </summary>
/// <param name="value">The value whose factorial to compute.</param>
/// <returns>The factorial of <paramref name="value" />.</returns>
public static ulong Factorial(this uint value)
{
if (value == 0)
{
return 1;
}
var result = 1UL;
for (var i = 1U; i <= value; i++)
{
result *= i;
}
return result;
}
}

View File

@ -0,0 +1,29 @@
namespace X10D.Math;
/// <summary>
/// Extension methods for <see cref="ulong" />.
/// </summary>
[CLSCompliant(false)]
public static class UInt64Extensions
{
/// <summary>
/// Returns the factorial of the current 64-bit unsigned integer.
/// </summary>
/// <param name="value">The value whose factorial to compute.</param>
/// <returns>The factorial of <paramref name="value" />.</returns>
public static ulong Factorial(this ulong value)
{
if (value == 0)
{
return 1;
}
var result = 1UL;
for (var i = 1UL; i <= value; i++)
{
result *= i;
}
return result;
}
}