Merged new equivalence function.
This commit is contained in:
parent
fb71ebcffe
commit
87de6dda4d
3 changed files with 95 additions and 2 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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))
|
Loading…
Reference in a new issue