From 239bd1dd384733f4fe33681556b5ee70d3071ec2 Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Sat, 20 Jan 2024 21:22:20 +0100 Subject: [PATCH] Extend coverage. --- .../Qowaiv.Specs/Percentage_INumber_specs.cs | 147 ++++++++++++++++-- src/Qowaiv.TestTools/Numerics/Number.cs | 120 ++++++++++++++ src/Qowaiv/Percentage.INumber.cs | 29 ++-- 3 files changed, 269 insertions(+), 27 deletions(-) create mode 100644 src/Qowaiv.TestTools/Numerics/Number.cs diff --git a/specs/Qowaiv.Specs/Percentage_INumber_specs.cs b/specs/Qowaiv.Specs/Percentage_INumber_specs.cs index 0bf5158a9..5119465be 100644 --- a/specs/Qowaiv.Specs/Percentage_INumber_specs.cs +++ b/specs/Qowaiv.Specs/Percentage_INumber_specs.cs @@ -1,24 +1,145 @@ #if NET8_0_OR_GREATER -using System.Numerics; +using Qowaiv.TestTools.Numerics; -namespace Percentage_INumber_specs; +namespace Percentage_specs; -public class Percentage_INumber_specs +public class Percentage_as_INumber { [Test] - public void X() + public void radix_is_10() + => Number.Radix().Should().Be(10); + + [Test] + public void Additive_identity_Is_1_percent() + => Number.AdditiveIdentity().Should().Be(1.Percent()); + + [Test] + public void Multiplicative_identity_is_100_percent() + => Number.MultiplicativeIdentity().Should().Be(100.Percent()); + + [Test] + public void Is_canonical_equal_to_decimal([Random(Min, Max, Count)]double d) { - var y0 = IsCanonical(double.Pi); - var z1 = IsCanonical(0.003); - var z2 = IsCanonical(-0.003); - var z3 = IsCanonical(double.PositiveInfinity); - var x = IsCanonical((decimal)Svo.Percentage); - IsCanonical(Svo.Percentage).Should().Be(IsCanonical((decimal)Svo.Percentage)); + var n = (decimal)d; + Number.IsCanonical((Percentage)n).Should().Be(Number.IsCanonical(n)); } - private bool IsCanonical(T number) where T : INumberBase - => T.IsCanonical(number); -} + [Test] + public void Abs_equal_to_percentage_Abs([Random(Min, Max, Count)] double d) + { + var p = (Percentage)d; + Number.Abs(p).Should().Be(p.Abs()); + } + + [Test] + public void is_never_a_complex_number([Random(Min, Max, Count)] double d) + => Number.IsComplexNumber((Percentage)d).Should().BeFalse(); + + [TestCase("4%", true)] + [TestCase("9%", true)] + [TestCase("1%", true)] + [TestCase("-1%", true)] + [TestCase("-2%", true)] + [TestCase("3.3%", false)] + [TestCase("-4.4%", false)] + public void is_integer(Percentage p, bool isEvenInteger) + => Number.IsInteger(p).Should().Be(isEvenInteger); + + [TestCase("4%", true)] + [TestCase("8%", true)] + [TestCase("0%", true)] + [TestCase("-2%", true)] + [TestCase("-1%", false)] + [TestCase("2.2%", false)] + public void is_even_integer(Percentage p, bool isEvenInteger) + => Number.IsEvenInteger(p).Should().Be(isEvenInteger); + [TestCase("5%", true)] + [TestCase("9%", true)] + [TestCase("1%", true)] + [TestCase("-1%", true)] + [TestCase("-2%", false)] + [TestCase("3.3%", false)] + public void is_odd_integer(Percentage p, bool isEvenInteger) + => Number.IsOddInteger(p).Should().Be(isEvenInteger); + + [Test] + public void is_always_real([Random(Min, Max, Count)] double d) + => Number.IsRealNumber((Percentage)d).Should().BeTrue(); + + [Test] + public void is_never_complex([Random(Min, Max, Count)] double d) + => Number.IsComplexNumber((Percentage)d).Should().BeFalse(); + + [Test] + public void is_never_imaginary([Random(Min, Max, Count)] double d) + => Number.IsImaginaryNumber((Percentage)d).Should().BeFalse(); + + [Test] + public void is_always_finate([Random(Min, Max, Count)] double d) + => Number.IsFinite((Percentage)d).Should().BeTrue(); + + [Test] + public void is_never_infinite([Random(Min, Max, Count)] double d) + { + Number.IsInfinity((Percentage)d).Should().BeFalse(); + Number.IsNegativeInfinity((Percentage)d).Should().BeFalse(); + Number.IsPositiveInfinity((Percentage)d).Should().BeFalse(); + } + + [Test] + public void is_never_NaN([Random(Min, Max, Count)] double d) + => Number.IsNaN((Percentage)d).Should().BeFalse(); + + [Test] + public void is_negative_equal_to_decimal([Random(Min, Max, Count)] double d) + { + var n = (decimal)d; + Number.IsNegative((Percentage)n).Should().Be(Number.IsNegative(n)); + } + + [Test] + public void zero_is_positive_and_not_negative() + { + Number.IsPositive(Percentage.Zero).Should().BeTrue(); + Number.IsNegative(Percentage.Zero).Should().BeFalse(); + + Number.IsPositive(0m).Should().BeTrue(); + Number.IsNegative(0m).Should().BeFalse(); + } + + [Test] + public void is_zero_is_false_for_all_but_zero([Random(Min, Max, Count)] double d) + { + var n = (decimal)d; + Number.IsZero((Percentage)n).Should().BeFalse(); + } + + [Test] + public void is_positive_equal_to_decimal([Random(Min, Max, Count)] double d) + { + var n = (decimal)d; + Number.IsPositive((Percentage)n).Should().Be(Number.IsPositive(n)); + } + + [Test] + public void Is_not_Normal_when_zero() + => Number.IsNormal(Percentage.Zero).Should().BeFalse(); + + [Test] + public void Is_never_subnormal([Random(Min, Max, Count)] double d) + => Number.IsSubnormal((Percentage)d).Should().BeFalse(); + + [Test] + public void Is_normal_when_not_zero([Random(Min, Max, Count)] double d) + { + var n = (decimal)d; + Number.IsNormal((Percentage)n).Should().BeTrue(); + } + + private const double Min = -79228162514264337593543950335d; + private const double Max = +79228162514264337593543950335d; + private const int Count = 8; +} #endif diff --git a/src/Qowaiv.TestTools/Numerics/Number.cs b/src/Qowaiv.TestTools/Numerics/Number.cs new file mode 100644 index 000000000..b16d23d3b --- /dev/null +++ b/src/Qowaiv.TestTools/Numerics/Number.cs @@ -0,0 +1,120 @@ +#if NET8_0_OR_GREATER + +using System.Numerics; + +namespace Qowaiv.TestTools.Numerics; + +/// An static helper to call methods. +/// +/// As some implementations of are explicit, +/// this helper accesses these methods via the interface. +/// +public static class Number +{ + /// + [Pure] + public static T AdditiveIdentity() where T : IAdditiveIdentity + => T.AdditiveIdentity; + + /// + [Pure] + public static T MultiplicativeIdentity() where T : IMultiplicativeIdentity + => T.MultiplicativeIdentity; + + /// + [Pure] + public static int Radix() where T : INumberBase + => T.Radix; + + /// + [Pure] + public static T Abs(T value) where T : INumberBase + => T.Abs(value); + + /// + [Pure] + public static bool IsCanonical(T number) where T : INumberBase + => T.IsCanonical(number); + + /// + [Pure] + public static bool IsEvenInteger(T number) where T : INumberBase + => T.IsEvenInteger(number); + + /// + [Pure] + public static bool IsOddInteger(T number) where T : INumberBase + => T.IsOddInteger(number); + + /// + [Pure] + public static bool IsFinite(T number) where T : INumberBase + => T.IsFinite(number); + + /// + [Pure] + public static bool IsInfinity(T number) where T : INumberBase + => T.IsInfinity(number); + + /// + [Pure] + public static bool IsNegativeInfinity(T number) where T : INumberBase + => T.IsNegativeInfinity(number); + + /// + [Pure] + public static bool IsPositiveInfinity(T number) where T : INumberBase + => T.IsPositiveInfinity(number); + + /// + [Pure] + public static bool IsInteger(T number) where T : INumberBase + => T.IsInteger(number); + + /// + [Pure] + public static bool IsNaN(T number) where T : INumberBase + => T.IsNaN(number); + + /// + [Pure] + public static bool IsNegative(T number) where T : INumberBase + => T.IsNegative(number); + + /// + [Pure] + public static bool IsZero(T number) where T : INumberBase + => T.IsZero(number); + + /// + [Pure] + public static bool IsPositive(T number) where T : INumberBase + => T.IsPositive(number); + + /// + [Pure] + public static bool IsNormal(T number) where T : INumberBase + => T.IsNormal(number); + + /// + [Pure] + public static bool IsSubnormal(T number) where T : INumberBase + => T.IsSubnormal(number); + + /// + [Pure] + public static bool IsRealNumber(T number) where T : INumberBase + => T.IsRealNumber(number); + + /// + [Pure] + public static bool IsComplexNumber(T number) where T : INumberBase + => T.IsComplexNumber(number); + + /// + [Pure] + public static bool IsImaginaryNumber(T number) where T : INumberBase + => T.IsImaginaryNumber(number); +} + +#endif diff --git a/src/Qowaiv/Percentage.INumber.cs b/src/Qowaiv/Percentage.INumber.cs index 2fd5ec121..f125be006 100644 --- a/src/Qowaiv/Percentage.INumber.cs +++ b/src/Qowaiv/Percentage.INumber.cs @@ -93,7 +93,7 @@ public static decimal operator *(decimal d, Percentage p) => d * p.m_Value; /// Gets the percentage of the Double. - public static double operator *(double d, Percentage p) => d * (double) p.m_Value; + public static double operator *(double d, Percentage p) => d * (double)p.m_Value; /// Gets the percentage of the Single. public static float operator *(float d, Percentage p) => d * (float)p.m_Value; @@ -242,10 +242,6 @@ [Pure] static bool INumberBase.IsComplexNumber(Percentage value) => false; - /// - [Pure] - static bool INumberBase.IsEvenInteger(Percentage value) => (value.m_Value.Abs() * 100) % 2 == 0; - /// [Pure] static bool INumberBase.IsFinite(Percentage value) => true; @@ -260,48 +256,53 @@ /// [Pure] - static bool INumberBase.IsInteger(Percentage value) => (value.m_Value.Abs() * 100) % 1 == 0; + static bool INumberBase.IsNegativeInfinity(Percentage value) => false; /// [Pure] - static bool INumberBase.IsNaN(Percentage value) => false; + static bool INumberBase.IsPositiveInfinity(Percentage value) => false; /// [Pure] - static bool INumberBase.IsNegative(Percentage value) => value < Zero; + static bool INumberBase.IsInteger(Percentage value) => value.m_Value.Abs() % 0.01m == 0; /// [Pure] - static bool INumberBase.IsNegativeInfinity(Percentage value) => false; + static bool INumberBase.IsEvenInteger(Percentage value) => value.m_Value.Abs() % 0.02m == 0; /// [Pure] - static bool INumberBase.IsNormal(Percentage value) => value.m_Value != 0; + static bool INumberBase.IsOddInteger(Percentage value) => value.m_Value.Abs() % 0.02m == 0.01m; /// [Pure] - static bool INumberBase.IsOddInteger(Percentage value) => (value.m_Value.Abs() * 100) % 2 == 1; + static bool INumberBase.IsNaN(Percentage value) => false; /// [Pure] - static bool INumberBase.IsPositive(Percentage value) => value > Zero; + static bool INumberBase.IsNormal(Percentage value) => value.m_Value != 0; /// [Pure] - static bool INumberBase.IsPositiveInfinity(Percentage value) => false; + static bool INumberBase.IsSubnormal(Percentage value) => false; /// [Pure] static bool INumberBase.IsRealNumber(Percentage value) => true; + /// [Pure] - static bool INumberBase.IsSubnormal(Percentage value) => false; + static bool INumberBase.IsNegative(Percentage value) => value < Zero; /// [Pure] static bool INumberBase.IsZero(Percentage value) => value == Zero; + /// + [Pure] + static bool INumberBase.IsPositive(Percentage value) => value >= Zero; + /// [Pure] static Percentage INumberBase.MaxMagnitude(Percentage x, Percentage y)