Skip to content

Commit

Permalink
Extend coverage.
Browse files Browse the repository at this point in the history
  • Loading branch information
Corniel committed Jan 20, 2024
1 parent bf0165d commit 239bd1d
Show file tree
Hide file tree
Showing 3 changed files with 269 additions and 27 deletions.
147 changes: 134 additions & 13 deletions specs/Qowaiv.Specs/Percentage_INumber_specs.cs
Original file line number Diff line number Diff line change
@@ -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<Percentage>().Should().Be(10);

[Test]
public void Additive_identity_Is_1_percent()
=> Number.AdditiveIdentity<Percentage>().Should().Be(1.Percent());

[Test]
public void Multiplicative_identity_is_100_percent()
=> Number.MultiplicativeIdentity<Percentage>().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>(T number) where T : INumberBase<T>
=> 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
120 changes: 120 additions & 0 deletions src/Qowaiv.TestTools/Numerics/Number.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#if NET8_0_OR_GREATER

using System.Numerics;

namespace Qowaiv.TestTools.Numerics;

/// <summary>An static helper to call <see cref="INumber{TSelf}"/> methods.</summary>
/// <remarks>
/// As some implementations of <see cref="INumber{TSelf}"/> are explicit,
/// this helper accesses these methods via the interface.
/// </remarks>
public static class Number
{
/// <inheritdoc cref="IAdditiveIdentity{T,T}.AdditiveIdentity" />
[Pure]
public static T AdditiveIdentity<T>() where T : IAdditiveIdentity<T, T>
=> T.AdditiveIdentity;

/// <inheritdoc cref="IMultiplicativeIdentity{T,T}.MultiplicativeIdentity" />
[Pure]
public static T MultiplicativeIdentity<T>() where T : IMultiplicativeIdentity<T, T>
=> T.MultiplicativeIdentity;

/// <inheritdoc cref="INumberBase{T}.Radix" />
[Pure]
public static int Radix<T>() where T : INumberBase<T>
=> T.Radix;

/// <inheritdoc cref="INumberBase{T}.Abs(T)" />
[Pure]
public static T Abs<T>(T value) where T : INumberBase<T>
=> T.Abs(value);

/// <inheritdoc cref="INumberBase{T}.IsCanonical(T)" />
[Pure]
public static bool IsCanonical<T>(T number) where T : INumberBase<T>
=> T.IsCanonical(number);

/// <inheritdoc cref="INumberBase{T}.IsEvenInteger(T)" />
[Pure]
public static bool IsEvenInteger<T>(T number) where T : INumberBase<T>
=> T.IsEvenInteger(number);

/// <inheritdoc cref="INumberBase{T}.IsOddInteger(T)" />
[Pure]
public static bool IsOddInteger<T>(T number) where T : INumberBase<T>
=> T.IsOddInteger(number);

/// <inheritdoc cref="INumberBase{T}.IsFinite(T)" />
[Pure]
public static bool IsFinite<T>(T number) where T : INumberBase<T>
=> T.IsFinite(number);

/// <inheritdoc cref="INumberBase{T}.IsInfinity(T)" />
[Pure]
public static bool IsInfinity<T>(T number) where T : INumberBase<T>
=> T.IsInfinity(number);

/// <inheritdoc cref="INumberBase{T}.IsNegativeInfinity(T)" />
[Pure]
public static bool IsNegativeInfinity<T>(T number) where T : INumberBase<T>
=> T.IsNegativeInfinity(number);

/// <inheritdoc cref="INumberBase{T}.IsNegativeInfinity(T)" />
[Pure]
public static bool IsPositiveInfinity<T>(T number) where T : INumberBase<T>
=> T.IsPositiveInfinity(number);

/// <inheritdoc cref="INumberBase{T}.IsInteger(T)" />
[Pure]
public static bool IsInteger<T>(T number) where T : INumberBase<T>
=> T.IsInteger(number);

/// <inheritdoc cref="INumberBase{T}.IsInteger(T)" />
[Pure]
public static bool IsNaN<T>(T number) where T : INumberBase<T>
=> T.IsNaN(number);

/// <inheritdoc cref="INumberBase{T}.IsInteger(T)" />
[Pure]
public static bool IsNegative<T>(T number) where T : INumberBase<T>
=> T.IsNegative(number);

/// <inheritdoc cref="INumberBase{T}.IsZero(T)" />
[Pure]
public static bool IsZero<T>(T number) where T : INumberBase<T>
=> T.IsZero(number);

/// <inheritdoc cref="INumberBase{T}.IsPositive(T)" />
[Pure]
public static bool IsPositive<T>(T number) where T : INumberBase<T>
=> T.IsPositive(number);

/// <inheritdoc cref="INumberBase{T}.IsNormal(T)" />
[Pure]
public static bool IsNormal<T>(T number) where T : INumberBase<T>
=> T.IsNormal(number);

/// <inheritdoc cref="INumberBase{T}.IsSubnormal(T)" />
[Pure]
public static bool IsSubnormal<T>(T number) where T : INumberBase<T>
=> T.IsSubnormal(number);

/// <inheritdoc cref="INumberBase{T}.IsRealNumber(T)" />
[Pure]
public static bool IsRealNumber<T>(T number) where T : INumberBase<T>
=> T.IsRealNumber(number);

/// <inheritdoc cref="INumberBase{T}.IsComplexNumber(T)" />
[Pure]
public static bool IsComplexNumber<T>(T number) where T : INumberBase<T>
=> T.IsComplexNumber(number);

/// <inheritdoc cref="INumberBase{T}.IsImaginaryNumber(T)" />
[Pure]
public static bool IsImaginaryNumber<T>(T number) where T : INumberBase<T>
=> T.IsImaginaryNumber(number);
}

#endif
29 changes: 15 additions & 14 deletions src/Qowaiv/Percentage.INumber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
public static decimal operator *(decimal d, Percentage p) => d * p.m_Value;

/// <summary>Gets the percentage of the Double.</summary>
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;

/// <summary>Gets the percentage of the Single.</summary>
public static float operator *(float d, Percentage p) => d * (float)p.m_Value;
Expand Down Expand Up @@ -242,10 +242,6 @@
[Pure]
static bool INumberBase<Percentage>.IsComplexNumber(Percentage value) => false;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsEvenInteger(Percentage value) => (value.m_Value.Abs() * 100) % 2 == 0;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsFinite(Percentage value) => true;
Expand All @@ -260,48 +256,53 @@

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsInteger(Percentage value) => (value.m_Value.Abs() * 100) % 1 == 0;
static bool INumberBase<Percentage>.IsNegativeInfinity(Percentage value) => false;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsNaN(Percentage value) => false;
static bool INumberBase<Percentage>.IsPositiveInfinity(Percentage value) => false;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsNegative(Percentage value) => value < Zero;
static bool INumberBase<Percentage>.IsInteger(Percentage value) => value.m_Value.Abs() % 0.01m == 0;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsNegativeInfinity(Percentage value) => false;
static bool INumberBase<Percentage>.IsEvenInteger(Percentage value) => value.m_Value.Abs() % 0.02m == 0;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsNormal(Percentage value) => value.m_Value != 0;
static bool INumberBase<Percentage>.IsOddInteger(Percentage value) => value.m_Value.Abs() % 0.02m == 0.01m;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsOddInteger(Percentage value) => (value.m_Value.Abs() * 100) % 2 == 1;
static bool INumberBase<Percentage>.IsNaN(Percentage value) => false;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsPositive(Percentage value) => value > Zero;
static bool INumberBase<Percentage>.IsNormal(Percentage value) => value.m_Value != 0;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsPositiveInfinity(Percentage value) => false;
static bool INumberBase<Percentage>.IsSubnormal(Percentage value) => false;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsRealNumber(Percentage value) => true;

Check warning on line 292 in src/Qowaiv/Percentage.INumber.cs

View workflow job for this annotation

GitHub Actions / Build


Check warning on line 293 in src/Qowaiv/Percentage.INumber.cs

View workflow job for this annotation

GitHub Actions / Build

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsSubnormal(Percentage value) => false;
static bool INumberBase<Percentage>.IsNegative(Percentage value) => value < Zero;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsZero(Percentage value) => value == Zero;

/// <inheritdoc />
[Pure]
static bool INumberBase<Percentage>.IsPositive(Percentage value) => value >= Zero;

/// <inheritdoc />
[Pure]
static Percentage INumberBase<Percentage>.MaxMagnitude(Percentage x, Percentage y)
Expand Down

0 comments on commit 239bd1d

Please sign in to comment.