mirror of https://github.com/SixLabors/ImageSharp
11 changed files with 362 additions and 1356 deletions
@ -1,209 +0,0 @@ |
|||||
// <copyright file="Ellipse.cs" company="Six Labors">
|
|
||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Numerics; |
|
||||
|
|
||||
namespace SixLabors.Primitives |
|
||||
{ |
|
||||
internal struct ApproximateFloatComparer |
|
||||
: IEqualityComparer<float>, |
|
||||
IEqualityComparer<Vector4>, |
|
||||
IEqualityComparer<Vector2>, |
|
||||
IEqualityComparer<Vector3>, |
|
||||
IEqualityComparer<System.Numerics.Matrix3x2>, |
|
||||
IEqualityComparer<Matrix4x4>, |
|
||||
IEqualityComparer<PointF> |
|
||||
{ |
|
||||
private readonly float tolerance; |
|
||||
const float defaultTolerance = 1e-5f; |
|
||||
|
|
||||
public ApproximateFloatComparer(float tolerance = defaultTolerance) |
|
||||
{ |
|
||||
this.tolerance = tolerance; |
|
||||
} |
|
||||
|
|
||||
public static bool Equal(float x, float y, float tolerance) |
|
||||
{ |
|
||||
float d = x - y; |
|
||||
|
|
||||
return d > -tolerance && d < tolerance; |
|
||||
} |
|
||||
|
|
||||
public static bool Equal(float x, float y) |
|
||||
{ |
|
||||
return Equal(x, y, defaultTolerance); |
|
||||
} |
|
||||
|
|
||||
public bool Equals(float x, float y) |
|
||||
{ |
|
||||
return Equal(x, y, this.tolerance); |
|
||||
} |
|
||||
|
|
||||
public int GetHashCode(float obj) |
|
||||
{ |
|
||||
var diff = obj % this.tolerance;// how different from tollerance are we?
|
|
||||
return (obj - diff).GetHashCode(); |
|
||||
} |
|
||||
|
|
||||
public bool Equals(Vector4 a, Vector4 b) |
|
||||
{ |
|
||||
return this.Equals(a.X, b.X) && this.Equals(a.Y, b.Y) && this.Equals(a.Z, b.Z) && this.Equals(a.W, b.W); |
|
||||
} |
|
||||
|
|
||||
public int GetHashCode(Vector4 obj) |
|
||||
{ |
|
||||
int hash = GetHashCode(obj.X); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.Y)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.Z)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.W)); |
|
||||
return hash; |
|
||||
} |
|
||||
|
|
||||
public bool Equals(Vector2 a, Vector2 b) |
|
||||
{ |
|
||||
return this.Equals(a.X, b.X) && this.Equals(a.Y, b.Y); |
|
||||
} |
|
||||
|
|
||||
public int GetHashCode(Vector2 obj) |
|
||||
{ |
|
||||
int hash = GetHashCode(obj.X); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.Y)); |
|
||||
return hash; |
|
||||
} |
|
||||
|
|
||||
public bool Equals(Vector3 a, Vector3 b) |
|
||||
{ |
|
||||
return this.Equals(a.X, b.X) && this.Equals(a.Y, b.Y) && this.Equals(a.Z, b.Z); |
|
||||
} |
|
||||
|
|
||||
public int GetHashCode(Vector3 obj) |
|
||||
{ |
|
||||
int hash = GetHashCode(obj.X); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.Y)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.Z)); |
|
||||
return hash; |
|
||||
} |
|
||||
|
|
||||
public static bool Equal(System.Numerics.Matrix3x2 a, System.Numerics.Matrix3x2 b, float tolerance) |
|
||||
{ |
|
||||
return Equal(a.M11, b.M11, tolerance) && |
|
||||
Equal(a.M12, b.M12, tolerance) && |
|
||||
Equal(a.M21, b.M21, tolerance) && |
|
||||
Equal(a.M22, b.M22, tolerance) && |
|
||||
Equal(a.M31, b.M31, tolerance) && |
|
||||
Equal(a.M32, b.M32, tolerance); |
|
||||
} |
|
||||
|
|
||||
public static bool Equal(System.Numerics.Matrix3x2 a, System.Numerics.Matrix3x2 b) |
|
||||
{ |
|
||||
return Equal(a, b, defaultTolerance); |
|
||||
} |
|
||||
|
|
||||
public bool Equals(System.Numerics.Matrix3x2 a, System.Numerics.Matrix3x2 b) |
|
||||
{ |
|
||||
return Equal(a, b, this.tolerance); |
|
||||
} |
|
||||
|
|
||||
public int GetHashCode(System.Numerics.Matrix3x2 obj) |
|
||||
{ |
|
||||
int hash = GetHashCode(obj.M11); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M11)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M12)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M21)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M22)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M31)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M32)); |
|
||||
return hash; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public static bool Equal(Matrix4x4 a, Matrix4x4 b, float tolerance) |
|
||||
{ |
|
||||
return |
|
||||
Equal(a.M11, b.M11, tolerance) && |
|
||||
Equal(a.M12, b.M12, tolerance) && |
|
||||
Equal(a.M13, b.M13, tolerance) && |
|
||||
Equal(a.M14, b.M14, tolerance) && |
|
||||
|
|
||||
Equal(a.M21, b.M21, tolerance) && |
|
||||
Equal(a.M22, b.M22, tolerance) && |
|
||||
Equal(a.M23, b.M23, tolerance) && |
|
||||
Equal(a.M24, b.M24, tolerance) && |
|
||||
|
|
||||
Equal(a.M31, b.M31, tolerance) && |
|
||||
Equal(a.M32, b.M32, tolerance) && |
|
||||
Equal(a.M33, b.M33, tolerance) && |
|
||||
Equal(a.M34, b.M34, tolerance) && |
|
||||
|
|
||||
Equal(a.M41, b.M41, tolerance) && |
|
||||
Equal(a.M42, b.M42, tolerance) && |
|
||||
Equal(a.M43, b.M43, tolerance) && |
|
||||
Equal(a.M44, b.M44, tolerance); |
|
||||
} |
|
||||
|
|
||||
public static bool Equal(Matrix4x4 a, Matrix4x4 b) |
|
||||
{ |
|
||||
return Equal(a, b, defaultTolerance); |
|
||||
} |
|
||||
|
|
||||
public bool Equals(Matrix4x4 a, Matrix4x4 b) |
|
||||
{ |
|
||||
return Equal(a, b, this.tolerance); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public int GetHashCode(Matrix4x4 obj) |
|
||||
{ |
|
||||
int hash = GetHashCode(obj.M11); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M12)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M13)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M14)); |
|
||||
|
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M21)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M22)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M23)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M24)); |
|
||||
|
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M31)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M32)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M33)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M34)); |
|
||||
|
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M41)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M42)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M43)); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.M44)); |
|
||||
return hash; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public static bool Equal(PointF a, PointF b, float tolerance) |
|
||||
{ |
|
||||
return |
|
||||
Equal(a.X, b.X, tolerance) && |
|
||||
Equal(a.Y, b.Y, tolerance); |
|
||||
} |
|
||||
|
|
||||
public static bool Equal(PointF a, PointF b) |
|
||||
{ |
|
||||
return Equal(a, b, defaultTolerance); |
|
||||
} |
|
||||
|
|
||||
public bool Equals(PointF a, PointF b) |
|
||||
{ |
|
||||
return Equal(a, b, this.tolerance); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public int GetHashCode(PointF obj) |
|
||||
{ |
|
||||
int hash = GetHashCode(obj.X); |
|
||||
hash = HashHelpers.Combine(hash, GetHashCode(obj.Y)); |
|
||||
return hash; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,180 +0,0 @@ |
|||||
// <copyright file="Ellipse.cs" company="Six Labors">
|
|
||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace SixLabors.Primitives |
|
||||
{ |
|
||||
using System; |
|
||||
using System.ComponentModel; |
|
||||
using System.Numerics; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents an ellipse.
|
|
||||
/// </summary>
|
|
||||
public struct Ellipse : IEquatable<Ellipse> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Represents a <see cref="Ellipse"/> that has X and Y values set to zero.
|
|
||||
/// </summary>
|
|
||||
public static readonly Ellipse Empty = default(Ellipse); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// The center point.
|
|
||||
/// </summary>
|
|
||||
private Point center; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="Ellipse"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="center">The center point.</param>
|
|
||||
/// <param name="radiusX">The x-radius.</param>
|
|
||||
/// <param name="radiusY">The y-radius.</param>
|
|
||||
public Ellipse(Point center, float radiusX, float radiusY) |
|
||||
{ |
|
||||
this.center = center; |
|
||||
this.RadiusX = radiusX; |
|
||||
this.RadiusY = radiusY; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the x-radius of this <see cref="Ellipse"/>.
|
|
||||
/// </summary>
|
|
||||
public float RadiusX { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the y-radius of this <see cref="Ellipse"/>.
|
|
||||
/// </summary>
|
|
||||
public float RadiusY { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether this <see cref="Ellipse"/> is empty.
|
|
||||
/// </summary>
|
|
||||
[EditorBrowsable(EditorBrowsableState.Never)] |
|
||||
public bool IsEmpty => this.Equals(Empty); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Compares two <see cref="Ellipse"/> objects for equality.
|
|
||||
/// </summary>
|
|
||||
/// <param name="left">
|
|
||||
/// The <see cref="Ellipse"/> on the left side of the operand.
|
|
||||
/// </param>
|
|
||||
/// <param name="right">
|
|
||||
/// The <see cref="Ellipse"/> on the right side of the operand.
|
|
||||
/// </param>
|
|
||||
/// <returns>
|
|
||||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|
||||
/// </returns>
|
|
||||
public static bool operator ==(Ellipse left, Ellipse right) |
|
||||
{ |
|
||||
return left.Equals(right); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Compares two <see cref="Ellipse"/> objects for inequality.
|
|
||||
/// </summary>
|
|
||||
/// <param name="left">
|
|
||||
/// The <see cref="Ellipse"/> on the left side of the operand.
|
|
||||
/// </param>
|
|
||||
/// <param name="right">
|
|
||||
/// The <see cref="Ellipse"/> on the right side of the operand.
|
|
||||
/// </param>
|
|
||||
/// <returns>
|
|
||||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|
||||
/// </returns>
|
|
||||
public static bool operator !=(Ellipse left, Ellipse right) |
|
||||
{ |
|
||||
return !left.Equals(right); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns the center point of the given <see cref="Ellipse"/>
|
|
||||
/// </summary>
|
|
||||
/// <param name="ellipse">The ellipse</param>
|
|
||||
/// <returns><see cref="Vector2"/></returns>
|
|
||||
public static Vector2 Center(Ellipse ellipse) |
|
||||
{ |
|
||||
return new Vector2(ellipse.center.X, ellipse.center.Y); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Determines if the specfied point is contained within the rectangular region defined by
|
|
||||
/// this <see cref="Ellipse"/>.
|
|
||||
/// </summary>
|
|
||||
/// <param name="x">The x-coordinate of the given point.</param>
|
|
||||
/// <param name="y">The y-coordinate of the given point.</param>
|
|
||||
/// <returns>The <see cref="bool"/></returns>
|
|
||||
public bool Contains(int x, int y) |
|
||||
{ |
|
||||
if (this.RadiusX <= 0 || this.RadiusY <= 0) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
// TODO: SIMD?
|
|
||||
// This is a more general form of the circle equation
|
|
||||
// X^2/a^2 + Y^2/b^2 <= 1
|
|
||||
Point normalized = new Point(x - this.center.X, y - this.center.Y); |
|
||||
int nX = normalized.X; |
|
||||
int nY = normalized.Y; |
|
||||
|
|
||||
return ((double)(nX * nX) / (this.RadiusX * this.RadiusX)) |
|
||||
+ ((double)(nY * nY) / (this.RadiusY * this.RadiusY)) |
|
||||
<= 1.0; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override int GetHashCode() |
|
||||
{ |
|
||||
return this.GetHashCode(this); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override string ToString() |
|
||||
{ |
|
||||
if (this.IsEmpty) |
|
||||
{ |
|
||||
return "Ellipse [ Empty ]"; |
|
||||
} |
|
||||
|
|
||||
return |
|
||||
$"Ellipse [ RadiusX={this.RadiusX}, RadiusY={this.RadiusX}, Centre={this.center.X},{this.center.Y} ]"; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Equals(object obj) |
|
||||
{ |
|
||||
if (obj is Ellipse) |
|
||||
{ |
|
||||
return this.Equals((Ellipse)obj); |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public bool Equals(Ellipse other) |
|
||||
{ |
|
||||
return this.center.Equals(other.center) |
|
||||
&& this.RadiusX.Equals(other.RadiusX) |
|
||||
&& this.RadiusY.Equals(other.RadiusY); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns the hash code for this instance.
|
|
||||
/// </summary>
|
|
||||
/// <param name="ellipse">
|
|
||||
/// The instance of <see cref="Point"/> to return the hash code for.
|
|
||||
/// </param>
|
|
||||
/// <returns>
|
|
||||
/// A 32-bit signed integer that is the hash code for this instance.
|
|
||||
/// </returns>
|
|
||||
private int GetHashCode(Ellipse ellipse) |
|
||||
{ |
|
||||
int hashCode = ellipse.center.GetHashCode(); |
|
||||
hashCode = HashHelpers.Combine(hashCode, ellipse.RadiusX.GetHashCode()); |
|
||||
hashCode = HashHelpers.Combine(hashCode, ellipse.RadiusY.GetHashCode()); |
|
||||
return hashCode; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,352 +0,0 @@ |
|||||
// <copyright file="LongRational.cs" company="Six Labors">
|
|
||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace SixLabors.Primitives |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Globalization; |
|
||||
using System.Text; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents a number that can be expressed as a fraction
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// This is a very simplified implementation of a rational number designed for use with metadata only.
|
|
||||
/// </remarks>
|
|
||||
internal struct LongRational : IEquatable<LongRational> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="LongRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="numerator">
|
|
||||
/// The number above the line in a vulgar fraction showing how many of the parts
|
|
||||
/// indicated by the denominator are taken.
|
|
||||
/// </param>
|
|
||||
/// <param name="denominator">
|
|
||||
/// The number below the line in a vulgar fraction; a divisor.
|
|
||||
/// </param>
|
|
||||
public LongRational(long numerator, long denominator) |
|
||||
: this(numerator, denominator, false) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="LongRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="numerator">
|
|
||||
/// The number above the line in a vulgar fraction showing how many of the parts
|
|
||||
/// indicated by the denominator are taken.
|
|
||||
/// </param>
|
|
||||
/// <param name="denominator">
|
|
||||
/// The number below the line in a vulgar fraction; a divisor.
|
|
||||
/// </param>
|
|
||||
/// <param name="simplify">
|
|
||||
/// Whether to attempt to simplify the fractional parts.
|
|
||||
/// </param>
|
|
||||
public LongRational(long numerator, long denominator, bool simplify) |
|
||||
: this() |
|
||||
{ |
|
||||
this.Numerator = numerator; |
|
||||
this.Denominator = denominator; |
|
||||
|
|
||||
if (simplify) |
|
||||
{ |
|
||||
this.Simplify(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="LongRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|
||||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|
||||
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(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the numerator of a number.
|
|
||||
/// </summary>
|
|
||||
public long Numerator |
|
||||
{ |
|
||||
get; |
|
||||
private set; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the denominator of a number.
|
|
||||
/// </summary>
|
|
||||
public long Denominator |
|
||||
{ |
|
||||
get; |
|
||||
private set; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether this instance is indeterminate.
|
|
||||
/// </summary>
|
|
||||
public bool IsIndeterminate |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
if (this.Denominator != 0) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
return this.Numerator == 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether this instance is an integer (n, 1)
|
|
||||
/// </summary>
|
|
||||
public bool IsInteger => this.Denominator == 1; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether this instance is equal to negative infinity (-1, 0)
|
|
||||
/// </summary>
|
|
||||
public bool IsNegativeInfinity |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
if (this.Denominator != 0) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
return this.Numerator == -1; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether this instance is equal to positive infinity (1, 0)
|
|
||||
/// </summary>
|
|
||||
public bool IsPositiveInfinity |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
if (this.Denominator != 0) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
return this.Numerator == 1; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether this instance is equal to 0 (0, 1)
|
|
||||
/// </summary>
|
|
||||
public bool IsZero |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
if (this.Denominator != 1) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
return this.Numerator == 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
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); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override int GetHashCode() |
|
||||
{ |
|
||||
return this.GetHashCode(this); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override string ToString() |
|
||||
{ |
|
||||
return this.ToString(CultureInfo.InvariantCulture); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts the numeric value of this instance to its equivalent string representation using
|
|
||||
/// the specified culture-specific format information.
|
|
||||
/// </summary>
|
|
||||
/// <param name="provider">
|
|
||||
/// An object that supplies culture-specific formatting information.
|
|
||||
/// </param>
|
|
||||
/// <returns>The <see cref="string"/></returns>
|
|
||||
public string ToString(IFormatProvider provider) |
|
||||
{ |
|
||||
if (this.IsIndeterminate) |
|
||||
{ |
|
||||
return "[ Indeterminate ]"; |
|
||||
} |
|
||||
|
|
||||
if (this.IsPositiveInfinity) |
|
||||
{ |
|
||||
return "[ PositiveInfinity ]"; |
|
||||
} |
|
||||
|
|
||||
if (this.IsNegativeInfinity) |
|
||||
{ |
|
||||
return "[ NegativeInfinity ]"; |
|
||||
} |
|
||||
|
|
||||
if (this.IsZero) |
|
||||
{ |
|
||||
return "0"; |
|
||||
} |
|
||||
|
|
||||
if (this.IsInteger) |
|
||||
{ |
|
||||
return this.Numerator.ToString(provider); |
|
||||
} |
|
||||
|
|
||||
StringBuilder sb = new StringBuilder(); |
|
||||
sb.Append(this.Numerator.ToString(provider)); |
|
||||
sb.Append("/"); |
|
||||
sb.Append(this.Denominator.ToString(provider)); |
|
||||
return sb.ToString(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Finds the greatest common divisor of two <see cref="long"/> values.
|
|
||||
/// </summary>
|
|
||||
/// <param name="left">The first value</param>
|
|
||||
/// <param name="right">The second value</param>
|
|
||||
/// <returns>The <see cref="long"/></returns>
|
|
||||
private static long GreatestCommonDivisor(long left, long right) |
|
||||
{ |
|
||||
return right == 0 ? left : GreatestCommonDivisor(right, left % right); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Simplifies the <see cref="LongRational"/>
|
|
||||
/// </summary>
|
|
||||
private void Simplify() |
|
||||
{ |
|
||||
if (this.IsIndeterminate) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (this.IsNegativeInfinity) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (this.IsPositiveInfinity) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (this.IsInteger) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (this.IsZero) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (this.Numerator == 0) |
|
||||
{ |
|
||||
this.Denominator = 0; |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (this.Numerator == this.Denominator) |
|
||||
{ |
|
||||
this.Numerator = 1; |
|
||||
this.Denominator = 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; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns the hash code for this instance.
|
|
||||
/// </summary>
|
|
||||
/// <param name="rational">
|
|
||||
/// The instance of <see cref="LongRational"/> to return the hash code for.
|
|
||||
/// </param>
|
|
||||
/// <returns>
|
|
||||
/// A 32-bit signed integer that is the hash code for this instance.
|
|
||||
/// </returns>
|
|
||||
private int GetHashCode(LongRational rational) => HashHelpers.Combine(rational.Numerator.GetHashCode(), rational.Denominator.GetHashCode()); |
|
||||
} |
|
||||
} |
|
||||
@ -1,189 +0,0 @@ |
|||||
// <copyright file="Rational.cs" company="Six Labors">
|
|
||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace SixLabors.Primitives |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Globalization; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents a number that can be expressed as a fraction.
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// This is a very simplified implementation of a rational number designed for use with metadata only.
|
|
||||
/// </remarks>
|
|
||||
public struct Rational : IEquatable<Rational> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="uint"/> to create the rational from.</param>
|
|
||||
public Rational(uint value) |
|
||||
: this(value, 1) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="numerator">The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.</param>
|
|
||||
/// <param name="denominator">The number below the line in a vulgar fraction; a divisor.</param>
|
|
||||
public Rational(uint numerator, uint denominator) |
|
||||
: this(numerator, denominator, true) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="numerator">The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.</param>
|
|
||||
/// <param name="denominator">The number below the line in a vulgar fraction; a divisor.</param>
|
|
||||
/// <param name="simplify">Specified if the rational should be simplified.</param>
|
|
||||
public Rational(uint numerator, uint denominator, bool simplify) |
|
||||
{ |
|
||||
LongRational rational = new LongRational(numerator, denominator, simplify); |
|
||||
|
|
||||
this.Numerator = (uint)rational.Numerator; |
|
||||
this.Denominator = (uint)rational.Denominator; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|
||||
public Rational(double value) |
|
||||
: this(value, false) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|
||||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|
||||
public Rational(double value, bool bestPrecision) |
|
||||
{ |
|
||||
LongRational rational = new LongRational(Math.Abs(value), bestPrecision); |
|
||||
|
|
||||
this.Numerator = (uint)rational.Numerator; |
|
||||
this.Denominator = (uint)rational.Denominator; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the numerator of a number.
|
|
||||
/// </summary>
|
|
||||
public uint Numerator { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the denominator of a number.
|
|
||||
/// </summary>
|
|
||||
public uint Denominator { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Determines whether the specified <see cref="Rational"/> instances are considered equal.
|
|
||||
/// </summary>
|
|
||||
/// <param name="left">The first <see cref="Rational"/> to compare.</param>
|
|
||||
/// <param name="right"> The second <see cref="Rational"/> to compare.</param>
|
|
||||
/// <returns>The <see cref="bool"/></returns>
|
|
||||
public static bool operator ==(Rational left, Rational right) |
|
||||
{ |
|
||||
return Rational.Equals(left, right); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Determines whether the specified <see cref="Rational"/> instances are not considered equal.
|
|
||||
/// </summary>
|
|
||||
/// <param name="left">The first <see cref="Rational"/> to compare.</param>
|
|
||||
/// <param name="right"> The second <see cref="Rational"/> to compare.</param>
|
|
||||
/// <returns>The <see cref="bool"/></returns>
|
|
||||
public static bool operator !=(Rational left, Rational right) |
|
||||
{ |
|
||||
return !Rational.Equals(left, right); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts the specified <see cref="double"/> to an instance of this type.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to convert to an instance of this type.</param>
|
|
||||
/// <returns>
|
|
||||
/// The <see cref="Rational"/>.
|
|
||||
/// </returns>
|
|
||||
public static Rational FromDouble(double value) |
|
||||
{ |
|
||||
return new Rational(value, false); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts the specified <see cref="double"/> to an instance of this type.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to convert to an instance of this type.</param>
|
|
||||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|
||||
/// <returns>
|
|
||||
/// The <see cref="Rational"/>.
|
|
||||
/// </returns>
|
|
||||
public static Rational FromDouble(double value, bool bestPrecision) |
|
||||
{ |
|
||||
return new Rational(value, bestPrecision); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Equals(object obj) |
|
||||
{ |
|
||||
if (obj is Rational) |
|
||||
{ |
|
||||
return this.Equals((Rational)obj); |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public bool Equals(Rational other) |
|
||||
{ |
|
||||
LongRational left = new LongRational(this.Numerator, this.Denominator); |
|
||||
LongRational right = new LongRational(other.Numerator, other.Denominator); |
|
||||
|
|
||||
return left.Equals(right); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override int GetHashCode() |
|
||||
{ |
|
||||
LongRational self = new LongRational(this.Numerator, this.Denominator); |
|
||||
return self.GetHashCode(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts a rational number to the nearest <see cref="double"/>.
|
|
||||
/// </summary>
|
|
||||
/// <returns>
|
|
||||
/// The <see cref="double"/>.
|
|
||||
/// </returns>
|
|
||||
public double ToDouble() |
|
||||
{ |
|
||||
return this.Numerator / (double)this.Denominator; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override string ToString() |
|
||||
{ |
|
||||
return this.ToString(CultureInfo.InvariantCulture); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts the numeric value of this instance to its equivalent string representation using
|
|
||||
/// the specified culture-specific format information.
|
|
||||
/// </summary>
|
|
||||
/// <param name="provider">
|
|
||||
/// An object that supplies culture-specific formatting information.
|
|
||||
/// </param>
|
|
||||
/// <returns>The <see cref="string"/></returns>
|
|
||||
public string ToString(IFormatProvider provider) |
|
||||
{ |
|
||||
LongRational rational = new LongRational(this.Numerator, this.Denominator); |
|
||||
return rational.ToString(provider); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,189 +0,0 @@ |
|||||
// <copyright file="SignedRational.cs" company="Six Labors">
|
|
||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace SixLabors.Primitives |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Globalization; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents a number that can be expressed as a fraction.
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// This is a very simplified implementation of a rational number designed for use with metadata only.
|
|
||||
/// </remarks>
|
|
||||
public struct SignedRational : IEquatable<SignedRational> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="int"/> to create the rational from.</param>
|
|
||||
public SignedRational(int value) |
|
||||
: this(value, 1) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="numerator">The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.</param>
|
|
||||
/// <param name="denominator">The number below the line in a vulgar fraction; a divisor.</param>
|
|
||||
public SignedRational(int numerator, int denominator) |
|
||||
: this(numerator, denominator, true) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="numerator">The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.</param>
|
|
||||
/// <param name="denominator">The number below the line in a vulgar fraction; a divisor.</param>
|
|
||||
/// <param name="simplify">Specified if the rational should be simplified.</param>
|
|
||||
public SignedRational(int numerator, int denominator, bool simplify) |
|
||||
{ |
|
||||
LongRational rational = new LongRational(numerator, denominator, simplify); |
|
||||
|
|
||||
this.Numerator = (int)rational.Numerator; |
|
||||
this.Denominator = (int)rational.Denominator; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|
||||
public SignedRational(double value) |
|
||||
: this(value, false) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|
||||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|
||||
public SignedRational(double value, bool bestPrecision) |
|
||||
{ |
|
||||
LongRational rational = new LongRational(value, bestPrecision); |
|
||||
|
|
||||
this.Numerator = (int)rational.Numerator; |
|
||||
this.Denominator = (int)rational.Denominator; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the numerator of a number.
|
|
||||
/// </summary>
|
|
||||
public int Numerator { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the denominator of a number.
|
|
||||
/// </summary>
|
|
||||
public int Denominator { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Determines whether the specified <see cref="SignedRational"/> instances are considered equal.
|
|
||||
/// </summary>
|
|
||||
/// <param name="left">The first <see cref="SignedRational"/> to compare.</param>
|
|
||||
/// <param name="right"> The second <see cref="SignedRational"/> to compare.</param>
|
|
||||
/// <returns>The <see cref="bool"/></returns>
|
|
||||
public static bool operator ==(SignedRational left, SignedRational right) |
|
||||
{ |
|
||||
return SignedRational.Equals(left, right); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Determines whether the specified <see cref="SignedRational"/> instances are not considered equal.
|
|
||||
/// </summary>
|
|
||||
/// <param name="left">The first <see cref="SignedRational"/> to compare.</param>
|
|
||||
/// <param name="right"> The second <see cref="SignedRational"/> to compare.</param>
|
|
||||
/// <returns>The <see cref="bool"/></returns>
|
|
||||
public static bool operator !=(SignedRational left, SignedRational right) |
|
||||
{ |
|
||||
return !SignedRational.Equals(left, right); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts the specified <see cref="double"/> to an instance of this type.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to convert to an instance of this type.</param>
|
|
||||
/// <returns>
|
|
||||
/// The <see cref="SignedRational"/>.
|
|
||||
/// </returns>
|
|
||||
public static SignedRational FromDouble(double value) |
|
||||
{ |
|
||||
return new SignedRational(value, false); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts the specified <see cref="double"/> to an instance of this type.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The <see cref="double"/> to convert to an instance of this type.</param>
|
|
||||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|
||||
/// <returns>
|
|
||||
/// The <see cref="SignedRational"/>.
|
|
||||
/// </returns>
|
|
||||
public static SignedRational FromDouble(double value, bool bestPrecision) |
|
||||
{ |
|
||||
return new SignedRational(value, bestPrecision); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Equals(object obj) |
|
||||
{ |
|
||||
if (obj is SignedRational) |
|
||||
{ |
|
||||
return this.Equals((SignedRational)obj); |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public bool Equals(SignedRational other) |
|
||||
{ |
|
||||
LongRational left = new LongRational(this.Numerator, this.Denominator); |
|
||||
LongRational right = new LongRational(other.Numerator, other.Denominator); |
|
||||
|
|
||||
return left.Equals(right); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override int GetHashCode() |
|
||||
{ |
|
||||
LongRational self = new LongRational(this.Numerator, this.Denominator); |
|
||||
return self.GetHashCode(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts a rational number to the nearest <see cref="double"/>.
|
|
||||
/// </summary>
|
|
||||
/// <returns>
|
|
||||
/// The <see cref="double"/>.
|
|
||||
/// </returns>
|
|
||||
public double ToDouble() |
|
||||
{ |
|
||||
return this.Numerator / (double)this.Denominator; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override string ToString() |
|
||||
{ |
|
||||
return this.ToString(CultureInfo.InvariantCulture); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Converts the numeric value of this instance to its equivalent string representation using
|
|
||||
/// the specified culture-specific format information.
|
|
||||
/// </summary>
|
|
||||
/// <param name="provider">
|
|
||||
/// An object that supplies culture-specific formatting information.
|
|
||||
/// </param>
|
|
||||
/// <returns>The <see cref="string"/></returns>
|
|
||||
public string ToString(IFormatProvider provider) |
|
||||
{ |
|
||||
LongRational rational = new LongRational(this.Numerator, this.Denominator); |
|
||||
return rational.ToString(provider); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,115 +0,0 @@ |
|||||
// <copyright file="RationalTests.cs" company="Six Labors">
|
|
||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace SixLabors.Primitives.Tests |
|
||||
{ |
|
||||
using Xunit; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Tests the <see cref="Rational"/> struct.
|
|
||||
/// </summary>
|
|
||||
public class RationalTests |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Tests the equality operators for equality.
|
|
||||
/// </summary>
|
|
||||
[Fact] |
|
||||
public void AreEqual() |
|
||||
{ |
|
||||
Rational r1 = new Rational(3, 2); |
|
||||
Rational r2 = new Rational(3, 2); |
|
||||
|
|
||||
Assert.Equal(r1, r2); |
|
||||
Assert.True(r1 == r2); |
|
||||
|
|
||||
Rational r3 = new Rational(7.55); |
|
||||
Rational r4 = new Rational(755, 100); |
|
||||
Rational r5 = new Rational(151, 20); |
|
||||
|
|
||||
Assert.Equal(r3, r4); |
|
||||
Assert.Equal(r4, r5); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Tests the equality operators for inequality.
|
|
||||
/// </summary>
|
|
||||
[Fact] |
|
||||
public void AreNotEqual() |
|
||||
{ |
|
||||
Rational first = new Rational(0, 100); |
|
||||
Rational second = new Rational(100, 100); |
|
||||
|
|
||||
Assert.NotEqual(first, second); |
|
||||
Assert.True(first != second); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Tests whether the Rational constructor correctly assign properties.
|
|
||||
/// </summary>
|
|
||||
[Fact] |
|
||||
public void ConstructorAssignsProperties() |
|
||||
{ |
|
||||
Rational rational = new Rational(7, 55); |
|
||||
Assert.Equal(7U, rational.Numerator); |
|
||||
Assert.Equal(55U, rational.Denominator); |
|
||||
|
|
||||
rational = new Rational(755, 100); |
|
||||
Assert.Equal(151U, rational.Numerator); |
|
||||
Assert.Equal(20U, rational.Denominator); |
|
||||
|
|
||||
rational = new Rational(755, 100, false); |
|
||||
Assert.Equal(755U, rational.Numerator); |
|
||||
Assert.Equal(100U, rational.Denominator); |
|
||||
|
|
||||
rational = new Rational(-7.55); |
|
||||
Assert.Equal(151U, rational.Numerator); |
|
||||
Assert.Equal(20U, rational.Denominator); |
|
||||
|
|
||||
rational = new Rational(7); |
|
||||
Assert.Equal(7U, rational.Numerator); |
|
||||
Assert.Equal(1U, rational.Denominator); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Fraction() |
|
||||
{ |
|
||||
Rational first = new Rational(1.0 / 1600); |
|
||||
Rational second = new Rational(1.0 / 1600, true); |
|
||||
Assert.False(first.Equals(second)); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void ToDouble() |
|
||||
{ |
|
||||
Rational rational = new Rational(0, 0); |
|
||||
Assert.Equal(double.NaN, rational.ToDouble()); |
|
||||
|
|
||||
rational = new Rational(2, 0); |
|
||||
Assert.Equal(double.PositiveInfinity, rational.ToDouble()); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void ToStringRepresention() |
|
||||
{ |
|
||||
Rational rational = new Rational(0, 0); |
|
||||
Assert.Equal("[ Indeterminate ]", rational.ToString()); |
|
||||
|
|
||||
rational = new Rational(double.PositiveInfinity); |
|
||||
Assert.Equal("[ PositiveInfinity ]", rational.ToString()); |
|
||||
|
|
||||
rational = new Rational(double.NegativeInfinity); |
|
||||
Assert.Equal("[ PositiveInfinity ]", rational.ToString()); |
|
||||
|
|
||||
rational = new Rational(0, 1); |
|
||||
Assert.Equal("0", rational.ToString()); |
|
||||
|
|
||||
rational = new Rational(2, 1); |
|
||||
Assert.Equal("2", rational.ToString()); |
|
||||
|
|
||||
rational = new Rational(1, 2); |
|
||||
Assert.Equal("1/2", rational.ToString()); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,122 +0,0 @@ |
|||||
// <copyright file="RationalTests.cs" company="Six Labors">
|
|
||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace SixLabors.Primitives.Tests |
|
||||
{ |
|
||||
using Xunit; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Tests the <see cref="SignedRational"/> struct.
|
|
||||
/// </summary>
|
|
||||
public class SignedRationalTests |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Tests the equality operators for equality.
|
|
||||
/// </summary>
|
|
||||
[Fact] |
|
||||
public void AreEqual() |
|
||||
{ |
|
||||
SignedRational r1 = new SignedRational(3, 2); |
|
||||
SignedRational r2 = new SignedRational(3, 2); |
|
||||
|
|
||||
Assert.Equal(r1, r2); |
|
||||
Assert.True(r1 == r2); |
|
||||
|
|
||||
SignedRational r3 = new SignedRational(7.55); |
|
||||
SignedRational r4 = new SignedRational(755, 100); |
|
||||
SignedRational r5 = new SignedRational(151, 20); |
|
||||
|
|
||||
Assert.Equal(r3, r4); |
|
||||
Assert.Equal(r4, r5); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Tests the equality operators for inequality.
|
|
||||
/// </summary>
|
|
||||
[Fact] |
|
||||
public void AreNotEqual() |
|
||||
{ |
|
||||
SignedRational first = new SignedRational(0, 100); |
|
||||
SignedRational second = new SignedRational(100, 100); |
|
||||
|
|
||||
Assert.NotEqual(first, second); |
|
||||
Assert.True(first != second); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Tests whether the Rational constructor correctly assign properties.
|
|
||||
/// </summary>
|
|
||||
[Fact] |
|
||||
public void ConstructorAssignsProperties() |
|
||||
{ |
|
||||
SignedRational rational = new SignedRational(7, -55); |
|
||||
Assert.Equal(7, rational.Numerator); |
|
||||
Assert.Equal(-55, rational.Denominator); |
|
||||
|
|
||||
rational = new SignedRational(-755, 100); |
|
||||
Assert.Equal(-151, rational.Numerator); |
|
||||
Assert.Equal(20, rational.Denominator); |
|
||||
|
|
||||
rational = new SignedRational(-755, -100, false); |
|
||||
Assert.Equal(-755, rational.Numerator); |
|
||||
Assert.Equal(-100, rational.Denominator); |
|
||||
|
|
||||
rational = new SignedRational(-151, -20); |
|
||||
Assert.Equal(-151, rational.Numerator); |
|
||||
Assert.Equal(-20, rational.Denominator); |
|
||||
|
|
||||
rational = new SignedRational(-7.55); |
|
||||
Assert.Equal(-151, rational.Numerator); |
|
||||
Assert.Equal(20, rational.Denominator); |
|
||||
|
|
||||
rational = new SignedRational(7); |
|
||||
Assert.Equal(7, rational.Numerator); |
|
||||
Assert.Equal(1, rational.Denominator); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Fraction() |
|
||||
{ |
|
||||
SignedRational first = new SignedRational(1.0 / 1600); |
|
||||
SignedRational second = new SignedRational(1.0 / 1600, true); |
|
||||
Assert.False(first.Equals(second)); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void ToDouble() |
|
||||
{ |
|
||||
SignedRational rational = new SignedRational(0, 0); |
|
||||
Assert.Equal(double.NaN, rational.ToDouble()); |
|
||||
|
|
||||
rational = new SignedRational(2, 0); |
|
||||
Assert.Equal(double.PositiveInfinity, rational.ToDouble()); |
|
||||
|
|
||||
rational = new SignedRational(-2, 0); |
|
||||
Assert.Equal(double.NegativeInfinity, rational.ToDouble()); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void ToStringRepresention() |
|
||||
{ |
|
||||
SignedRational rational = new SignedRational(0, 0); |
|
||||
Assert.Equal("[ Indeterminate ]", rational.ToString()); |
|
||||
|
|
||||
rational = new SignedRational(double.PositiveInfinity); |
|
||||
Assert.Equal("[ PositiveInfinity ]", rational.ToString()); |
|
||||
|
|
||||
rational = new SignedRational(double.NegativeInfinity); |
|
||||
Assert.Equal("[ NegativeInfinity ]", rational.ToString()); |
|
||||
|
|
||||
rational = new SignedRational(0, 1); |
|
||||
Assert.Equal("0", rational.ToString()); |
|
||||
|
|
||||
rational = new SignedRational(2, 1); |
|
||||
Assert.Equal("2", rational.ToString()); |
|
||||
|
|
||||
rational = new SignedRational(1, 2); |
|
||||
Assert.Equal("1/2", rational.ToString()); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue