diff --git a/src/ImageSharp/Primitives/LongRational.cs b/src/ImageSharp/Primitives/LongRational.cs
index 9addf1e18a..d790b110d0 100644
--- a/src/ImageSharp/Primitives/LongRational.cs
+++ b/src/ImageSharp/Primitives/LongRational.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Primitives
///
/// This is a very simplified implementation of a rational number designed for use with metadata only.
///
- internal struct LongRational : IEquatable
+ internal readonly struct LongRational : IEquatable
{
///
/// Initializes a new instance of the struct.
@@ -26,126 +26,25 @@ namespace SixLabors.ImageSharp.Primitives
/// The number below the line in a vulgar fraction; a divisor.
///
public LongRational(long numerator, long denominator)
- : this(numerator, denominator, false)
- {
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- ///
- /// The number above the line in a vulgar fraction showing how many of the parts
- /// indicated by the denominator are taken.
- ///
- ///
- /// The number below the line in a vulgar fraction; a divisor.
- ///
- ///
- /// Whether to attempt to simplify the fractional parts.
- ///
- public LongRational(long numerator, long denominator, bool simplify)
- : this()
{
this.Numerator = numerator;
this.Denominator = denominator;
-
- if (simplify)
- {
- this.Simplify();
- }
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The to create the instance from.
- /// Whether to use the best possible precision when parsing the value.
- public LongRational(double value, bool bestPrecision)
- : this()
- {
- if (double.IsNaN(value))
- {
- this.Numerator = this.Denominator = 0;
- return;
- }
-
- if (double.IsPositiveInfinity(value))
- {
- this.Numerator = 1;
- this.Denominator = 0;
- return;
- }
-
- if (double.IsNegativeInfinity(value))
- {
- this.Numerator = -1;
- this.Denominator = 0;
- return;
- }
-
- this.Numerator = 1;
- this.Denominator = 1;
-
- double val = Math.Abs(value);
- double df = this.Numerator / (double)this.Denominator;
- double epsilon = bestPrecision ? double.Epsilon : .000001;
-
- while (Math.Abs(df - val) > epsilon)
- {
- if (df < val)
- {
- this.Numerator++;
- }
- else
- {
- this.Denominator++;
- this.Numerator = (int)(val * this.Denominator);
- }
-
- df = this.Numerator / (double)this.Denominator;
- }
-
- if (value < 0.0)
- {
- this.Numerator *= -1;
- }
-
- this.Simplify();
}
///
/// Gets the numerator of a number.
///
- public long Numerator
- {
- get;
- private set;
- }
+ public long Numerator { get; }
///
/// Gets the denominator of a number.
///
- public long Denominator
- {
- get;
- private set;
- }
+ public long Denominator { get; }
///
/// Gets a value indicating whether this instance is indeterminate.
///
- public bool IsIndeterminate
- {
- get
- {
- if (this.Denominator != 0)
- {
- return false;
- }
-
- return this.Numerator == 0;
- }
- }
+ public bool IsIndeterminate => this.Denominator == 0 && this.Numerator == 0;
///
/// Gets a value indicating whether this instance is an integer (n, 1)
@@ -155,76 +54,28 @@ namespace SixLabors.ImageSharp.Primitives
///
/// Gets a value indicating whether this instance is equal to negative infinity (-1, 0)
///
- public bool IsNegativeInfinity
- {
- get
- {
- if (this.Denominator != 0)
- {
- return false;
- }
-
- return this.Numerator == -1;
- }
- }
+ public bool IsNegativeInfinity => this.Denominator == 0 && this.Numerator == -1;
///
/// Gets a value indicating whether this instance is equal to positive infinity (1, 0)
///
- public bool IsPositiveInfinity
- {
- get
- {
- if (this.Denominator != 0)
- {
- return false;
- }
-
- return this.Numerator == 1;
- }
- }
+ public bool IsPositiveInfinity => this.Denominator == 0 && this.Numerator == 1;
///
/// Gets a value indicating whether this instance is equal to 0 (0, 1)
///
- public bool IsZero
- {
- get
- {
- if (this.Denominator != 1)
- {
- return false;
- }
-
- return this.Numerator == 0;
- }
- }
+ public bool IsZero => this.Denominator == 1 && this.Numerator == 0;
///
public bool Equals(LongRational other)
{
- if (this.Denominator == other.Denominator)
- {
- return this.Numerator == other.Numerator;
- }
-
- if (this.Numerator == 0 && this.Denominator == 0)
- {
- return other.Numerator == 0 && other.Denominator == 0;
- }
-
- if (other.Numerator == 0 && other.Denominator == 0)
- {
- return this.Numerator == 0 && this.Denominator == 0;
- }
-
- return (this.Numerator * other.Denominator) == (this.Denominator * other.Numerator);
+ return this.Numerator == other.Numerator && this.Denominator == other.Denominator;
}
///
public override int GetHashCode()
{
- return this.GetHashCode(this);
+ return ((this.Numerator * 397) ^ this.Denominator).GetHashCode();
}
///
@@ -276,78 +127,100 @@ namespace SixLabors.ImageSharp.Primitives
}
///
- /// Finds the greatest common divisor of two values.
+ /// Create a new instance of the struct from a double value.
///
- /// The first value
- /// The second value
- /// The
- private static long GreatestCommonDivisor(long left, long right)
+ /// The to create the instance from.
+ /// Whether to use the best possible precision when parsing the value.
+ public static LongRational FromDouble(double value, bool bestPrecision)
{
- return right == 0 ? left : GreatestCommonDivisor(right, left % right);
- }
+ if (double.IsNaN(value))
+ {
+ return new LongRational(0, 0);
+ }
- ///
- /// Simplifies the
- ///
- private void Simplify()
- {
- if (this.IsIndeterminate)
+ if (double.IsPositiveInfinity(value))
{
- return;
+ return new LongRational(1, 0);
}
- if (this.IsNegativeInfinity)
+ if (double.IsNegativeInfinity(value))
{
- return;
+ return new LongRational(-1, 0);
}
- if (this.IsPositiveInfinity)
+ long numerator = 1;
+ long denominator = 1;
+
+ double val = Math.Abs(value);
+ double df = numerator / (double)denominator;
+ double epsilon = bestPrecision ? double.Epsilon : .000001;
+
+ while (Math.Abs(df - val) > epsilon)
{
- return;
+ if (df < val)
+ {
+ numerator++;
+ }
+ else
+ {
+ denominator++;
+ numerator = (int)(val * denominator);
+ }
+
+ df = numerator / (double)denominator;
}
- if (this.IsInteger)
+ if (value < 0.0)
{
- return;
+ numerator *= -1;
}
- if (this.IsZero)
+ return new LongRational(numerator, denominator).Simplify();
+ }
+
+ ///
+ /// Finds the greatest common divisor of two values.
+ ///
+ /// The first value
+ /// The second value
+ /// The
+ private static long GreatestCommonDivisor(long left, long right)
+ {
+ return right == 0 ? left : GreatestCommonDivisor(right, left % right);
+ }
+
+ ///
+ /// Simplifies the
+ ///
+ public LongRational Simplify()
+ {
+ if (this.IsIndeterminate ||
+ this.IsNegativeInfinity ||
+ this.IsPositiveInfinity ||
+ this.IsInteger ||
+ this.IsZero)
{
- return;
+ return this;
}
if (this.Numerator == 0)
{
- this.Denominator = 0;
- return;
+ return new LongRational(0, 0);
}
if (this.Numerator == this.Denominator)
{
- this.Numerator = 1;
- this.Denominator = 1;
+ return new LongRational(1, 1);
}
long gcd = GreatestCommonDivisor(Math.Abs(this.Numerator), Math.Abs(this.Denominator));
+
if (gcd > 1)
{
- this.Numerator = this.Numerator / gcd;
- this.Denominator = this.Denominator / gcd;
+ return new LongRational(this.Numerator / gcd, this.Denominator / gcd);
}
- }
- ///
- /// Returns the hash code for this instance.
- ///
- ///
- /// The instance of to return the hash code for.
- ///
- ///
- /// A 32-bit signed integer that is the hash code for this instance.
- ///
- private int GetHashCode(LongRational rational)
- {
- return ((rational.Numerator * 397) ^ rational.Denominator).GetHashCode();
+ return this;
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Primitives/Rational.cs b/src/ImageSharp/Primitives/Rational.cs
index fa3961ffa8..b598f0e02f 100644
--- a/src/ImageSharp/Primitives/Rational.cs
+++ b/src/ImageSharp/Primitives/Rational.cs
@@ -41,10 +41,18 @@ namespace SixLabors.ImageSharp.Primitives
/// Specified if the rational should be simplified.
public Rational(uint numerator, uint denominator, bool simplify)
{
- var rational = new LongRational(numerator, denominator, simplify);
-
- this.Numerator = (uint)rational.Numerator;
- this.Denominator = (uint)rational.Denominator;
+ if (simplify)
+ {
+ LongRational rational = new LongRational(numerator, denominator).Simplify();
+
+ this.Numerator = (uint)rational.Numerator;
+ this.Denominator = (uint)rational.Denominator;
+ }
+ else
+ {
+ this.Numerator = numerator;
+ this.Denominator = denominator;
+ }
}
///
@@ -63,7 +71,7 @@ namespace SixLabors.ImageSharp.Primitives
/// Whether to use the best possible precision when parsing the value.
public Rational(double value, bool bestPrecision)
{
- var rational = new LongRational(Math.Abs(value), bestPrecision);
+ var rational = LongRational.FromDouble(Math.Abs(value), bestPrecision);
this.Numerator = (uint)rational.Numerator;
this.Denominator = (uint)rational.Denominator;
diff --git a/src/ImageSharp/Primitives/SignedRational.cs b/src/ImageSharp/Primitives/SignedRational.cs
index bc0e41966e..7e486e4f22 100644
--- a/src/ImageSharp/Primitives/SignedRational.cs
+++ b/src/ImageSharp/Primitives/SignedRational.cs
@@ -41,10 +41,18 @@ namespace SixLabors.ImageSharp.Primitives
/// Specified if the rational should be simplified.
public SignedRational(int numerator, int denominator, bool simplify)
{
- var rational = new LongRational(numerator, denominator, simplify);
-
- this.Numerator = (int)rational.Numerator;
- this.Denominator = (int)rational.Denominator;
+ if (simplify)
+ {
+ LongRational rational = new LongRational(numerator, denominator).Simplify();
+
+ this.Numerator = (int)rational.Numerator;
+ this.Denominator = (int)rational.Denominator;
+ }
+ else
+ {
+ this.Numerator = numerator;
+ this.Denominator = denominator;
+ }
}
///
@@ -63,7 +71,7 @@ namespace SixLabors.ImageSharp.Primitives
/// Whether to use the best possible precision when parsing the value.
public SignedRational(double value, bool bestPrecision)
{
- var rational = new LongRational(value, bestPrecision);
+ var rational = LongRational.FromDouble(value, bestPrecision);
this.Numerator = (int)rational.Numerator;
this.Denominator = (int)rational.Denominator;