diff --git a/specs/Qowaiv.Specs/Svo_numeric_contract_specs.cs b/specs/Qowaiv.Specs/Svo_numeric_contract_specs.cs index 2ee793b9..0302c726 100644 --- a/specs/Qowaiv.Specs/Svo_numeric_contract_specs.cs +++ b/specs/Qowaiv.Specs/Svo_numeric_contract_specs.cs @@ -25,7 +25,6 @@ public void Abs(Type svo) methods.Should().ContainSingle(); } - [TestCase(typeof(Amount))] [TestCase(typeof(Money))] [TestCase(typeof(StreamSize))] public void Plus(Type svo) @@ -52,7 +51,6 @@ public void Plus(Type svo) operators.Should().ContainSingle(); } - [TestCase(typeof(Amount))] [TestCase(typeof(Money))] [TestCase(typeof(StreamSize))] public void Negate(Type svo) @@ -79,7 +77,6 @@ public void Negate(Type svo) operators.Should().ContainSingle(); } - [TestCase(typeof(Amount))] [TestCase(typeof(Money))] [TestCase(typeof(StreamSize))] public void Increment(Type svo) @@ -106,7 +103,6 @@ public void Increment(Type svo) operators.Should().ContainSingle(); } - [TestCase(typeof(Amount))] [TestCase(typeof(Money))] [TestCase(typeof(StreamSize))] public void Decrement(Type svo) @@ -133,7 +129,6 @@ public void Decrement(Type svo) operators.Should().ContainSingle(); } - [TestCase(typeof(Amount), typeof(Amount), typeof(Percentage))] [TestCase(typeof(Money), typeof(Money), typeof(Percentage))] [TestCase(typeof(StreamSize), typeof(StreamSize), typeof(Percentage))] public void Add(Type svo, params Type[] expected) @@ -162,7 +157,6 @@ public void Add(Type svo, params Type[] expected) operators.Should().BeEquivalentTo(expected); } - [TestCase(typeof(Amount), typeof(Amount), typeof(Percentage))] [TestCase(typeof(Money), typeof(Money), typeof(Percentage))] [TestCase(typeof(StreamSize), typeof(StreamSize), typeof(Percentage))] public void Subtract(Type svo, params Type[] expected) @@ -191,7 +185,6 @@ public void Subtract(Type svo, params Type[] expected) operators.Should().BeEquivalentTo(expected); } - [TestCase(typeof(Amount), typeof(short), typeof(int), typeof(long), typeof(ushort), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(Percentage))] [TestCase(typeof(Money), typeof(short), typeof(int), typeof(long), typeof(ushort), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(Percentage))] [TestCase(typeof(StreamSize), typeof(short), typeof(int), typeof(long), typeof(ushort), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(Percentage))] public void Multiply(Type svo, params Type[] expected) @@ -220,7 +213,6 @@ public void Multiply(Type svo, params Type[] expected) operators.Should().BeEquivalentTo(expected); } - [TestCase(typeof(Amount), typeof(short), typeof(int), typeof(long), typeof(ushort), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(Percentage))] [TestCase(typeof(Money), typeof(short), typeof(int), typeof(long), typeof(ushort), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(Percentage))] [TestCase(typeof(StreamSize), typeof(short), typeof(int), typeof(long), typeof(ushort), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(Percentage))] public void Divide(Type svo, params Type[] expected) @@ -249,7 +241,6 @@ public void Divide(Type svo, params Type[] expected) operators.Should().BeEquivalentTo(expected); } - [TestCase(typeof(Amount))] [TestCase(typeof(Money))] [TestCase(typeof(Percentage))] public void Round(Type svo) @@ -265,7 +256,6 @@ public void Round(Type svo) methods.Should().ContainSingle(); } - [TestCase(typeof(Amount))] [TestCase(typeof(Money))] [TestCase(typeof(Percentage))] public void Round_Decimals(Type svo) @@ -281,7 +271,6 @@ public void Round_Decimals(Type svo) methods.Should().ContainSingle(); } - [TestCase(typeof(Amount))] [TestCase(typeof(Money))] [TestCase(typeof(Percentage))] public void Round_Decimals_DecimalRounding(Type svo) diff --git a/src/Qowaiv/Financial/Amount.INumber.cs b/src/Qowaiv/Financial/Amount.INumber.cs new file mode 100644 index 00000000..6d22aee5 --- /dev/null +++ b/src/Qowaiv/Financial/Amount.INumber.cs @@ -0,0 +1,313 @@ + +namespace Qowaiv.Financial; + +public readonly partial struct Amount +{ + /// Represents an Amount of zero. + public static Amount Zero => default; + + /// Represents an Amount of one. + public static Amount One => new(1); + + /// Unitary plusses the amount. + public static Amount operator +(Amount amount) => amount; + + /// Negates the amount. + public static Amount operator -(Amount amount) => new(-amount.m_Value); + + /// Increases the amount with one. + public static Amount operator ++(Amount amount) => amount + One; + + /// Decreases the amount with one. + public static Amount operator --(Amount amount) => amount - One; + + /// Adds the left and the right amount. + public static Amount operator +(Amount l, Amount r) => new(l.m_Value + r.m_Value); + + /// Subtracts the right from the left amount. + public static Amount operator -(Amount l, Amount r) => new(l.m_Value - r.m_Value); + + /// Multiplies the amount with the factor. + public static Amount operator *(Amount amount, Percentage factor) => new(amount.m_Value * factor); + + /// Divides the amount by the percentage. + public static Amount operator /(Amount amount, Percentage p) => new(amount.m_Value / p); + + /// Adds the percentage to the amount. + public static Amount operator +(Amount amount, Percentage p) => new(amount.m_Value + p); + + /// Subtracts the percentage from the amount. + public static Amount operator -(Amount amount, Percentage p) => new(amount.m_Value - p); + + /// Multiplies the amount with the factor. + public static Amount operator *(Amount amount, decimal factor) => new(amount.m_Value * factor); + + /// Multiplies the amount with the factor. + public static Amount operator *(Amount amount, double factor) => new(amount.m_Value * (decimal)factor); + + /// Multiplies the amount with the factor. + public static Amount operator *(Amount amount, float factor) => new(amount.m_Value * (decimal)factor); + + /// Multiplies the amount with the factor. + public static Amount operator *(Amount amount, long factor) => new(amount.m_Value * factor); + + /// Multiplies the amount with the factor. + public static Amount operator *(Amount amount, int factor) => new(amount.m_Value * factor); + + /// Multiplies the amount with the factor. + public static Amount operator *(Amount amount, short factor) => new(amount.m_Value * factor); + + /// Multiplies the amount with the factor. + [CLSCompliant(false)] + public static Amount operator *(Amount amount, ulong factor) => new(amount.m_Value * factor); + + /// Multiplies the amount with the factor. + [CLSCompliant(false)] + public static Amount operator *(Amount amount, uint factor) => new(amount.m_Value * factor); + + /// Multiplies the amount with the factor. + [CLSCompliant(false)] + public static Amount operator *(Amount amount, ushort factor) => new(amount.m_Value * factor); + + /// Divides the amount by an other amount. + public static decimal operator /(Amount numerator, Amount denominator) => numerator.m_Value / denominator.m_Value; + + /// Divides the amount by the factor. + public static Amount operator /(Amount amount, decimal factor) => new(amount.m_Value / factor); + + /// Divides the amount by the factor. + public static Amount operator /(Amount amount, double factor) => new(amount.m_Value / (decimal)factor); + + /// Divides the amount by the factor. + public static Amount operator /(Amount amount, float factor) => new(amount.m_Value / (decimal)factor); + + /// Divides the amount by the factor. + public static Amount operator /(Amount amount, long factor) => new(amount.m_Value / factor); + + /// Divides the amount by the factor. + public static Amount operator /(Amount amount, int factor) => new(amount.m_Value / factor); + + /// Divides the amount by the factor. + public static Amount operator /(Amount amount, short factor) => new(amount.m_Value / factor); + + /// Divides the amount by the factor. + [CLSCompliant(false)] + public static Amount operator /(Amount amount, ulong factor) => new(amount.m_Value / factor); + + /// Divides the amount by the factor. + [CLSCompliant(false)] + public static Amount operator /(Amount amount, uint factor) => new(amount.m_Value / factor); + + /// Divides the amount by the factor. + [CLSCompliant(false)] + public static Amount operator /(Amount amount, ushort factor) => new(amount.m_Value / factor); + + /// Gets the remainder of the amount. + public static Amount operator %(Amount left, Amount right) => new(left.m_Value % right.m_Value); +} + +#if NET8_0_OR_GREATER + +public readonly partial struct Amount : INumber + , IAdditionOperators, ISubtractionOperators + , IMultiplyOperators, IDivisionOperators + , IMultiplyOperators, IDivisionOperators + , IMultiplyOperators, IDivisionOperators + , IMultiplyOperators, IDivisionOperators + , IMultiplyOperators, IDivisionOperators + , IMultiplyOperators, IDivisionOperators + , IMultiplyOperators, IDivisionOperators + , IMultiplyOperators, IDivisionOperators + , IMultiplyOperators, IDivisionOperators +{ + /// + static int INumberBase.Radix => 10; + + /// + static Amount IAdditiveIdentity.AdditiveIdentity => One; + + /// + static Amount IMultiplicativeIdentity.MultiplicativeIdentity => One; + + /// + [Pure] + static Amount INumberBase.Abs(Amount value) => value.Abs(); + + static bool INumberBase.IsCanonical(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsComplexNumber(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsEvenInteger(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsFinite(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsImaginaryNumber(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsInfinity(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsInteger(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsNaN(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsNegative(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsNegativeInfinity(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsNormal(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsOddInteger(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsPositive(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsPositiveInfinity(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsRealNumber(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsSubnormal(Amount value) + { + throw new NotImplementedException(); + } + + static bool INumberBase.IsZero(Amount value) + { + throw new NotImplementedException(); + } + + static Amount INumberBase.MaxMagnitude(Amount x, Amount y) + { + throw new NotImplementedException(); + } + + static Amount INumberBase.MaxMagnitudeNumber(Amount x, Amount y) + { + throw new NotImplementedException(); + } + + static Amount INumberBase.MinMagnitude(Amount x, Amount y) + { + throw new NotImplementedException(); + } + + static Amount INumberBase.MinMagnitudeNumber(Amount x, Amount y) + { + throw new NotImplementedException(); + } + + static Amount INumberBase.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) + { + throw new NotImplementedException(); + } + + static Amount INumberBase.Parse(string s, NumberStyles style, IFormatProvider? provider) + { + throw new NotImplementedException(); + } + + static Amount ISpanParsable.Parse(ReadOnlySpan s, IFormatProvider? provider) + { + throw new NotImplementedException(); + } + + static bool INumberBase.TryConvertFromChecked(TOther value, out Amount result) + { + throw new NotImplementedException(); + } + + static bool INumberBase.TryConvertFromSaturating(TOther value, out Amount result) + { + throw new NotImplementedException(); + } + + static bool INumberBase.TryConvertFromTruncating(TOther value, out Amount result) + { + throw new NotImplementedException(); + } + + static bool INumberBase.TryConvertToChecked(Amount value, out TOther result) + { + throw new NotImplementedException(); + } + + static bool INumberBase.TryConvertToSaturating(Amount value, out TOther result) + { + throw new NotImplementedException(); + } + + static bool INumberBase.TryConvertToTruncating(Amount value, out TOther result) + { + throw new NotImplementedException(); + } + + static bool INumberBase.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out Amount result) + { + throw new NotImplementedException(); + } + + static bool INumberBase.TryParse(string? s, NumberStyles style, IFormatProvider? provider, out Amount result) + { + throw new NotImplementedException(); + } + + static bool ISpanParsable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out Amount result) + { + throw new NotImplementedException(); + } + + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + throw new NotImplementedException(); + } + + static Amount IMultiplyOperators.operator *(Amount left, Amount right) + => throw new NotSupportedException(); + + static Amount IDivisionOperators.operator /(Amount left, Amount right) + => throw new NotSupportedException(); + +} +#endif diff --git a/src/Qowaiv/Financial/Amount.cs b/src/Qowaiv/Financial/Amount.cs index 7048d496..1123437b 100644 --- a/src/Qowaiv/Financial/Amount.cs +++ b/src/Qowaiv/Financial/Amount.cs @@ -13,25 +13,9 @@ namespace Qowaiv.Financial; #endif public readonly partial struct Amount : IXmlSerializable, IFormattable, IEquatable, IComparable, IComparable #if NET8_0_OR_GREATER - , IIncrementOperators, IDecrementOperators - , IUnaryPlusOperators, IUnaryNegationOperators - , IAdditionOperators, ISubtractionOperators - , IAdditionOperators, ISubtractionOperators - , IMultiplyOperators, IDivisionOperators - , IMultiplyOperators, IDivisionOperators - , IMultiplyOperators, IDivisionOperators - , IMultiplyOperators, IDivisionOperators - , IMultiplyOperators, IDivisionOperators - , IMultiplyOperators, IDivisionOperators - , IMultiplyOperators, IDivisionOperators - , IMultiplyOperators, IDivisionOperators - , IMultiplyOperators, IDivisionOperators , IMinMaxValue #endif { - /// Represents an Amount of zero. - public static Amount Zero => default; - /// Represents the smallest possible value of the amount. public static Amount MinValue => new(decimal.MinValue); @@ -44,216 +28,7 @@ namespace Qowaiv.Financial; /// Returns the absolute value of the amount. [Pure] - public Amount Abs() => (Amount)m_Value.Abs(); - - /// Pluses the amount. - [Pure] - internal Amount Plus() => (Amount)(+m_Value); - - /// Negates the amount. - [Pure] - internal Amount Negate() => (Amount)(-m_Value); - - /// Increases the amount with one. - [Pure] - internal Amount Increment() => new(m_Value + 1); - - /// Decreases the amount with one. - [Pure] - internal Amount Decrement() => new(m_Value - 1); - - /// Decreases the amount with one. - /// Adds a amount to the current amount. - /// - /// The amount to add. - /// - [Pure] - public Amount Add(Amount amount) => new(m_Value + amount.m_Value); - - /// Adds the specified percentage to the amount. - /// - /// The percentage to add. - /// - [Pure] - public Amount Add(Percentage p) => new(m_Value + p); - - /// Subtracts a amount from the current amount. - /// - /// The amount to Subtract. - /// - [Pure] - public Amount Subtract(Amount amount) => (Amount)(m_Value - amount.m_Value); - - /// AddsSubtract the specified percentage from the amount. - /// - /// The percentage to add. - /// - [Pure] - public Amount Subtract(Percentage p) => new(m_Value - p); - - /// Gets a percentage of the current amount. - /// - /// The percentage to get. - /// - [Pure] - public Amount Multiply(Percentage p) => (Amount)(m_Value * p); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Multiply(decimal factor) => (Amount)(m_Value * factor); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Multiply(double factor) => Multiply((decimal)factor); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Multiply(float factor) => Multiply((decimal)factor); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Multiply(long factor) => Multiply((decimal)factor); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Multiply(int factor) => Multiply((decimal)factor); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Multiply(short factor) => Multiply((decimal)factor); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [CLSCompliant(false)] - [Pure] - public Amount Multiply(ulong factor) => Multiply((decimal)factor); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [CLSCompliant(false)] - [Pure] - public Amount Multiply(uint factor) => Multiply((decimal)factor); - - /// Multiplies the amount with a specified factor. - /// - /// - /// The factor to multiply with. - /// - [CLSCompliant(false)] - [Pure] - public Amount Multiply(ushort factor) => Multiply((decimal)factor); - - /// Divides the amount by a specified amount. - /// - /// The amount to divides to.. - /// - [Pure] - public Amount Divide(Percentage p) => (Amount)(m_Value / p); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Divide(decimal factor) => (Amount)(m_Value / factor); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Divide(double factor) => Divide((decimal)factor); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Divide(float factor) => Divide((decimal)factor); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Divide(long factor) => Divide((decimal)factor); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Divide(int factor) => Divide((decimal)factor); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [Pure] - public Amount Divide(short factor) => Divide((decimal)factor); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [CLSCompliant(false)] - [Pure] - public Amount Divide(ulong factor) => Divide((decimal)factor); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [CLSCompliant(false)] - [Pure] - public Amount Divide(uint factor) => Divide((decimal)factor); - - /// Divides the amount by a specified factor. - /// - /// - /// The factor to multiply with. - /// - [CLSCompliant(false)] - [Pure] - public Amount Divide(ushort factor) => Divide((decimal)factor); + public Amount Abs() => new(m_Value.Abs()); /// Rounds the amount value to zero decimal places. [Pure] @@ -345,99 +120,6 @@ namespace Qowaiv.Financial; [Pure] public static Amount Min(params Amount[] values) => Guard.NotNull(values).Min(); - /// Unitary plusses the amount. - public static Amount operator +(Amount amount) => amount.Plus(); - - /// Negates the amount. - public static Amount operator -(Amount amount) => amount.Negate(); - - /// Increases the amount with one. - public static Amount operator ++(Amount amount) => amount.Increment(); - - /// Decreases the amount with one. - public static Amount operator --(Amount amount) => amount.Decrement(); - - /// Adds the left and the right amount. - public static Amount operator +(Amount l, Amount r) => l.Add(r); - - /// Adds the percentage to the amount. - public static Amount operator +(Amount amount, Percentage p) => amount.Add(p); - - /// Subtracts the right from the left amount. - public static Amount operator -(Amount l, Amount r) => l.Subtract(r); - - /// Subtracts the percentage from the amount. - public static Amount operator -(Amount amount, Percentage p) => amount.Subtract(p); - - /// Multiplies the amount with the factor. - public static Amount operator *(Amount amount, Percentage factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - public static Amount operator *(Amount amount, decimal factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - public static Amount operator *(Amount amount, double factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - public static Amount operator *(Amount amount, float factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - public static Amount operator *(Amount amount, long factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - public static Amount operator *(Amount amount, int factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - public static Amount operator *(Amount amount, short factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - [CLSCompliant(false)] - public static Amount operator *(Amount amount, ulong factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - [CLSCompliant(false)] - public static Amount operator *(Amount amount, uint factor) => amount.Multiply(factor); - - /// Multiplies the amount with the factor. - [CLSCompliant(false)] - public static Amount operator *(Amount amount, ushort factor) => amount.Multiply(factor); - - /// Divides the amount by an other amount. - public static decimal operator /(Amount numerator, Amount denominator) => numerator.m_Value / denominator.m_Value; - - /// Divides the amount by the percentage. - public static Amount operator /(Amount amount, Percentage p) => amount.Divide(p); - - /// Divides the amount by the factor. - public static Amount operator /(Amount amount, decimal factor) => amount.Divide(factor); - - /// Divides the amount by the factor. - public static Amount operator /(Amount amount, double factor) => amount.Divide(factor); - - /// Divides the amount by the factor. - public static Amount operator /(Amount amount, float factor) => amount.Divide(factor); - - /// Divides the amount by the factor. - public static Amount operator /(Amount amount, long factor) => amount.Divide(factor); - - /// Divides the amount by the factor. - public static Amount operator /(Amount amount, int factor) => amount.Divide(factor); - - /// Divides the amount by the factor. - public static Amount operator /(Amount amount, short factor) => amount.Divide(factor); - - /// Divides the amount by the factor. - [CLSCompliant(false)] - public static Amount operator /(Amount amount, ulong factor) => amount.Divide(factor); - - /// Divides the amount by the factor. - [CLSCompliant(false)] - public static Amount operator /(Amount amount, uint factor) => amount.Divide(factor); - - /// Divides the amount by the factor. - [CLSCompliant(false)] - public static Amount operator /(Amount amount, ushort factor) => amount.Divide(factor); - /// Serializes the amount to a JSON node. /// /// The serialized JSON number.