diff --git a/src/Rationals/Formatting.cs b/src/Rationals/Formatting.cs index b9d4e97..7f49815 100644 --- a/src/Rationals/Formatting.cs +++ b/src/Rationals/Formatting.cs @@ -62,6 +62,24 @@ public IEnumerable Digits /// Ignored, custom format providers are not supported public string ToString(string format, IFormatProvider formatProvider) => ToString(format); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + + /// Tries to format the value of the current instance into the provided span of characters. + /// When this method returns, this instance's value formatted as a span of characters. + /// When this method returns, the number of characters that were written in . + /// A span containing the characters that represent a standard or custom format string that defines the acceptable format for . + /// An optional object that supplies culture-specific formatting information for . + /// if the formatting was successful; otherwise, . + /// + /// An implementation of this interface should produce the same string of characters as an implementation of + /// on the same type. + /// TryFormat should return false only if there is not enough space in the destination buffer. Any other failures should throw an exception. + /// + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider provider) + => throw new NotImplementedException(); + +#endif + /// /// Formats rational number to string /// diff --git a/src/Rationals/GenericMath.cs b/src/Rationals/GenericMath.cs new file mode 100644 index 0000000..bf3b7a0 --- /dev/null +++ b/src/Rationals/GenericMath.cs @@ -0,0 +1,189 @@ +using System; +using System.Numerics; + +#if NET7_0_OR_GREATER + +namespace Rationals +{ + public partial struct Rational : INumber + { + /// + static Rational INumberBase.One + => One; + + /// + static int INumberBase.Radix + => 2; + + /// + static Rational INumberBase.Zero + => Zero; + + /// + static Rational IAdditiveIdentity.AdditiveIdentity + => Zero; + + /// + static Rational IMultiplicativeIdentity.MultiplicativeIdentity + => One; + + /// + static bool INumberBase.IsCanonical(Rational value) + { + var canonical = value.CanonicalForm; + return value.Numerator == canonical.Numerator && value.Denominator == canonical.Denominator; + } + + /// + static bool INumberBase.IsComplexNumber(Rational value) + => false; + + /// + static bool INumberBase.IsEvenInteger(Rational value) + { + var canonical = value.CanonicalForm; + return canonical.Denominator.IsOne && canonical.Numerator.IsEven; + } + + /// + static bool INumberBase.IsFinite(Rational value) + => true; + + /// + static bool INumberBase.IsImaginaryNumber(Rational value) + => false; + + /// + static bool INumberBase.IsInfinity(Rational value) + => false; + + /// + static bool INumberBase.IsInteger(Rational value) + => value.CanonicalForm.Denominator.IsOne; + + /// + static bool INumberBase.IsNaN(Rational value) + => value.IsNaN; + + /// + static bool INumberBase.IsNegative(Rational value) + => value.Sign < 0; + + /// + static bool INumberBase.IsNegativeInfinity(Rational value) + => false; + + /// + static bool INumberBase.IsNormal(Rational value) + => !value.IsZero && !value.IsNaN; + + /// + static bool INumberBase.IsOddInteger(Rational value) + { + var canonical = value.CanonicalForm; + return canonical.Denominator.IsOne && !canonical.Numerator.IsEven; + } + + /// + static bool INumberBase.IsPositive(Rational value) + => value.Sign > 0; + + /// + static bool INumberBase.IsPositiveInfinity(Rational value) + => false; + + /// + static bool INumberBase.IsRealNumber(Rational value) + => true; + + /// + static bool INumberBase.IsSubnormal(Rational value) + => false; + + /// + static bool INumberBase.IsZero(Rational value) + => value.IsZero; + + private static Rational MaxMagnitudeInner(Rational x, Rational y) + { + if (x.IsNaN) + return NaN; + + if (y.IsNaN) + return NaN; + + var ax = Abs(x); + var ay = Abs(y); + + if (ax > ay) + return x; + + if (ax == ay) + return x.Sign < 0 ? y : x; + + return y; + } + + private static Rational MinMagnitudeInner(Rational x, Rational y) + { + if (x.IsNaN) + return NaN; + + if (y.IsNaN) + return NaN; + + var ax = Abs(x); + var ay = Abs(y); + + if (ax < ay) + return x; + + if (ax == ay) + return x.Sign < 0 ? x : y; + + return y; + } + + /// + static Rational INumberBase.MaxMagnitude(Rational x, Rational y) + => MaxMagnitudeInner(x, y); + + /// + static Rational INumberBase.MaxMagnitudeNumber(Rational x, Rational y) + => MaxMagnitudeInner(x, y); + + /// + static Rational INumberBase.MinMagnitude(Rational x, Rational y) + => MinMagnitudeInner(x, y); + + /// + static Rational INumberBase.MinMagnitudeNumber(Rational x, Rational y) + => MinMagnitudeInner(x, y); + + /// + static bool INumberBase.TryConvertFromChecked(TOther value, out Rational result) + => throw new NotImplementedException(); + + /// + static bool INumberBase.TryConvertFromSaturating(TOther value, out Rational result) + => throw new NotImplementedException(); + + /// + static bool INumberBase.TryConvertFromTruncating(TOther value, out Rational result) + => throw new NotImplementedException(); + + /// + static bool INumberBase.TryConvertToChecked(Rational value, out TOther result) + => throw new NotImplementedException(); + + /// + static bool INumberBase.TryConvertToSaturating(Rational value, out TOther result) + => throw new NotImplementedException(); + + /// + static bool INumberBase.TryConvertToTruncating(Rational value, out TOther result) + => throw new NotImplementedException(); + } +} + +#endif diff --git a/src/Rationals/Operators.cs b/src/Rationals/Operators.cs index 1e83b2b..fe8b730 100644 --- a/src/Rationals/Operators.cs +++ b/src/Rationals/Operators.cs @@ -1,4 +1,6 @@ -namespace Rationals +using System; + +namespace Rationals { /// /// Rational number. @@ -69,5 +71,17 @@ public partial struct Rational /// Overload of the >= operator. /// public static bool operator >=(Rational left, Rational right) => !left.IsNaN && !right.IsNaN && left.CompareTo(right) >= 0; + + /// + /// Overload of the % operator. + /// + public static Rational operator %(Rational left, Rational right) + => throw new NotImplementedException(); + + /// + /// Overload of the unary + operator. + /// + public static Rational operator +(Rational value) + => new(+value.Denominator, +value.Numerator); } -} \ No newline at end of file +} diff --git a/src/Rationals/Parsing.cs b/src/Rationals/Parsing.cs index f7781f3..fecc634 100644 --- a/src/Rationals/Parsing.cs +++ b/src/Rationals/Parsing.cs @@ -52,6 +52,23 @@ public static Rational Parse(string value, NumberStyles style, IFormatProvider p return Parse(value, style, NumberFormatInfo.GetInstance(provider)); } + +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + + /// + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public static Rational Parse(ReadOnlySpan value, IFormatProvider provider) + { + return Parse(value, NumberStyles.Float, NumberFormatInfo.GetInstance(provider)); + } + + /// + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public static Rational Parse(ReadOnlySpan value, NumberStyles style, IFormatProvider provider) + => Parse(value.ToString(), style, NumberFormatInfo.GetInstance(provider)); + +#endif + private static Rational Parse(string value, NumberStyles style, NumberFormatInfo info) { if (!TryParse(value, style, info, out var result)) @@ -74,6 +91,29 @@ public static bool TryParse(string value, NumberStyles style, IFormatProvider pr return TryParse(value, style, NumberFormatInfo.GetInstance(provider), out result); } + /// + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public static bool TryParse(string value, IFormatProvider provider, out Rational result) + { + return TryParse(value, NumberStyles.Float, NumberFormatInfo.GetInstance(provider), out result); + } + +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + + /// + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public static bool TryParse(ReadOnlySpan value, IFormatProvider provider, out Rational result) + { + return TryParse(value, NumberStyles.Float, NumberFormatInfo.GetInstance(provider), out result); + } + + /// + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public static bool TryParse(ReadOnlySpan value, NumberStyles style, IFormatProvider provider, out Rational result) + => TryParse(value.ToString(), style, NumberFormatInfo.GetInstance(provider), out result); + +#endif + private static bool TryParse(string value, NumberStyles style, NumberFormatInfo info, out Rational result) { result = default; diff --git a/src/Rationals/Rationals.csproj b/src/Rationals/Rationals.csproj index 08677e8..85142a1 100644 --- a/src/Rationals/Rationals.csproj +++ b/src/Rationals/Rationals.csproj @@ -1,8 +1,8 @@ - netstandard1.3;net40; - 7.3 + net7.0;netstandard2.1;netstandard1.3;net40 + 11 true