mirror of https://github.com/SixLabors/ImageSharp
6 changed files with 243 additions and 33 deletions
@ -0,0 +1,75 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System.Runtime.CompilerServices; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Implements math operations using tolerant comparison.
|
||||
|
/// </summary>
|
||||
|
internal struct TolerantMath |
||||
|
{ |
||||
|
private readonly double epsilon; |
||||
|
|
||||
|
private readonly double negEpsilon; |
||||
|
|
||||
|
public TolerantMath(double epsilon) |
||||
|
{ |
||||
|
DebugGuard.MustBeGreaterThan(epsilon, 0, nameof(epsilon)); |
||||
|
|
||||
|
this.epsilon = epsilon; |
||||
|
this.negEpsilon = -epsilon; |
||||
|
} |
||||
|
|
||||
|
public static TolerantMath Default { get; } = new TolerantMath(1e-8); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <paramref name="a"/> == 0
|
||||
|
/// </summary>
|
||||
|
[MethodImpl(InliningOptions.ShortMethod)] |
||||
|
public bool IsZero(double a) => a > this.negEpsilon && a < this.epsilon; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <paramref name="a"/> > 0
|
||||
|
/// </summary>
|
||||
|
[MethodImpl(InliningOptions.ShortMethod)] |
||||
|
public bool IsPositive(double a) => a > this.epsilon; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <paramref name="a"/> < 0
|
||||
|
/// </summary>
|
||||
|
[MethodImpl(InliningOptions.ShortMethod)] |
||||
|
public bool IsNegative(double a) => a < this.negEpsilon; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <paramref name="a"/> == <paramref name="b"/>
|
||||
|
/// </summary>
|
||||
|
[MethodImpl(InliningOptions.ShortMethod)] |
||||
|
public bool AreEqual(double a, double b) => this.IsZero(a - b); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <paramref name="a"/> > <paramref name="b"/>
|
||||
|
/// </summary>
|
||||
|
[MethodImpl(InliningOptions.ShortMethod)] |
||||
|
public bool IsGreater(double a, double b) => a > b + this.epsilon; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <paramref name="a"/> < <paramref name="b"/>
|
||||
|
/// </summary>
|
||||
|
[MethodImpl(InliningOptions.ShortMethod)] |
||||
|
public bool IsLess(double a, double b) => a < b - this.epsilon; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <paramref name="a"/> >= <paramref name="b"/>
|
||||
|
/// </summary>
|
||||
|
[MethodImpl(InliningOptions.ShortMethod)] |
||||
|
public bool IsGreaterOrEqual(double a, double b) => a >= b - this.epsilon; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <paramref name="a"/> <= <paramref name="b"/>
|
||||
|
/// </summary>
|
||||
|
[MethodImpl(InliningOptions.ShortMethod)] |
||||
|
public bool IsLessOrEqual(double a, double b) => b >= a - this.epsilon; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,130 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
using Xunit; |
||||
|
// ReSharper disable InconsistentNaming
|
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Helpers |
||||
|
{ |
||||
|
public class TolerantMathTests |
||||
|
{ |
||||
|
private readonly TolerantMath tolerantMath = new TolerantMath(0.1); |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(0)] |
||||
|
[InlineData(0.01)] |
||||
|
[InlineData(-0.05)] |
||||
|
public void IsZero_WhenTrue(double a) |
||||
|
{ |
||||
|
Assert.True(this.tolerantMath.IsZero(a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(0.11)] |
||||
|
[InlineData(-0.101)] |
||||
|
[InlineData(42)] |
||||
|
public void IsZero_WhenFalse(double a) |
||||
|
{ |
||||
|
Assert.False(this.tolerantMath.IsZero(a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(0.11)] |
||||
|
[InlineData(100)] |
||||
|
public void IsPositive_WhenTrue(double a) |
||||
|
{ |
||||
|
Assert.True(this.tolerantMath.IsPositive(a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(0.09)] |
||||
|
[InlineData(-0.1)] |
||||
|
[InlineData(-1000)] |
||||
|
public void IsPositive_WhenFalse(double a) |
||||
|
{ |
||||
|
Assert.False(this.tolerantMath.IsPositive(a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(-0.11)] |
||||
|
[InlineData(-100)] |
||||
|
public void IsNegative_WhenTrue(double a) |
||||
|
{ |
||||
|
Assert.True(this.tolerantMath.IsNegative(a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(-0.09)] |
||||
|
[InlineData(0.1)] |
||||
|
[InlineData(1000)] |
||||
|
public void IsNegative_WhenFalse(double a) |
||||
|
{ |
||||
|
Assert.False(this.tolerantMath.IsNegative(a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(4.2, 4.2)] |
||||
|
[InlineData(4.2, 4.25)] |
||||
|
[InlineData(-Math.PI, -Math.PI + 0.05)] |
||||
|
[InlineData(999999.2, 999999.25)] |
||||
|
public void AreEqual_WhenTrue(double a, double b) |
||||
|
{ |
||||
|
Assert.True(this.tolerantMath.AreEqual(a, b)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(1, 2)] |
||||
|
[InlineData(-1000000, -1000000.2)] |
||||
|
public void AreEqual_WhenFalse(double a, double b) |
||||
|
{ |
||||
|
Assert.False(this.tolerantMath.AreEqual(a, b)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(2, 1.8)] |
||||
|
[InlineData(-20, -20.2)] |
||||
|
[InlineData(0.1, -0.1)] |
||||
|
[InlineData(100, 10)] |
||||
|
public void IsGreater_IsLess_WhenTrue(double a, double b) |
||||
|
{ |
||||
|
Assert.True(this.tolerantMath.IsGreater(a, b)); |
||||
|
Assert.True(this.tolerantMath.IsLess(b, a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(2, 1.95)] |
||||
|
[InlineData(-20, -20.02)] |
||||
|
[InlineData(0.01, -0.01)] |
||||
|
[InlineData(999999, 999999.09)] |
||||
|
public void IsGreater_IsLess_WhenFalse(double a, double b) |
||||
|
{ |
||||
|
Assert.False(this.tolerantMath.IsGreater(a, b)); |
||||
|
Assert.False(this.tolerantMath.IsLess(b, a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(3, 2)] |
||||
|
[InlineData(3, 2.99)] |
||||
|
[InlineData(2.99, 3)] |
||||
|
[InlineData(-5, -6)] |
||||
|
[InlineData(-5, -5.05)] |
||||
|
[InlineData(-5.05, -5)] |
||||
|
public void IsGreaterOrEqual_IsLessOrEqual_WhenTrue(double a, double b) |
||||
|
{ |
||||
|
Assert.True(this.tolerantMath.IsGreaterOrEqual(a, b)); |
||||
|
Assert.True(this.tolerantMath.IsLessOrEqual(b, a)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(2, 3)] |
||||
|
[InlineData(2.89, 3)] |
||||
|
[InlineData(-3, -2.89)] |
||||
|
public void IsGreaterOrEqual_IsLessOrEqual_WhenFalse(double a, double b) |
||||
|
{ |
||||
|
Assert.False(this.tolerantMath.IsGreaterOrEqual(a, b)); |
||||
|
Assert.False(this.tolerantMath.IsLessOrEqual(b, a)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue