Skip to content

Commit

Permalink
Implement * and / to allow generic functions on amounts.
Browse files Browse the repository at this point in the history
  • Loading branch information
Corniel committed Jan 29, 2024
1 parent 992ad21 commit 47ca887
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 45 deletions.
71 changes: 30 additions & 41 deletions specs/Qowaiv.Specs/Financial/Amount_INumber_specs.cs
Expand Up @@ -16,32 +16,31 @@ public void modulo(Amount p, Amount mod, Amount remainder)
public class Amount_as_INumber
{
[Test]
public void radix_is_10()
public void radixis_10()
=> Number.Radix<Amount>().Should().Be(10);

[Test]
public void Additive_identity_Is_1()
public void Additive_identityIs_1()
=> Number.AdditiveIdentity<Amount>().Should().Be(1.Amount());

[Test]
public void Multiplicative_identity_is_1()
public void Multiplicative_identityis_1()
=> Number.MultiplicativeIdentity<Amount>().Should().Be(1.Amount());

[Test]
public void Is_canonical_equal_to_decimal([Random(Min, Max, Count)] double d)
public void Is_canonical_equal_to_decimal([Random(Min, Max, Count)] decimal d)
{
var n = (decimal)d;
Number.IsCanonical((Amount)n).Should().Be(Number.IsCanonical(n));
Number.IsCanonical(d.Amount()).Should().Be(Number.IsCanonical(d));
}

[Test]
public void Abs_equal_to_Amount_Abs([Random(Min, Max, Count)] double d)
public void Abs_equal_to_Amount_Abs([Random(Min, Max, Count)] decimal d)
{
Number.Abs(d.Amount()).Should().Be(d.Amount().Abs());
}

[Test]
public void is_never_a_complex_number([Random(Min, Max, Count)] double d)
public void is_never_a_complexnumber([Random(Min, Max, Count)] decimal d)
=> Number.IsComplexNumber(d.Amount()).Should().BeFalse();

[TestCase(4, true)]
Expand Down Expand Up @@ -73,38 +72,37 @@ public void is_odd_integer(Amount p, bool isEvenInteger)
=> Number.IsOddInteger(p).Should().Be(isEvenInteger);

[Test]
public void is_always_real([Random(Min, Max, Count)] double d)
public void is_always_real([Random(Min, Max, Count)] decimal d)
=> Number.IsRealNumber(d.Amount()).Should().BeTrue();

[Test]
public void is_never_complex([Random(Min, Max, Count)] double d)
public void is_never_complex([Random(Min, Max, Count)] decimal d)
=> Number.IsComplexNumber(d.Amount()).Should().BeFalse();

[Test]
public void is_never_imaginary([Random(Min, Max, Count)] double d)
public void is_never_imaginary([Random(Min, Max, Count)] decimal d)
=> Number.IsImaginaryNumber(d.Amount()).Should().BeFalse();

[Test]
public void is_always_finate([Random(Min, Max, Count)] double d)
public void is_always_finate([Random(Min, Max, Count)] decimal d)
=> Number.IsFinite(d.Amount()).Should().BeTrue();

[Test]
public void is_never_infinite([Random(Min, Max, Count)] double d)
public void is_never_infinite([Random(Min, Max, Count)] decimal d)
{
Number.IsInfinity(d.Amount()).Should().BeFalse();
Number.IsNegativeInfinity(d.Amount()).Should().BeFalse();
Number.IsPositiveInfinity(d.Amount()).Should().BeFalse();
}

[Test]
public void is_never_NaN([Random(Min, Max, Count)] double d)
public void is_never_NaN([Random(Min, Max, Count)] decimal d)
=> Number.IsNaN(d.Amount()).Should().BeFalse();

[Test]
public void is_negative_equal_to_decimal([Random(Min, Max, Count)] double d)
public void is_negative_equal_to_decimal([Random(Min, Max, Count)] decimal d)
{
var n = (decimal)d;
Number.IsNegative((Amount)n).Should().Be(Number.IsNegative(n));
Number.IsNegative(d.Amount()).Should().Be(Number.IsNegative(d));
}

[Test]
Expand All @@ -118,13 +116,13 @@ public void zero_is_positive_and_not_negative()
}

[Test]
public void is_zero_is_false_for_all_but_zero([Random(Min, Max, Count)] double d)
public void is_zero_is_false_for_all_but_zero([Random(Min, Max, Count)] decimal d)
{
Number.IsZero(d.Amount()).Should().BeFalse();
}

[Test]
public void is_positive_equal_to_decimal([Random(Min, Max, Count)] double d)
public void is_positive_equal_to_decimal([Random(Min, Max, Count)] decimal d)
{
Number.IsPositive(d.Amount()).Should().Be(Number.IsPositive(d.Amount()));
}
Expand All @@ -134,48 +132,39 @@ public void Is_not_Normal_when_zero()
=> Number.IsNormal(Amount.Zero).Should().BeFalse();

[Test]
public void Is_never_subnormal([Random(Min, Max, Count)] double d)
public void Is_never_subnormal([Random(Min, Max, Count)] decimal d)
=> Number.IsSubnormal(d.Amount()).Should().BeFalse();

[Test]
public void Is_normal_when_not_zero([Random(Min, Max, Count)] double d)
public void Is_normal_when_not_zero([Random(Min, Max, Count)] decimal d)
{
var n = (decimal)d;
Number.IsNormal((Amount)n).Should().BeTrue();
Number.IsNormal(d.Amount()).Should().BeTrue();
}

[Test]
public void max_maginiute_equal_to_decimal([Random(Min, Max, 3)] double x, [Random(Min, Max, 3)] double y)
public void maxmaginiute_equal_to_decimal([Random(Min, Max, 3)] decimal x, [Random(Min, Max, 3)] decimal y)
{
var x_ = (decimal)x;
var y_ = (decimal)y;

Number.MaxMagnitude((Amount)x_, (Amount)y_).Should().Be((Amount)Number.MaxMagnitude(x_, y_));
Number.MaxMagnitudeNumber((Amount)x_, (Amount)y_).Should().Be((Amount)Number.MaxMagnitudeNumber(x_, y_));
Number.MaxMagnitude(x.Amount(), y.Amount()).Should().Be(Number.MaxMagnitude(x, y).Amount());
Number.MaxMagnitudeNumber(x.Amount(), y.Amount()).Should().Be(Number.MaxMagnitudeNumber(x, y).Amount());
}

[Test]
public void min_maginiute_equal_to_decimal([Random(Min, Max, 3)] double x, [Random(Min, Max, 3)] double y)
public void min_maginiute_equal_to_decimal([Random(Min, Max, 3)] decimal x, [Random(Min, Max, 3)] decimal y)
{
var x_ = (decimal)x;
var y_ = (decimal)y;

Number.MinMagnitude((Amount)x_, (Amount)y_).Should().Be((Amount)Number.MinMagnitude(x_, y_));
Number.MinMagnitudeNumber((Amount)x_, (Amount)y_).Should().Be((Amount)Number.MinMagnitudeNumber(x_, y_));
Number.MinMagnitude(x.Amount(), y.Amount()).Should().Be(Number.MinMagnitude(x, y).Amount());
Number.MinMagnitudeNumber(x.Amount(), y.Amount()).Should().Be((Amount)Number.MinMagnitudeNumber(x, y));
}

[Test]
public void multiplication_is_not_supported()
public void multiplication_is_supported_via_explicit_contract_only([Random(-100_000, +100_000, 3)] decimal x, [Random(-100_000, +100_000, 3)] decimal y)
{
var multiply = () => Number.Multiply(6.Amount(), 7.Amount());
multiply.Should().Throw<NotSupportedException>(because: "Multiplying amounts makes no sense.");
Number.Multiply(x.Amount(), y.Amount()).Should().Be((x * y).Amount());
}

[Test]
public void division_is_not_supported()
public void division_is_supported_via_explicit_contract_only([Random(Min, Max, 3)] decimal x, [Random(Min, Max, 3)] decimal y)
{
var multiply = () => Number.Divide(6.Amount(), 7.Amount());
multiply.Should().Throw<NotSupportedException>(because: "Devision amounts makes no sense (when the result is amount).");
Number.Divide(x.Amount(), y.Amount()).Should().Be((x / y).Amount());
}

private const double Min = -79228162514264337593543950335d;
Expand Down
7 changes: 3 additions & 4 deletions src/Qowaiv/Financial/Amount.INumber.cs
@@ -1,5 +1,4 @@

namespace Qowaiv.Financial;
namespace Qowaiv.Financial;

public readonly partial struct Amount
{
Expand Down Expand Up @@ -266,10 +265,10 @@ static bool ISpanParsable<Amount>.TryParse(ReadOnlySpan<char> s, IFormatProvider
=> TryParse(s.ToString(), NumberStyles.Currency, provider, out result);

static Amount IMultiplyOperators<Amount, Amount, Amount>.operator *(Amount left, Amount right)
=> throw new NotSupportedException();
=> new(left.m_Value * right.m_Value);

static Amount IDivisionOperators<Amount, Amount, Amount>.operator /(Amount left, Amount right)
=> throw new NotSupportedException();
=> new(left.m_Value / right.m_Value);

[ExcludeFromCodeCoverage(Justification = "Protected member of the contract that is not supported.")]
static bool INumberBase<Amount>.TryConvertFromChecked<TOther>(TOther value, out Amount result)
Expand Down

0 comments on commit 47ca887

Please sign in to comment.