From 2547d4a227378d393909d0d87cc9880b284480e9 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 30 Apr 2022 10:15:36 +0100 Subject: [PATCH] Add comprehensive math tests Introduces extension methods for decimal --- X10D.Tests/src/Core/DoubleTests.cs | 108 ------------ X10D.Tests/src/Core/SingleTests.cs | 61 ------- X10D.Tests/src/Math/DecimalTests.cs | 122 +++++++++++++ X10D.Tests/src/Math/DoubleTests.cs | 242 ++++++++++++++++++++++++++ X10D.Tests/src/Math/SingleTests.cs | 242 ++++++++++++++++++++++++++ X10D/src/Math/DecimalExtensions.cs | 175 +++++++++++++++++++ X10D/src/Math/DoubleExtensions.cs | 27 +++ X10D/src/Math/SingleExtensions.cs | 27 +++ X10D/src/Numerics/DoubleExtensions.cs | 35 ---- X10D/src/Numerics/SingleExtensions.cs | 35 ---- 10 files changed, 835 insertions(+), 239 deletions(-) delete mode 100644 X10D.Tests/src/Core/DoubleTests.cs delete mode 100644 X10D.Tests/src/Core/SingleTests.cs create mode 100644 X10D.Tests/src/Math/DecimalTests.cs create mode 100644 X10D.Tests/src/Math/DoubleTests.cs create mode 100644 X10D.Tests/src/Math/SingleTests.cs create mode 100644 X10D/src/Math/DecimalExtensions.cs delete mode 100644 X10D/src/Numerics/DoubleExtensions.cs delete mode 100644 X10D/src/Numerics/SingleExtensions.cs diff --git a/X10D.Tests/src/Core/DoubleTests.cs b/X10D.Tests/src/Core/DoubleTests.cs deleted file mode 100644 index dbb297e..0000000 --- a/X10D.Tests/src/Core/DoubleTests.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System.Diagnostics; -using System.Numerics; -using X10D.Math; -using X10D.Numerics; - -namespace X10D.Tests.Core; - -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -/// -/// Tests for . -/// -[TestClass] -public class DoubleTests -{ - [TestMethod] - public void ComplexSqrt() - { - Assert.AreEqual(0.0, 0.0.ComplexSqrt()); - Assert.AreEqual(1.414213562373095, 2.0.ComplexSqrt()); - Assert.AreEqual(3.0, 9.0.ComplexSqrt()); - Assert.AreEqual(4.0, 16.0.ComplexSqrt()); - Assert.AreEqual(new Complex(1.414213562373095, 1), (-2.0).ComplexSqrt()); - Assert.AreEqual(new Complex(3.0, 1), (-9.0).ComplexSqrt()); - Assert.AreEqual(new Complex(4.0, 1), (-16.0).ComplexSqrt()); - Assert.AreEqual(Complex.NaN, double.NaN.ComplexSqrt()); - Assert.AreEqual(new Complex(1, 1), (-1.0).ComplexSqrt()); - Assert.AreEqual(Complex.Infinity, double.NegativeInfinity.ComplexSqrt()); - Assert.AreEqual(Complex.Infinity, double.PositiveInfinity.ComplexSqrt()); - } - - /// - /// Tests for . - /// - [TestMethod] - public void DegreesToRadians() - { - Assert.AreEqual(Math.PI, 180.0.DegreesToRadians()); - Assert.AreEqual(Math.PI * 1.5, 270.0.DegreesToRadians()); - Assert.AreEqual(0.0, 0.0.DegreesToRadians()); - Assert.AreEqual(0.017453292519943295, 1.0.DegreesToRadians()); - Assert.AreEqual(0.10471975511965978, 6.0.DegreesToRadians()); - Assert.AreEqual(0.20943951023931956, 12.0.DegreesToRadians()); - } - - /// - /// Tests for . - /// - [TestMethod] - public void IsEven() - { - Assert.IsTrue(2.0.IsEven()); - Assert.IsFalse(1.0.IsEven()); - } - - /// - /// Tests for . - /// - [TestMethod] - public void IsOdd() - { - Assert.IsFalse(2.0.IsOdd()); - Assert.IsTrue(1.0.IsOdd()); - } - - /// - /// Tests for . - /// - [TestMethod] - public void RadiansToDegrees() - { - Assert.AreEqual(180.0, Math.PI.RadiansToDegrees()); - Assert.AreEqual(360.0, (2.0 * Math.PI).RadiansToDegrees()); - Assert.AreEqual(0.0, 0.0.RadiansToDegrees()); - Assert.AreEqual(1.0, 0.017453292519943295.RadiansToDegrees()); - Assert.AreEqual(6.000000000000001, 0.10471975511965978.RadiansToDegrees()); // rounding errors are fun - Assert.AreEqual(12.0, 0.20943951023931953.RadiansToDegrees()); - } - - /// - /// Tests for and . - /// - [TestMethod] - public void Round() - { - Assert.AreEqual(4.0, 3.5.Round()); - Assert.AreEqual(7.0, 6.8.Round()); - Assert.AreEqual(7.0, 7.2.Round()); - - Assert.AreEqual(5.0, 3.5.Round(5)); - Assert.AreEqual(5.0, 7.0.Round(5)); - Assert.AreEqual(10.0, 7.5.Round(5)); - } - - [TestMethod] - public void Sqrt() - { - Assert.AreEqual(0.0, 0.0.Sqrt()); - Assert.AreEqual(1.414213562373095, 2.0.Sqrt()); - Assert.AreEqual(3.0, 9.0.Sqrt()); - Assert.AreEqual(4.0, 16.0.Sqrt()); - Assert.AreEqual(double.NaN, double.NaN.Sqrt()); - Assert.AreEqual(double.NaN, (-1.0).Sqrt()); - Assert.AreEqual(double.NaN, double.NegativeInfinity.Sqrt()); - Assert.AreEqual(double.PositiveInfinity, double.PositiveInfinity.Sqrt()); - } -} diff --git a/X10D.Tests/src/Core/SingleTests.cs b/X10D.Tests/src/Core/SingleTests.cs deleted file mode 100644 index 386dc15..0000000 --- a/X10D.Tests/src/Core/SingleTests.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Numerics; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using X10D.Math; -using X10D.Numerics; - -namespace X10D.Tests.Core; - -[TestClass] -public class SingleTests -{ - [TestMethod] - public void ComplexSqrt() - { - Assert.AreEqual(0.0f, 0.0f.ComplexSqrt()); - Assert.AreEqual(1.4142135f, 2.0f.ComplexSqrt()); - Assert.AreEqual(3.0f, 9.0f.ComplexSqrt()); - Assert.AreEqual(4.0f, 16.0f.ComplexSqrt()); - Assert.AreEqual(new Complex(1.4142135f, 1), (-2.0f).ComplexSqrt()); - Assert.AreEqual(new Complex(3.0f, 1), (-9.0f).ComplexSqrt()); - Assert.AreEqual(new Complex(4.0f, 1), (-16.0f).ComplexSqrt()); - Assert.AreEqual(Complex.NaN, float.NaN.ComplexSqrt()); - Assert.AreEqual(new Complex(1, 1), (-1.0f).ComplexSqrt()); - Assert.AreEqual(Complex.Infinity, float.NegativeInfinity.ComplexSqrt()); - Assert.AreEqual(Complex.Infinity, float.PositiveInfinity.ComplexSqrt()); - } - - [TestMethod] - public void DegreesToRadians() - { - Assert.AreEqual(MathF.PI, 180.0f.DegreesToRadians()); - Assert.AreEqual(MathF.PI * 1.5f, 270.0f.DegreesToRadians()); - Assert.AreEqual(0.0f, 0.0f.DegreesToRadians()); - Assert.AreEqual(0.017453292f, 1.0f.DegreesToRadians()); - Assert.AreEqual(0.10471976f, 6.0f.DegreesToRadians()); - Assert.AreEqual(0.20943952f, 12.0f.DegreesToRadians()); - } - - [TestMethod] - public void RadiansToDegrees() - { - Assert.AreEqual(180.0f, MathF.PI.RadiansToDegrees()); - Assert.AreEqual(270.0f, (MathF.PI * 1.5f).RadiansToDegrees()); - Assert.AreEqual(0.0, 0.0f.RadiansToDegrees()); - Assert.AreEqual(0.99999994f, 0.017453292f.RadiansToDegrees()); // rounding errors are fun - Assert.AreEqual(6.0f, 0.10471976f.RadiansToDegrees()); - Assert.AreEqual(12.0f, 0.20943952f.RadiansToDegrees()); - } - - [TestMethod] - public void Sqrt() - { - Assert.AreEqual(0.0f, 0.0f.Sqrt()); - Assert.AreEqual(1.4142135f, 2.0f.Sqrt()); - Assert.AreEqual(3.0f, 9.0f.Sqrt()); - Assert.AreEqual(4.0f, 16.0f.Sqrt()); - Assert.AreEqual(float.NaN, float.NaN.Sqrt()); - Assert.AreEqual(float.NaN, (-1.0f).Sqrt()); - Assert.AreEqual(float.NaN, float.NegativeInfinity.Sqrt()); - Assert.AreEqual(float.PositiveInfinity, float.PositiveInfinity.Sqrt()); - } -} diff --git a/X10D.Tests/src/Math/DecimalTests.cs b/X10D.Tests/src/Math/DecimalTests.cs new file mode 100644 index 0000000..a8ce150 --- /dev/null +++ b/X10D.Tests/src/Math/DecimalTests.cs @@ -0,0 +1,122 @@ +using System.Numerics; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.Math; + +namespace X10D.Tests.Math; + +[TestClass] +public class DecimalTests +{ + [TestMethod] + public void ComplexSqrt_ShouldBeCorrect_GivenReal() + { + Assert.AreEqual(0.0, 0.0m.ComplexSqrt()); + Assert.AreEqual(1.4142135623730951, 2.0m.ComplexSqrt()); + Assert.AreEqual(3.0, 9.0m.ComplexSqrt()); + Assert.AreEqual(4.0, 16.0m.ComplexSqrt()); + Assert.AreEqual(100.0, 10000.0m.ComplexSqrt()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeImaginary_GivenNegativeValue() + { + Assert.AreEqual(new Complex(0, 1), (-1.0m).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 1.4142135623730951), (-2.0m).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 3.0), (-9.0m).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 4.0), (-16.0m).ComplexSqrt()); + } + + [TestMethod] + public void IsEven_ShouldBeFalse_GivenOddNumber() + { + Assert.IsFalse((-3.0m).IsEven()); + Assert.IsFalse((-1.0m).IsEven()); + Assert.IsFalse(1.0m.IsEven()); + Assert.IsFalse(3.0m.IsEven()); + } + + [TestMethod] + public void IsEven_ShouldBeTrue_GivenOddNumber() + { + Assert.IsTrue((-4.0m).IsEven()); + Assert.IsTrue((-2.0m).IsEven()); + Assert.IsTrue(0.0m.IsEven()); + Assert.IsTrue(2.0m.IsEven()); + Assert.IsTrue(4.0m.IsEven()); + } + + [TestMethod] + public void IsOdd_ShouldBeFalse_GivenEvenNumber() + { + Assert.IsFalse((-4.0m).IsOdd()); + Assert.IsFalse((-2.0m).IsOdd()); + Assert.IsFalse(0.0m.IsOdd()); + Assert.IsFalse(2.0m.IsOdd()); + Assert.IsFalse(4.0m.IsOdd()); + } + + [TestMethod] + public void IsOdd_ShouldBeTrue_GivenOddNumber() + { + Assert.IsTrue((-3.0m).IsOdd()); + Assert.IsTrue((-1.0m).IsOdd()); + Assert.IsTrue(1.0m.IsOdd()); + Assert.IsTrue(3.0m.IsOdd()); + } + + [TestMethod] + public void Round_ShouldRoundToNearestInteger() + { + Assert.AreEqual(4.0m, 3.5m.Round()); + Assert.AreEqual(7.0m, 6.8m.Round()); + Assert.AreEqual(7.0m, 7.2m.Round()); + } + + [TestMethod] + public void Round_ShouldRoundToNearestMultiple() + { + Assert.AreEqual(5.0m, 3.5m.Round(5)); + Assert.AreEqual(5.0m, 7.0m.Round(5)); + Assert.AreEqual(10.0m, 7.5m.Round(5)); + } + + [TestMethod] + public void Sign_ShouldBeMinus1_GivenNegative() + { + Assert.AreEqual(-1, -1.0m.Sign()); + Assert.AreEqual(-1, -2.0m.Sign()); + Assert.AreEqual(-1, -3.0m.Sign()); + } + + [TestMethod] + public void Sign_ShouldBe0_Given0() + { + Assert.AreEqual(0, 0.0m.Sign()); + } + + [TestMethod] + public void Sign_ShouldBe1_GivenPositive() + { + Assert.AreEqual(1, 1.0m.Sign()); + Assert.AreEqual(1, 2.0m.Sign()); + Assert.AreEqual(1, 3.0m.Sign()); + } + + [TestMethod] + public void Sqrt_ShouldBeCorrect_GivenValue() + { + Assert.AreEqual(0.0m, 0.0m.Sqrt()); + Assert.AreEqual(1.4142135623730950488016887242m, 2.0m.Sqrt()); + Assert.AreEqual(3.0m, 9.0m.Sqrt()); + Assert.AreEqual(4.0m, 16.0m.Sqrt()); + Assert.AreEqual(100.0m, 10000.0m.Sqrt()); + } + + [TestMethod] + public void Sqrt_ShouldThrow_GivenNegativeValue() + { + Assert.ThrowsException(() => (-1.0m).Sqrt()); + Assert.ThrowsException(() => (-2.0m).Sqrt()); + Assert.ThrowsException(() => (-3.0m).Sqrt()); + } +} diff --git a/X10D.Tests/src/Math/DoubleTests.cs b/X10D.Tests/src/Math/DoubleTests.cs new file mode 100644 index 0000000..de49ba0 --- /dev/null +++ b/X10D.Tests/src/Math/DoubleTests.cs @@ -0,0 +1,242 @@ +using System.Numerics; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.Math; + +namespace X10D.Tests.Math; + +[TestClass] +public class DoubleTests +{ + [TestMethod] + public void DegreesToRadians_ShouldBeCorrect() + { + Assert.AreEqual(System.Math.PI, 180.0.DegreesToRadians()); + Assert.AreEqual(System.Math.PI * 1.5, 270.0.DegreesToRadians()); + Assert.AreEqual(0.0, 0.0.DegreesToRadians()); + Assert.AreEqual(0.017453292519943295, 1.0.DegreesToRadians()); + Assert.AreEqual(0.10471975511965978, 6.0.DegreesToRadians()); + Assert.AreEqual(0.20943951023931956, 12.0.DegreesToRadians()); + } + + [TestMethod] + public void RadiansToDegrees_ShouldBeCorrect() + { + Assert.AreEqual(180.0, System.Math.PI.RadiansToDegrees()); + Assert.AreEqual(360.0, (2.0 * System.Math.PI).RadiansToDegrees()); + Assert.AreEqual(0.0, 0.0.RadiansToDegrees()); + Assert.AreEqual(1.0, 0.017453292519943295.RadiansToDegrees()); + Assert.AreEqual(6.000000000000001, 0.10471975511965978.RadiansToDegrees()); // rounding errors are fun + Assert.AreEqual(12.0, 0.20943951023931953.RadiansToDegrees()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeCorrect_GivenReal() + { + Assert.AreEqual(0.0, 0.0.ComplexSqrt()); + Assert.AreEqual(1.4142135623730951, 2.0.ComplexSqrt()); + Assert.AreEqual(3.0, 9.0.ComplexSqrt()); + Assert.AreEqual(4.0, 16.0.ComplexSqrt()); + Assert.AreEqual(100.0, 10000.0.ComplexSqrt()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeImaginary_GivenNegativeValue() + { + Assert.AreEqual(new Complex(0, 1), (-1.0).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 1.4142135623730951), (-2.0).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 3.0), (-9.0).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 4.0), (-16.0).ComplexSqrt()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeComplexInfinity_GivenInfinity() + { + Assert.AreEqual(Complex.Infinity, double.NegativeInfinity.ComplexSqrt()); + Assert.AreEqual(Complex.Infinity, double.PositiveInfinity.ComplexSqrt()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeNaN_GivenNaN() + { + Assert.AreEqual(Complex.NaN, double.NaN.ComplexSqrt()); + } + + [TestMethod] + public void IsEven_ShouldBeFalse_GivenOddNumber() + { + Assert.IsFalse((-3.0).IsEven()); + Assert.IsFalse((-1.0).IsEven()); + Assert.IsFalse(1.0.IsEven()); + Assert.IsFalse(3.0.IsEven()); + } + + [TestMethod] + public void IsEven_ShouldBeTrue_GivenOddNumber() + { + Assert.IsTrue((-4.0).IsEven()); + Assert.IsTrue((-2.0).IsEven()); + Assert.IsTrue(0.0.IsEven()); + Assert.IsTrue(2.0.IsEven()); + Assert.IsTrue(4.0.IsEven()); + } + + [TestMethod] + public void IsOdd_ShouldBeFalse_GivenEvenNumber() + { + Assert.IsFalse((-4.0).IsOdd()); + Assert.IsFalse((-2.0).IsOdd()); + Assert.IsFalse(0.0.IsOdd()); + Assert.IsFalse(2.0.IsOdd()); + Assert.IsFalse(4.0.IsOdd()); + } + + [TestMethod] + public void IsOdd_ShouldBeTrue_GivenOddNumber() + { + Assert.IsTrue((-3.0).IsOdd()); + Assert.IsTrue((-1.0).IsOdd()); + Assert.IsTrue(1.0.IsOdd()); + Assert.IsTrue(3.0.IsOdd()); + } + + [TestMethod] + public void Round_ShouldRoundToNearestInteger() + { + Assert.AreEqual(4.0, 3.5.Round()); + Assert.AreEqual(7.0, 6.8.Round()); + Assert.AreEqual(7.0, 7.2.Round()); + } + + [TestMethod] + public void Round_ShouldRoundToNearestMultiple() + { + Assert.AreEqual(5.0, 3.5.Round(5)); + Assert.AreEqual(5.0, 7.0.Round(5)); + Assert.AreEqual(10.0, 7.5.Round(5)); + } + + [TestMethod] + public void Sign_ShouldBeMinus1_GivenNegative() + { + Assert.AreEqual(-1, -1.0.Sign()); + Assert.AreEqual(-1, -2.0.Sign()); + Assert.AreEqual(-1, -3.0.Sign()); + } + + [TestMethod] + public void Sign_ShouldBe0_Given0() + { + Assert.AreEqual(0, 0.0.Sign()); + } + + [TestMethod] + public void Sign_ShouldBe1_GivenPositive() + { + Assert.AreEqual(1, 1.0.Sign()); + Assert.AreEqual(1, 2.0.Sign()); + Assert.AreEqual(1, 3.0.Sign()); + } + + [TestMethod] + public void Sqrt_ShouldBeCorrect_GivenValue() + { + Assert.AreEqual(0.0, 0.0.Sqrt()); + Assert.AreEqual(1.414213562373095, 2.0.Sqrt()); + Assert.AreEqual(3.0, 9.0.Sqrt()); + Assert.AreEqual(4.0, 16.0.Sqrt()); + Assert.AreEqual(100.0, 10000.0.Sqrt()); + } + + [TestMethod] + public void Sqrt_ShouldBeNaN_GivenNaN() + { + Assert.AreEqual(double.NaN, double.NaN.Sqrt()); + } + + [TestMethod] + public void Sqrt_ShouldBeNaN_GivenNegativeValue() + { + Assert.AreEqual(double.NaN, (-1.0).Sqrt()); + Assert.AreEqual(double.NaN, (-2.0).Sqrt()); + Assert.AreEqual(double.NaN, (-3.0).Sqrt()); + Assert.AreEqual(double.NaN, double.NegativeInfinity.Sqrt()); + } + + [TestMethod] + public void Sqrt_ShouldBePositiveInfinity_GivenPositiveInfinity() + { + Assert.AreEqual(double.PositiveInfinity, double.PositiveInfinity.Sqrt()); + } + + [TestMethod] + public void Acos_ShouldBeCorrect() + { + Assert.AreEqual(1.0471975511965979, 0.5.Acos()); + } + + [TestMethod] + public void Acosh_ShouldBeCorrect() + { + Assert.AreEqual(0.9624236501192069, 1.5.Acosh()); + } + + [TestMethod] + public void Asin_ShouldBeCorrect() + { + Assert.AreEqual(0.5235987755982989, 0.5.Asin()); + } + + [TestMethod] + public void Asinh_ShouldBeCorrect() + { + Assert.AreEqual(1.1947632172871094, 1.5.Asinh()); + } + + [TestMethod] + public void Atan_ShouldBeCorrect() + { + Assert.AreEqual(0.4636476090008061, 0.5.Atan()); + } + + [TestMethod] + public void Atanh_ShouldBeCorrect() + { + Assert.AreEqual(0.5493061443340549, 0.5.Atanh()); + } + + [TestMethod] + public void Cos_ShouldBeCorrect() + { + Assert.AreEqual(0.8775825618903728, 0.5.Cos()); + } + + [TestMethod] + public void Cosh_ShouldBeCorrect() + { + Assert.AreEqual(2.352409615243247, 1.5.Cosh()); + } + + [TestMethod] + public void Sin_ShouldBeCorrect() + { + Assert.AreEqual(0.479425538604203, 0.5.Sin()); + } + + [TestMethod] + public void Sinh_ShouldBeCorrect() + { + Assert.AreEqual(2.1292794550948173, 1.5.Sinh()); + } + + [TestMethod] + public void Tan_ShouldBeCorrect() + { + Assert.AreEqual(0.5463024898437905, 0.5.Tan()); + } + + [TestMethod] + public void Tanh_ShouldBeCorrect() + { + Assert.AreEqual(0.46211715726000974, 0.5.Tanh()); + } +} diff --git a/X10D.Tests/src/Math/SingleTests.cs b/X10D.Tests/src/Math/SingleTests.cs new file mode 100644 index 0000000..0a48dd2 --- /dev/null +++ b/X10D.Tests/src/Math/SingleTests.cs @@ -0,0 +1,242 @@ +using System.Numerics; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.Math; + +namespace X10D.Tests.Math; + +[TestClass] +public class SingleTests +{ + [TestMethod] + public void DegreesToRadians_ShouldBeCorrect() + { + Assert.AreEqual(MathF.PI, 180.0f.DegreesToRadians()); + Assert.AreEqual(MathF.PI * 1.5f, 270.0f.DegreesToRadians()); + Assert.AreEqual(0.0f, 0.0f.DegreesToRadians()); + Assert.AreEqual(0.017453292f, 1.0f.DegreesToRadians()); + Assert.AreEqual(0.10471976f, 6.0f.DegreesToRadians()); + Assert.AreEqual(0.20943952f, 12.0f.DegreesToRadians()); + } + + [TestMethod] + public void RadiansToDegrees_ShouldBeCorrect() + { + Assert.AreEqual(180.0f, MathF.PI.RadiansToDegrees()); + Assert.AreEqual(270.0f, (MathF.PI * 1.5f).RadiansToDegrees()); + Assert.AreEqual(0.0, 0.0f.RadiansToDegrees()); + Assert.AreEqual(0.99999994f, 0.017453292f.RadiansToDegrees()); // rounding errors are fun + Assert.AreEqual(6.0f, 0.10471976f.RadiansToDegrees()); + Assert.AreEqual(12.0f, 0.20943952f.RadiansToDegrees()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeCorrect_GivenReal() + { + Assert.AreEqual(0.0f, 0.0f.ComplexSqrt()); + Assert.AreEqual(1.4142135f, 2.0f.ComplexSqrt()); + Assert.AreEqual(3.0f, 9.0f.ComplexSqrt()); + Assert.AreEqual(4.0f, 16.0f.ComplexSqrt()); + Assert.AreEqual(100.0f, 10000.0f.ComplexSqrt()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeImaginary_GivenNegativeValue() + { + Assert.AreEqual(new Complex(0, 1), (-1.0f).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 1.4142135f), (-2.0f).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 3.0f), (-9.0f).ComplexSqrt()); + Assert.AreEqual(new Complex(0, 4.0f), (-16.0f).ComplexSqrt()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeComplexInfinity_GivenInfinity() + { + Assert.AreEqual(Complex.Infinity, float.NegativeInfinity.ComplexSqrt()); + Assert.AreEqual(Complex.Infinity, float.PositiveInfinity.ComplexSqrt()); + } + + [TestMethod] + public void ComplexSqrt_ShouldBeNaN_GivenNaN() + { + Assert.AreEqual(Complex.NaN, float.NaN.ComplexSqrt()); + } + + [TestMethod] + public void IsEven_ShouldBeFalse_GivenOddNumber() + { + Assert.IsFalse((-3.0f).IsEven()); + Assert.IsFalse((-1.0f).IsEven()); + Assert.IsFalse(1.0f.IsEven()); + Assert.IsFalse(3.0f.IsEven()); + } + + [TestMethod] + public void IsEven_ShouldBeTrue_GivenOddNumber() + { + Assert.IsTrue((-4.0f).IsEven()); + Assert.IsTrue((-2.0f).IsEven()); + Assert.IsTrue(0.0f.IsEven()); + Assert.IsTrue(2.0f.IsEven()); + Assert.IsTrue(4.0f.IsEven()); + } + + [TestMethod] + public void IsOdd_ShouldBeFalse_GivenEvenNumber() + { + Assert.IsFalse((-4.0f).IsOdd()); + Assert.IsFalse((-2.0f).IsOdd()); + Assert.IsFalse(0.0f.IsOdd()); + Assert.IsFalse(2.0f.IsOdd()); + Assert.IsFalse(4.0f.IsOdd()); + } + + [TestMethod] + public void IsOdd_ShouldBeTrue_GivenOddNumber() + { + Assert.IsTrue((-3.0f).IsOdd()); + Assert.IsTrue((-1.0f).IsOdd()); + Assert.IsTrue(1.0f.IsOdd()); + Assert.IsTrue(3.0f.IsOdd()); + } + + [TestMethod] + public void Round_ShouldRoundToNearestInteger() + { + Assert.AreEqual(4.0f, 3.5f.Round()); + Assert.AreEqual(7.0f, 6.8f.Round()); + Assert.AreEqual(7.0f, 7.2f.Round()); + } + + [TestMethod] + public void Round_ShouldRoundToNearestMultiple() + { + Assert.AreEqual(5.0f, 3.5f.Round(5)); + Assert.AreEqual(5.0f, 7.0f.Round(5)); + Assert.AreEqual(10.0f, 7.5f.Round(5)); + } + + [TestMethod] + public void Sign_ShouldBeMinus1_GivenNegative() + { + Assert.AreEqual(-1, -1.0f.Sign()); + Assert.AreEqual(-1, -2.0f.Sign()); + Assert.AreEqual(-1, -3.0f.Sign()); + } + + [TestMethod] + public void Sign_ShouldBe0_Given0() + { + Assert.AreEqual(0, 0.0f.Sign()); + } + + [TestMethod] + public void Sign_ShouldBe1_GivenPositive() + { + Assert.AreEqual(1, 1.0f.Sign()); + Assert.AreEqual(1, 2.0f.Sign()); + Assert.AreEqual(1, 3.0f.Sign()); + } + + [TestMethod] + public void Sqrt_ShouldBeCorrect_GivenValue() + { + Assert.AreEqual(0.0f, 0.0f.Sqrt()); + Assert.AreEqual(1.4142135f, 2.0f.Sqrt()); + Assert.AreEqual(3.0f, 9.0f.Sqrt()); + Assert.AreEqual(4.0f, 16.0f.Sqrt()); + Assert.AreEqual(100.0f, 10000.0f.Sqrt()); + } + + [TestMethod] + public void Sqrt_ShouldBeNaN_GivenNaN() + { + Assert.AreEqual(float.NaN, float.NaN.Sqrt()); + } + + [TestMethod] + public void Sqrt_ShouldBeNaN_GivenNegativeValue() + { + Assert.AreEqual(float.NaN, (-1.0f).Sqrt()); + Assert.AreEqual(float.NaN, (-2.0f).Sqrt()); + Assert.AreEqual(float.NaN, (-3.0f).Sqrt()); + Assert.AreEqual(float.NaN, float.NegativeInfinity.Sqrt()); + } + + [TestMethod] + public void Sqrt_ShouldBePositiveInfinity_GivenPositiveInfinity() + { + Assert.AreEqual(float.PositiveInfinity, float.PositiveInfinity.Sqrt()); + } + + [TestMethod] + public void Acos_ShouldBeCorrect() + { + Assert.AreEqual(1.0471975803375244f, 0.5f.Acos()); + } + + [TestMethod] + public void Acosh_ShouldBeCorrect() + { + Assert.AreEqual(0.9624236822128296f, 1.5f.Acosh()); + } + + [TestMethod] + public void Asin_ShouldBeCorrect() + { + Assert.AreEqual(0.5235987901687622f, 0.5f.Asin()); + } + + [TestMethod] + public void Asinh_ShouldBeCorrect() + { + Assert.AreEqual(1.19476318359375f, 1.5f.Asinh()); + } + + [TestMethod] + public void Atan_ShouldBeCorrect() + { + Assert.AreEqual(0.46364760398864746, 0.5f.Atan()); + } + + [TestMethod] + public void Atanh_ShouldBeCorrect() + { + Assert.AreEqual(0.5493061542510986f, 0.5f.Atanh()); + } + + [TestMethod] + public void Cos_ShouldBeCorrect() + { + Assert.AreEqual(0.8775825500488281f, 0.5f.Cos()); + } + + [TestMethod] + public void Cosh_ShouldBeCorrect() + { + Assert.AreEqual(2.352409601211548f, 1.5f.Cosh()); + } + + [TestMethod] + public void Sin_ShouldBeCorrect() + { + Assert.AreEqual(0.4794255495071411, 0.5f.Sin()); + } + + [TestMethod] + public void Sinh_ShouldBeCorrect() + { + Assert.AreEqual(2.129279375076294f, 1.5f.Sinh()); + } + + [TestMethod] + public void Tan_ShouldBeCorrect() + { + Assert.AreEqual(0.4794255495071411f, 0.5f.Tan()); + } + + [TestMethod] + public void Tanh_ShouldBeCorrect() + { + Assert.AreEqual(0.46211716532707214f, 0.5f.Tanh()); + } +} diff --git a/X10D/src/Math/DecimalExtensions.cs b/X10D/src/Math/DecimalExtensions.cs new file mode 100644 index 0000000..18a80cc --- /dev/null +++ b/X10D/src/Math/DecimalExtensions.cs @@ -0,0 +1,175 @@ +using System.Diagnostics.Contracts; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace X10D.Math; + +/// +/// Extension methods for . +/// +public static class DecimalExtensions +{ + /// + /// Returns the complex square root of this decimal number. + /// + /// The number whose square root is to be found. + /// The square root of . + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static Complex ComplexSqrt(this decimal value) + { + return Complex.Sqrt((double)value); + } + + + /// + /// Returns a value indicating whether the current value is evenly divisible by 2. + /// + /// The value whose parity to check. + /// + /// if is evenly divisible by 2, or + /// otherwise. + /// + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static bool IsEven(this decimal value) + { + return value % 2.0m == 0.0m; + } + + /// + /// Returns a value indicating whether the current value is not evenly divisible by 2. + /// + /// The value whose parity to check. + /// + /// if is not evenly divisible by 2, or + /// otherwise. + /// + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static bool IsOdd(this decimal value) + { + return !value.IsEven(); + } + + + /// + /// Rounds the current value to the nearest whole number. + /// + /// The value to round. + /// rounded to the nearest whole number. + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static decimal Round(this decimal value) + { + return value.Round(1.0m); + } + + /// + /// Rounds the current value to the nearest multiple of a specified number. + /// + /// The value to round. + /// The nearest multiple to which should be rounded. + /// rounded to the nearest multiple of . + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static decimal Round(this decimal value, decimal nearest) + { + return System.Math.Round(value / nearest) * nearest; + } + + /// + /// Returns an integer that indicates the sign of this decimal number. + /// + /// A signed number. + /// + /// A number that indicates the sign of , as shown in the following table. + /// + /// + /// + /// Return value + /// Meaning + /// + /// + /// + /// -1 + /// is less than zero. + /// + /// + /// 0 + /// is equal to zero. + /// + /// + /// 1 + /// is greater than zero. + /// + /// + /// + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static int Sign(this decimal value) + { + return System.Math.Sign(value); + } + + /// + /// Returns the square root of this double-precision floating-point number. + /// + /// The number whose square root is to be found. + /// + /// One of the values in the following table. + /// + /// + /// + /// Return value + /// Meaning + /// + /// + /// + /// The positive square root of . + /// is greater than or equal to 0. + /// + /// + /// + /// is equal to or is negative. + /// + /// + /// + /// is equal to . + /// + /// + /// + /// is negative. + /// + /// For negative input, this method returns . To receive a complex number, see + /// . + /// + /// + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static decimal Sqrt(this decimal value) + { + switch (value) + { + case 0: + return 0; + case < 0: + throw new ArgumentException("value cannot be negative", nameof(value)); + } + + decimal previous; + var current = (decimal)System.Math.Sqrt((double)value); + do + { + previous = current; + if (previous == 0.0m) + { + return 0; + } + + current = (previous + value / previous) / 2; + } while (System.Math.Abs(previous - current) > 0.0m); + + return current; + } +} diff --git a/X10D/src/Math/DoubleExtensions.cs b/X10D/src/Math/DoubleExtensions.cs index 0fec4a3..5b393a7 100644 --- a/X10D/src/Math/DoubleExtensions.cs +++ b/X10D/src/Math/DoubleExtensions.cs @@ -1,4 +1,5 @@ using System.Diagnostics.Contracts; +using System.Numerics; using System.Runtime.CompilerServices; namespace X10D.Math; @@ -115,6 +116,32 @@ public static class DoubleExtensions return System.Math.Atanh(value); } + /// + /// Returns the complex square root of this double-precision floating-point number. + /// + /// The number whose square root is to be found. + /// The square root of . + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static Complex ComplexSqrt(this double value) + { + switch (value) + { + case double.PositiveInfinity: + case double.NegativeInfinity: + return Complex.Infinity; + case double.NaN: + return Complex.NaN; + + case 0: + return Complex.Zero; + case > 0: + return new Complex(System.Math.Sqrt(value), 0); + case < 0: + return new Complex(0, System.Math.Sqrt(-value)); + } + } + /// /// Returns the cosine of the specified angle. /// diff --git a/X10D/src/Math/SingleExtensions.cs b/X10D/src/Math/SingleExtensions.cs index f7316b0..df6b8b8 100644 --- a/X10D/src/Math/SingleExtensions.cs +++ b/X10D/src/Math/SingleExtensions.cs @@ -1,4 +1,5 @@ using System.Diagnostics.Contracts; +using System.Numerics; using System.Runtime.CompilerServices; namespace X10D.Math; @@ -115,6 +116,32 @@ public static class SingleExtensions return MathF.Atanh(value); } + /// + /// Returns the complex square root of this single-precision floating-point number. + /// + /// The number whose square root is to be found. + /// The square root of . + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static Complex ComplexSqrt(this float value) + { + switch (value) + { + case float.PositiveInfinity: + case float.NegativeInfinity: + return Complex.Infinity; + case float.NaN: + return Complex.NaN; + + case 0: + return Complex.Zero; + case > 0: + return new Complex(MathF.Sqrt(value), 0); + case < 0: + return new Complex(0, MathF.Sqrt(-value)); + } + } + /// /// Returns the cosine of the specified angle. /// diff --git a/X10D/src/Numerics/DoubleExtensions.cs b/X10D/src/Numerics/DoubleExtensions.cs deleted file mode 100644 index bfc0631..0000000 --- a/X10D/src/Numerics/DoubleExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Diagnostics.Contracts; -using System.Numerics; -using System.Runtime.CompilerServices; -using X10D.Math; - -namespace X10D.Numerics; - -/// -/// Extension methods for . -/// -public static class DoubleExtensions -{ - /// - /// Returns the complex square root of this double-precision floating-point number. - /// - /// The number whose square root is to be found. - /// The square root of . - /// - [Pure] - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static Complex ComplexSqrt(this double value) - { - switch (value) - { - case double.PositiveInfinity: - case double.NegativeInfinity: - return Complex.Infinity; - case double.NaN: - return Complex.NaN; - } - - double absoluteSqrt = System.Math.Abs(value).Sqrt(); - return new Complex(absoluteSqrt, value >= 0 ? 0 : 1); - } -} diff --git a/X10D/src/Numerics/SingleExtensions.cs b/X10D/src/Numerics/SingleExtensions.cs deleted file mode 100644 index a85a23b..0000000 --- a/X10D/src/Numerics/SingleExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Diagnostics.Contracts; -using System.Numerics; -using System.Runtime.CompilerServices; -using X10D.Math; - -namespace X10D.Numerics; - -/// -/// Extension methods for . -/// -public static class SingleExtensions -{ - /// - /// Returns the complex square root of this single-precision floating-point number. - /// - /// The number whose square root is to be found. - /// The square root of . - /// - [Pure] - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static Complex ComplexSqrt(this float value) - { - switch (value) - { - case float.PositiveInfinity: - case float.NegativeInfinity: - return Complex.Infinity; - case float.NaN: - return Complex.NaN; - } - - float absoluteSqrt = MathF.Abs(value).Sqrt(); - return new Complex(absoluteSqrt, value >= 0 ? 0 : 1); - } -}