Merged new equivalence function.

This commit is contained in:
Jarl Gullberg 2017-06-07 14:27:36 +02:00
parent fb71ebcffe
commit 87de6dda4d
No known key found for this signature in database
GPG key ID: 750FF6F6BDA72D23
3 changed files with 95 additions and 2 deletions

View file

@ -422,6 +422,50 @@ namespace OpenTK
return relativeError < epsilon;
}
/// <summary>
/// Approximates equivalence between two single-precision floating-point numbers on a direct human scale.
/// It is important to note that this does not approximate equality - instead, it merely checks whether or not
/// two numbers could be considered equivalent to each other within a certain tolerance.
/// </summary>
/// <param name="a">The first value to compare.</param>
/// <param name="b">The second value to compare·</param>
/// <param name="tolerance">The tolerance within which the two values would be considered equivalent.</param>
/// <returns>Whether or not the values can be considered equivalent within the tolerance.</returns>
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
public static bool ApproximatelyEquivalent(float a, float b, float tolerance)
{
if (a == b)
{
// Early bailout, handles infinities
return true;
}
float diff = Math.Abs(a - b);
return diff < tolerance;
}
/// <summary>
/// Approximates equivalence between two double-precision floating-point numbers on a direct human scale.
/// It is important to note that this does not approximate equality - instead, it merely checks whether or not
/// two numbers could be considered equivalent to each other within a certain tolerance.
/// </summary>
/// <param name="a">The first value to compare.</param>
/// <param name="b">The second value to compare·</param>
/// <param name="tolerance">The tolerance within which the two values would be considered equivalent.</param>
/// <returns>Whether or not the values can be considered equivalent within the tolerance.</returns>
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
public static bool ApproximatelyEquivalent(double a, double b, double tolerance)
{
if (a == b)
{
// Early bailout, handles infinities
return true;
}
double diff = Math.Abs(a - b);
return diff < tolerance;
}
#endregion
#endregion

View file

@ -11,8 +11,13 @@ module private AssertHelpers =
[<Literal>]
let private BitAccuracy = 16
[<Literal>]
let private EquivalenceTolerance = 0.0001f
let approxEq a b = MathHelper.ApproximatelyEquivalent(a, b, EquivalenceTolerance)
//let approxEq a b = MathHelper.ApproximatelyEqual(a,b,BitAccuracy)
let approxEq a b = MathHelper.ApproximatelyEqualEpsilon(a,b,0.0001f)
//let approxEq a b = MathHelper.ApproximatelyEqualEpsilon(a,b,0.0001f)
let approxEqSingleEpsilon a b = MathHelper.ApproximatelyEqualEpsilon(a, b, 0.00001f)
let approxEqDoubleEpsilon a b = MathHelper.ApproximatelyEqualEpsilon(a, b, 0.00001)

View file

@ -305,4 +305,48 @@ module MathHelper =
Assert.NotApproximatelyEqualEpsilon(0.000000001, -System.Double.Epsilon);
Assert.NotApproximatelyEqualEpsilon(0.000000001, System.Double.Epsilon);
Assert.NotApproximatelyEqualEpsilon(System.Double.Epsilon, 0.000000001);
Assert.NotApproximatelyEqualEpsilon(-System.Double.Epsilon, 0.000000001);
Assert.NotApproximatelyEqualEpsilon(-System.Double.Epsilon, 0.000000001);
[<Properties(Arbitrary = [| typeof<OpenTKGen> |], MaxTest = 10000)>]
module ``ApproximatelyEquivalent (tolerance diff)`` =
[<Fact>]
let ``ApproximatelyEquivalent correctly approximates equivalence where the difference falls below the tolerance``() =
let a = 0.0001f
let b = 0.00019f
Assert.NotEqual(a,b)
Assert.True(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
[<Fact>]
let ``ApproximatelyEquivalent correctly approximates inequivalence where the difference is the tolerance``() =
let a = 0.0001f
let b = 0.0002f
Assert.NotEqual(a,b)
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
[<Fact>]
let ``ApproximatelyEquivalent correctly approximates inequivalence where the difference exceeds the tolerance``() =
let a = 0.0001f
let b = 0.00021f
Assert.NotEqual(a,b)
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
[<Fact>]
let ``ApproximatelyEquivalent reports very different values as non-equal even with a high tolerance``() =
let a = 2.0f
let b = 1.0f
Assert.NotEqual(a,b)
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 1.0f))
[<Fact>]
let ``ApproximatelyEquivalent works with single zero value``() =
let a = 1.0f
let b = 0.0f
Assert.NotEqual(a,b)
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
[<Fact>]
let ``ApproximatelyEquivalent works with both zero values``() =
let a = 0.0f
let b = 0.0f
Assert.Equal(a,b)
Assert.True(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))