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