Merged new equivalence function.
authorJarl Gullberg <jarl.gullberg@gmail.com>
Wed, 7 Jun 2017 12:27:36 +0000 (14:27 +0200)
committerJarl Gullberg <jarl.gullberg@gmail.com>
Wed, 7 Jun 2017 12:27:36 +0000 (14:27 +0200)
src/OpenTK/Math/MathHelper.cs
tests/OpenTK.Tests/Assertions.fs
tests/OpenTK.Tests/MathHelperTests.fs

index c13cd89..0dc553f 100644 (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
index 72673de..b54ef7a 100644 (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)
 
index 554341a..fdd21f9 100644 (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);
\ No newline at end of file
+            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))
\ No newline at end of file