From: Jarl Gullberg Date: Sun, 4 Jun 2017 17:05:43 +0000 (+0200) Subject: Added new and improved floating-point equality tester. X-Git-Tag: v3.0.0~107^2^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6d0f3eb973d06e43dd131650e28f3ba4954ec04e;p=platform%2Fcore%2Fcsapi%2Fopentk.git Added new and improved floating-point equality tester. --- diff --git a/tests/OpenTK.Tests/Assertions.fs b/tests/OpenTK.Tests/Assertions.fs index b6fdfc8..72673de 100644 --- a/tests/OpenTK.Tests/Assertions.fs +++ b/tests/OpenTK.Tests/Assertions.fs @@ -9,9 +9,19 @@ open OpenTK [] module private AssertHelpers = [] - let private BitAccuracy = 13 + let private BitAccuracy = 16 - let approxEq a b = MathHelper.ApproximatelyEqual(a,b,BitAccuracy) + //let approxEq a b = MathHelper.ApproximatelyEqual(a,b,BitAccuracy) + 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) + + let approxEqSingleEpsilonWithError (a, b, c : float32) = MathHelper.ApproximatelyEqualEpsilon(a, b, c) + let approxEqDoubleEpsilonWithError (a, b, c : float) = MathHelper.ApproximatelyEqualEpsilon(a, b, c) + + let anyZero2 (a : Vector2) = (approxEq a.X 0.0f || approxEq a.Y 0.0f) + let anyZero3 (a : Vector3) = (approxEq a.X 0.0f || approxEq a.Y 0.0f || approxEq a.Z 0.0f) + let anyZero4 (a : Vector4) = (approxEq a.X 0.0f || approxEq a.Y 0.0f || approxEq a.Z 0.0f || approxEq a.W 0.0f) /// We use a full type here instead of a module, as the overloading semantics are more suitable for our desired goal. [] @@ -31,4 +41,31 @@ type internal Assert = if not <| approxEq a b then raise <| new Xunit.Sdk.EqualException(a,b) + static member ApproximatelyEqualEpsilon(a : float32, b : float32) = + if not <| approxEqSingleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b) + + static member ApproximatelyEqualEpsilon(a : float32, b : float32, c : float32) = + if not <| approxEqSingleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b) + + + static member ApproximatelyEqualEpsilon(a : float, b : float) = + if not <| approxEqDoubleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b) + + static member ApproximatelyEqualEpsilon(a : float, b : float, c : float) = + if not <| approxEqDoubleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b) + + + static member NotApproximatelyEqualEpsilon(a : float32, b : float32) = + if approxEqSingleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b) + + static member NotApproximatelyEqualEpsilon(a : float32, b : float32, c : float32) = + if approxEqSingleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b) + + + static member NotApproximatelyEqualEpsilon(a : float, b : float) = + if approxEqDoubleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b) + + static member NotApproximatelyEqualEpsilon(a : float, b : float, c : float) = + if approxEqDoubleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b) + static member ThrowsIndexExn(f:unit -> unit) = Assert.Throws(f) |> ignore diff --git a/tests/OpenTK.Tests/MathHelperTests.fs b/tests/OpenTK.Tests/MathHelperTests.fs index e127017..554341a 100644 --- a/tests/OpenTK.Tests/MathHelperTests.fs +++ b/tests/OpenTK.Tests/MathHelperTests.fs @@ -6,50 +6,303 @@ open FsCheck.Xunit open System open OpenTK -[ |])>] module MathHelper = - /// This test ensures that approximately equal can never get it 'wrong' about the values. - [] - let ``ApproximatelyEqual is never incorrect`` (a : float32,b : float32,bits : int32) = - let clamped = max 0 (min bits 24) - let areApproxEqual = MathHelper.ApproximatelyEqual(a,b,clamped) - let areExactlyEqual = a = b - let isWrong = areExactlyEqual && not areApproxEqual - Assert.False(isWrong) - - [] - let ``ApproximatelyEqual can return true if some values are not exactly equal`` (a : float32,b : float32,bits : int32) = - let clamped = max 0 (min bits 24) - let areApproxEqual = MathHelper.ApproximatelyEqual(a,b,clamped) - let areExactlyEqual = a = b - let isWrong = areExactlyEqual && not areApproxEqual - let p = new PropertyAttribute() - Assert.False(isWrong) - - [] - let ``ApproximatelyEqual correctly approximates equality``() = - let a = 0.000000001f - let b = 0.0000000010000001f - Assert.NotEqual(a,b) - [ 1..24 ] |> List.iter (fun i -> Assert.True(MathHelper.ApproximatelyEqual(a,b,i))) - - [] - let ``ApproximatelyEqual reports very different values as non-equal even with high bit count``() = - let a = 2.0f - let b = 1.0f - Assert.NotEqual(a,b) - Assert.False(MathHelper.ApproximatelyEqual(a,b,10)) - - [] - let ``ApproximatelyEqual works with single zero value``() = - let a = 1.0f - let b = 0.0f - Assert.NotEqual(a,b) - Assert.False(MathHelper.ApproximatelyEqual(a,b,0)) - - [] - let ``ApproximatelyEqual works with both zero values``() = - let a = 0.0f - let b = 0.0f - Assert.Equal(a,b) - Assert.True(MathHelper.ApproximatelyEqual(a,b,0)) + [ |], MaxTest = 10000)>] + module ``ApproximatelyEqual (delta)`` = + /// This test ensures that approximately equal can never get it 'wrong' about the values. + [] + let ``ApproximatelyEqual is never incorrect`` (a : float32,b : float32,bits : int32) = + let clamped = max 0 (min bits 24) + let areApproxEqual = MathHelper.ApproximatelyEqual(a,b,clamped) + let areExactlyEqual = a = b + let isWrong = areExactlyEqual && not areApproxEqual + Assert.False(isWrong) + + [] + let ``ApproximatelyEqual can return true if some values are not exactly equal`` (a : float32,b : float32,bits : int32) = + let clamped = max 0 (min bits 24) + let areApproxEqual = MathHelper.ApproximatelyEqual(a,b,clamped) + let areExactlyEqual = a = b + let isWrong = areExactlyEqual && not areApproxEqual + let p = new PropertyAttribute() + Assert.False(isWrong) + + [] + let ``ApproximatelyEqual correctly approximates equality``() = + let a = 0.000000001f + let b = 0.0000000010000001f + Assert.NotEqual(a,b) + [ 1..24 ] |> List.iter (fun i -> Assert.True(MathHelper.ApproximatelyEqual(a,b,i))) + + [] + let ``ApproximatelyEqual reports very different values as non-equal even with high bit count``() = + let a = 2.0f + let b = 1.0f + Assert.NotEqual(a,b) + Assert.False(MathHelper.ApproximatelyEqual(a,b,10)) + + [] + let ``ApproximatelyEqual works with single zero value``() = + let a = 1.0f + let b = 0.0f + Assert.NotEqual(a,b) + Assert.False(MathHelper.ApproximatelyEqual(a,b,0)) + + [] + let ``ApproximatelyEqual works with both zero values``() = + let a = 0.0f + let b = 0.0f + Assert.Equal(a,b) + Assert.True(MathHelper.ApproximatelyEqual(a,b,0)) + + [ |], MaxTest = 10000)>] + module ``ApproximatelyEqual (single-precision epsilon)`` = + // + [] + let ``ApproximatelyEqual (single precision) is correct for large positive values``() = + Assert.ApproximatelyEqualEpsilon(1000000.0f, 1000001.0f); + Assert.ApproximatelyEqualEpsilon(1000001.0f, 1000000.0f); + Assert.NotApproximatelyEqualEpsilon(10000.0f, 10001.0f); + Assert.NotApproximatelyEqualEpsilon(10001.0f, 10000.0f); + + [] + let ``ApproximatelyEqual (single precision) is correct for large negative values``() = + Assert.ApproximatelyEqualEpsilon(-1000000.0f, -1000001.0f); + Assert.ApproximatelyEqualEpsilon(-1000001.0f, -1000000.0f); + Assert.NotApproximatelyEqualEpsilon(-10000.0f, -10001.0f); + Assert.NotApproximatelyEqualEpsilon(-10001.0f, -10000.0f); + + [] + let ``ApproximatelyEqual (single precision) is correct for positive values around 1``() = + Assert.ApproximatelyEqualEpsilon(1.0000001f, 1.0000002f); + Assert.ApproximatelyEqualEpsilon(1.0000002f, 1.0000001f); + Assert.NotApproximatelyEqualEpsilon(1.0002f, 1.0001f); + Assert.NotApproximatelyEqualEpsilon(1.0001f, 1.0002f); + + [] + let ``ApproximatelyEqual (single precision) is correct for negative values around -1``() = + Assert.ApproximatelyEqualEpsilon(-1.000001f, -1.000002f); + Assert.ApproximatelyEqualEpsilon(-1.000002f, -1.000001f); + Assert.NotApproximatelyEqualEpsilon(-1.0001f, -1.0002f); + Assert.NotApproximatelyEqualEpsilon(-1.0002f, -1.0001f); + + [] + let ``ApproximatelyEqual (single precision) is correct for values between 1 and 0``() = + Assert.ApproximatelyEqualEpsilon(0.000000001000001f, 0.000000001000002f); + Assert.ApproximatelyEqualEpsilon(0.000000001000002f, 0.000000001000001f); + Assert.NotApproximatelyEqualEpsilon(0.000000000001002f, 0.000000000001001f); + Assert.NotApproximatelyEqualEpsilon(0.000000000001001f, 0.000000000001002f); + + [] + let ``ApproximatelyEqual (single precision) is correct for values between -1 and 0``() = + Assert.ApproximatelyEqualEpsilon(-0.000000001000001f, -0.000000001000002f); + Assert.ApproximatelyEqualEpsilon(-0.000000001000002f, -0.000000001000001f); + Assert.NotApproximatelyEqualEpsilon(-0.000000000001002f, -0.000000000001001f); + Assert.NotApproximatelyEqualEpsilon(-0.000000000001001f, -0.000000000001002f); + + [] + let ``ApproximatelyEqual (single precision) is correct for comparisons involving 0``() = + Assert.ApproximatelyEqualEpsilon(0.0f, 0.0f); + Assert.ApproximatelyEqualEpsilon(0.0f, -0.0f); + Assert.ApproximatelyEqualEpsilon(-0.0f, -0.0f); + Assert.NotApproximatelyEqualEpsilon(0.00000001f, 0.0f); + Assert.NotApproximatelyEqualEpsilon(0.0f, 0.00000001f); + Assert.NotApproximatelyEqualEpsilon(-0.00000001f, 0.0f); + Assert.NotApproximatelyEqualEpsilon(0.0f, -0.00000001f); + + Assert.ApproximatelyEqualEpsilon(0.0f, 1e-40f, 0.01f); + Assert.ApproximatelyEqualEpsilon(1e-40f, 0.0f, 0.01f); + Assert.NotApproximatelyEqualEpsilon(1e-40f, 0.0f, 0.000001f); + Assert.NotApproximatelyEqualEpsilon(0.0f, 1e-40f, 0.000001f); + + Assert.ApproximatelyEqualEpsilon(0.0f, -1e-40f, 0.1f); + Assert.ApproximatelyEqualEpsilon(-1e-40f, 0.0f, 0.1f); + Assert.NotApproximatelyEqualEpsilon(-1e-40f, 0.0f, 0.00000001f); + Assert.NotApproximatelyEqualEpsilon(0.0f, -1e-40f, 0.00000001f); + + [] + let ``ApproximatelyEqual (single precision) is correct for extreme values with overflow potential``() = + Assert.ApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.MaxValue); + Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, -System.Single.MaxValue); + Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.MaxValue); + Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.MaxValue / 2.0f); + Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, -System.Single.MaxValue / 2.0f); + Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.MaxValue / 2.0f); + + [] + let ``ApproximatelyEqual (single precision) is correct for values involving infinities``() = + Assert.ApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.PositiveInfinity); + Assert.ApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.NegativeInfinity); + Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.PositiveInfinity); + Assert.NotApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.MaxValue); + Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, -System.Single.MaxValue); + + [] + let ``ApproximatelyEqual (single precision) is correct for values involving NaN``() = + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, 0.0f); + Assert.NotApproximatelyEqualEpsilon(-0.0f, System.Single.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -0.0f); + Assert.NotApproximatelyEqualEpsilon(0.0f, System.Single.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.PositiveInfinity); + Assert.NotApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.NegativeInfinity); + Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.MaxValue); + Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -System.Single.MaxValue); + Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.Epsilon); + Assert.NotApproximatelyEqualEpsilon(System.Single.Epsilon, System.Single.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -System.Single.Epsilon); + Assert.NotApproximatelyEqualEpsilon(-System.Single.Epsilon, System.Single.NaN); + + [] + let ``ApproximatelyEqual (single precision) is correct for values on opposite sides of 0``() = + Assert.NotApproximatelyEqualEpsilon(1.000000001f, -1.0f); + Assert.NotApproximatelyEqualEpsilon(-1.0f, 1.000000001f); + Assert.NotApproximatelyEqualEpsilon(-1.000000001f, 1.0f); + Assert.NotApproximatelyEqualEpsilon(1.0f, -1.000000001f); + Assert.ApproximatelyEqualEpsilon(10.0f * System.Single.Epsilon, 10.0f * -System.Single.Epsilon); + Assert.NotApproximatelyEqualEpsilon(10000.0f * System.Single.Epsilon, 10000.0f * -System.Single.Epsilon); + + [] + let ``ApproximatelyEqual (single precision) is correct for values very close to 0``() = + Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, System.Single.Epsilon); + Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, -System.Single.Epsilon); + Assert.ApproximatelyEqualEpsilon(-System.Single.Epsilon, System.Single.Epsilon); + Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, 0.0f); + Assert.ApproximatelyEqualEpsilon(0.0f, System.Single.Epsilon); + Assert.ApproximatelyEqualEpsilon(-System.Single.Epsilon, 0.0f); + Assert.ApproximatelyEqualEpsilon(0.0f, -System.Single.Epsilon); + + Assert.NotApproximatelyEqualEpsilon(0.000000001f, -System.Single.Epsilon); + Assert.NotApproximatelyEqualEpsilon(0.000000001f, System.Single.Epsilon); + Assert.NotApproximatelyEqualEpsilon(System.Single.Epsilon, 0.000000001f); + Assert.NotApproximatelyEqualEpsilon(-System.Single.Epsilon, 0.000000001f); + + [ |], MaxTest = 10000)>] + module ``ApproximatelyEqual (double-precision epsilon)`` = + // + [] + let ``ApproximatelyEqual (double precision) is correct for large positive values``() = + Assert.ApproximatelyEqualEpsilon(1000000.0, 1000001.0); + Assert.ApproximatelyEqualEpsilon(1000001.0, 1000000.0); + Assert.NotApproximatelyEqualEpsilon(10000.0, 10001.0); + Assert.NotApproximatelyEqualEpsilon(10001.0, 10000.0); + + [] + let ``ApproximatelyEqual (double precision) is correct for large negative values``() = + Assert.ApproximatelyEqualEpsilon(-1000000.0, -1000001.0); + Assert.ApproximatelyEqualEpsilon(-1000001.0, -1000000.0); + Assert.NotApproximatelyEqualEpsilon(-10000.0, -10001.0); + Assert.NotApproximatelyEqualEpsilon(-10001.0, -10000.0); + + [] + let ``ApproximatelyEqual (double precision) is correct for positive values around 1``() = + Assert.ApproximatelyEqualEpsilon(1.0000001, 1.0000002); + Assert.ApproximatelyEqualEpsilon(1.0000002, 1.0000001); + Assert.NotApproximatelyEqualEpsilon(1.0002, 1.0001); + Assert.NotApproximatelyEqualEpsilon(1.0001, 1.0002); + + [] + let ``ApproximatelyEqual (double precision) is correct for negative values around -1``() = + Assert.ApproximatelyEqualEpsilon(-1.000001, -1.000002); + Assert.ApproximatelyEqualEpsilon(-1.000002, -1.000001); + Assert.NotApproximatelyEqualEpsilon(-1.0001, -1.0002); + Assert.NotApproximatelyEqualEpsilon(-1.0002, -1.0001); + + [] + let ``ApproximatelyEqual (double precision) is correct for values between 1 and 0``() = + Assert.ApproximatelyEqualEpsilon(0.000000001000001, 0.000000001000002); + Assert.ApproximatelyEqualEpsilon(0.000000001000002, 0.000000001000001); + Assert.NotApproximatelyEqualEpsilon(0.000000000001002, 0.000000000001001); + Assert.NotApproximatelyEqualEpsilon(0.000000000001001, 0.000000000001002); + + [] + let ``ApproximatelyEqual (double precision) is correct for values between -1 and 0``() = + Assert.ApproximatelyEqualEpsilon(-0.000000001000001, -0.000000001000002); + Assert.ApproximatelyEqualEpsilon(-0.000000001000002, -0.000000001000001); + Assert.NotApproximatelyEqualEpsilon(-0.000000000001002, -0.000000000001001); + Assert.NotApproximatelyEqualEpsilon(-0.000000000001001, -0.000000000001002); + + [] + let ``ApproximatelyEqual (double precision) is correct for comparisons involving 0``() = + Assert.ApproximatelyEqualEpsilon(0.0, 0.0); + Assert.ApproximatelyEqualEpsilon(0.0, -0.0); + Assert.ApproximatelyEqualEpsilon(-0.0, -0.0); + Assert.NotApproximatelyEqualEpsilon(0.00000001, 0.0); + Assert.NotApproximatelyEqualEpsilon(0.0, 0.00000001); + Assert.NotApproximatelyEqualEpsilon(-0.00000001, 0.0); + Assert.NotApproximatelyEqualEpsilon(0.0, -0.00000001); + + Assert.ApproximatelyEqualEpsilon(0.0, 1e-310, 0.01); + Assert.ApproximatelyEqualEpsilon(1e-310, 0.0, 0.01); + Assert.NotApproximatelyEqualEpsilon(1e-310, 0.0, 0.000001); + Assert.NotApproximatelyEqualEpsilon(0.0, 1e-310, 0.000001); + + Assert.ApproximatelyEqualEpsilon(0.0, -1e-310, 0.1); + Assert.ApproximatelyEqualEpsilon(-1e-310, 0.0, 0.1); + Assert.NotApproximatelyEqualEpsilon(-1e-310, 0.0, 0.00000001); + Assert.NotApproximatelyEqualEpsilon(0.0, -1e-310, 0.00000001); + + [] + let ``ApproximatelyEqual (double precision) is correct for extreme values with overflow potential``() = + Assert.ApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.MaxValue); + Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, -System.Double.MaxValue); + Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.MaxValue); + Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.MaxValue / 2.0); + Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, -System.Double.MaxValue / 2.0); + Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.MaxValue / 2.0); + + [] + let ``ApproximatelyEqual (double precision) is correct for values involving infinities``() = + Assert.ApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.PositiveInfinity); + Assert.ApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.NegativeInfinity); + Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.PositiveInfinity); + Assert.NotApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.MaxValue); + Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, -System.Double.MaxValue); + + [] + let ``ApproximatelyEqual (double precision) is correct for values involving NaN``() = + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, 0.0); + Assert.NotApproximatelyEqualEpsilon(-0.0, System.Double.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -0.0); + Assert.NotApproximatelyEqualEpsilon(0.0, System.Double.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.PositiveInfinity); + Assert.NotApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.NegativeInfinity); + Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.MaxValue); + Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -System.Double.MaxValue); + Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.Epsilon); + Assert.NotApproximatelyEqualEpsilon(System.Double.Epsilon, System.Double.NaN); + Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -System.Double.Epsilon); + Assert.NotApproximatelyEqualEpsilon(-System.Double.Epsilon, System.Double.NaN); + + [] + let ``ApproximatelyEqual (double precision) is correct for values on opposite sides of 0``() = + Assert.NotApproximatelyEqualEpsilon(1.000000001, -1.0); + Assert.NotApproximatelyEqualEpsilon(-1.0, 1.000000001); + Assert.NotApproximatelyEqualEpsilon(-1.000000001, 1.0); + Assert.NotApproximatelyEqualEpsilon(1.0, -1.000000001); + Assert.ApproximatelyEqualEpsilon(10.0 * System.Double.Epsilon, 10.0 * -System.Double.Epsilon); + Assert.NotApproximatelyEqualEpsilon(100000000000.0 * System.Double.Epsilon, 100000000000.0 * -System.Double.Epsilon); + + [] + let ``ApproximatelyEqual (double precision) is correct for values very close to 0``() = + Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, System.Double.Epsilon); + Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, -System.Double.Epsilon); + Assert.ApproximatelyEqualEpsilon(-System.Double.Epsilon, System.Double.Epsilon); + Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, 0.0); + Assert.ApproximatelyEqualEpsilon(0.0, System.Double.Epsilon); + Assert.ApproximatelyEqualEpsilon(-System.Double.Epsilon, 0.0); + Assert.ApproximatelyEqualEpsilon(0.0, -System.Double.Epsilon); + + 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 diff --git a/tests/OpenTK.Tests/Matrix4Tests.fs b/tests/OpenTK.Tests/Matrix4Tests.fs index 706a839..43dc471 100644 --- a/tests/OpenTK.Tests/Matrix4Tests.fs +++ b/tests/OpenTK.Tests/Matrix4Tests.fs @@ -7,7 +7,7 @@ open System open OpenTK module Matrix4 = - [ |])>] + [ |], MaxTest = 10000)>] module Constructors = // [] @@ -88,7 +88,7 @@ module Matrix4 = Assert.Equal(o, A.M43) Assert.Equal(p, A.M44) - [ |])>] + [ |], MaxTest = 10000)>] module Equality = // [] @@ -103,7 +103,7 @@ module Matrix4 = let ``A matrix is not equal to an object which is not a matrix`` (a : Matrix4, b : Vector3) = Assert.False(a.Equals(b)) - [ |])>] + [ |], MaxTest = 10000)>] module Multiplication = // [] @@ -202,7 +202,7 @@ module Matrix4 = Assert.Equal(R4, AScaled.Row3) - [ |])>] + [ |], MaxTest = 10000)>] module Addition = // [] @@ -232,7 +232,7 @@ module Matrix4 = Assert.Equal(o + o, sum.M43) Assert.Equal(p + p, sum.M44) - [ |])>] + [ |], MaxTest = 10000)>] module Subtraction = // [] @@ -262,7 +262,7 @@ module Matrix4 = Assert.Equal(o - o, sub.M43) Assert.Equal(p - p, sub.M44) - [ |])>] + [ |], MaxTest = 10000)>] module Indexing = // [] @@ -338,7 +338,7 @@ module Matrix4 = let ``Indexed set operator throws exception for negative indices`` (b : Matrix4, x : float32) = let mutable a = b - + (fun() -> a.[-1, 2] <- x) |> Assert.ThrowsIndexExn (fun() -> a.[1, -2] <- x) |> Assert.ThrowsIndexExn @@ -363,7 +363,7 @@ module Matrix4 = (fun() -> a.[1, 6] |> ignore) |> Assert.ThrowsIndexExn (fun() -> a.[7, 12] |> ignore) |> Assert.ThrowsIndexExn - [ |])>] + [ |], MaxTest = 10000)>] module ``Row and column properties`` = // [] diff --git a/tests/OpenTK.Tests/Vector2Tests.fs b/tests/OpenTK.Tests/Vector2Tests.fs index a77d279..ae59506 100644 --- a/tests/OpenTK.Tests/Vector2Tests.fs +++ b/tests/OpenTK.Tests/Vector2Tests.fs @@ -8,7 +8,7 @@ open System.Runtime.InteropServices open OpenTK module Vector2 = - [ |])>] + [ |], MaxTest = 10000)>] module Constructors = // [] @@ -23,7 +23,7 @@ module Vector2 = Assert.Equal(x,v.X) Assert.Equal(y,v.Y) - [ |])>] + [ |], MaxTest = 10000)>] module Clamping = // [] @@ -46,7 +46,7 @@ module Vector2 = Assert.Equal(expX, res.X) Assert.Equal(expY, res.Y) - [ |])>] + [ |], MaxTest = 10000)>] module Length = // [] @@ -75,7 +75,7 @@ module Vector2 = Assert.Equal(lsq, v.LengthSquared) - [ |])>] + [ |], MaxTest = 10000)>] module ``Unit vectors and perpendicularity`` = // [] @@ -92,7 +92,7 @@ module Vector2 = Assert.Equal(perp, v.PerpendicularLeft) - [ |])>] + [ |], MaxTest = 10000)>] module Indexing = // [] @@ -126,7 +126,7 @@ module Vector2 = (fun() -> v.[2] |> ignore) |> Assert.ThrowsIndexExn - [ |])>] + [ |], MaxTest = 10000)>] module ``Simple Properties`` = // [] @@ -139,7 +139,7 @@ module Vector2 = // Assert.True(a.Length >= 0.0f) - [ |])>] + [ |], MaxTest = 10000)>] module Addition = // [] @@ -176,7 +176,7 @@ module Vector2 = Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Multiplication = // [] @@ -227,7 +227,7 @@ module Vector2 = Assert.Equal(a.X * f,r.X) Assert.Equal(a.Y * f,r.Y) - [ |])>] + [ |], MaxTest = 10000)>] module Subtraction = // [] @@ -252,49 +252,50 @@ module Vector2 = Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Division = // [] let ``Vector2-float division is the same as component-float division`` (a : Vector2, f : float32) = - let r = a / f + if not (approxEq f 0.0f) then + let r = a / f - Assert.ApproximatelyEqual(a.X / f,r.X) - Assert.ApproximatelyEqual(a.Y / f,r.Y) + Assert.ApproximatelyEqual(a.X / f,r.X) + Assert.ApproximatelyEqual(a.Y / f,r.Y) [] let ``Static Vector2-Vector2 division method is the same as component division`` (a : Vector2, b : Vector2) = + if not (anyZero2 a || anyZero2 b) then + let v1 = Vector2(a.X / b.X, a.Y / b.Y) + let sum = Vector2.Divide(a, b) - let v1 = Vector2(a.X / b.X, a.Y / b.Y) - let sum = Vector2.Divide(a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector2-Vector2 divison method by reference `` (a : Vector2, b : Vector2) = + if not (anyZero2 a || anyZero2 b) then + let v1 = Vector2(a.X / b.X, a.Y / b.Y) + let sum = Vector2.Divide(ref a, ref b) - let v1 = Vector2(a.X / b.X, a.Y / b.Y) - let sum = Vector2.Divide(ref a, ref b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector2-scalar division method is the same as component division`` (a : Vector2, b : float32) = + if not (approxEq b 0.0f) then + let v1 = Vector2(a.X / b, a.Y / b) + let sum = Vector2.Divide(a, b) - let v1 = Vector2(a.X / b, a.Y / b) - let sum = Vector2.Divide(a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector2-scalar divison method by reference is the same as component division`` (a : Vector2, b : float32) = + if not (approxEq b 0.0f) then + let v1 = Vector2(a.X / b, a.Y / b) + let sum = Vector2.Divide(ref a, b) - let v1 = Vector2(a.X / b, a.Y / b) - let sum = Vector2.Divide(ref a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Negation = // [] @@ -304,7 +305,7 @@ module Vector2 = Assert.Equal(-x, vNeg.X) Assert.Equal(-y, vNeg.Y) - [ |])>] + [ |], MaxTest = 10000)>] module Equality = // [] @@ -335,7 +336,7 @@ module Vector2 = Assert.True(equality) Assert.False(inequalityByOtherType) - [ |])>] + [ |], MaxTest = 10000)>] module Swizzling = // [] @@ -346,7 +347,7 @@ module Vector2 = let v1yx = v1.Yx; Assert.Equal(v2, v1yx); - [ |])>] + [ |], MaxTest = 10000)>] module Interpolation = // [] @@ -373,7 +374,7 @@ module Vector2 = let vRes = Vector2.BaryCentric(ref a, ref b, ref c, u, v) Assert.Equal(r, vRes) - [ |])>] + [ |], MaxTest = 10000)>] module ``Vector products`` = // [] @@ -394,7 +395,7 @@ module Vector2 = let vRes = Vector2.PerpDot(ref a, ref b) Assert.Equal(perpDot, vRes) - [ |])>] + [ |], MaxTest = 10000)>] module Normalization = // [] @@ -434,16 +435,20 @@ module Vector2 = [] let ``Normalization by reference is the same as division by magnitude`` (a : Vector2) = - let norm = a / a.Length - let vRes = Vector2.Normalize(ref a) + // Zero-length vectors can't be normalized + if not (approxEq a.Length 0.0f) then + let norm = a / a.Length + let vRes = Vector2.Normalize(ref a) - Assert.ApproximatelyEqual(norm, vRes) + Assert.ApproximatelyEqual(norm, vRes) [] let ``Normalization is the same as division by magnitude`` (a : Vector2) = - let norm = a / a.Length + // Zero-length vectors can't be normalized + if not (approxEq a.Length 0.0f) then + let norm = a / a.Length - Assert.ApproximatelyEqual(norm, Vector2.Normalize(a)); + Assert.ApproximatelyEqual(norm, Vector2.Normalize(a)); [] let ``Fast approximate normalization by reference is the same as multiplication by the fast inverse square`` (a : Vector2) = @@ -462,66 +467,74 @@ module Vector2 = Assert.ApproximatelyEqual(norm, Vector2.NormalizeFast(a)); - [ |])>] + [ |], MaxTest = 10000)>] module ``Magnitude min and max`` = // [] let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector2, v2: Vector2) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector2.MagnitudeMin(v1, v2) + let vMin = Vector2.MagnitudeMin(v1, v2) - if vMin = v1 then - let v1ShorterThanv2 = l1 < l2 - Assert.True(v1ShorterThanv2) - else - let v2ShorterThanOrEqualTov1 = l2 <= l1 - Assert.True(v2ShorterThanOrEqualTov1) + if vMin = v1 then + let v1ShorterThanv2 = l1 < l2 + Assert.True(v1ShorterThanv2) + else + let v2ShorterThanOrEqualTov1 = l2 <= l1 + Assert.True(v2ShorterThanOrEqualTov1) [] let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector2, v2: Vector2) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector2.MagnitudeMax(v1, v2) + let vMin = Vector2.MagnitudeMax(v1, v2) - if vMin = v1 then - let v1LongerThanOrEqualTov2 = l1 >= l2 - Assert.True(v1LongerThanOrEqualTov2) - else - let v2LongerThanv1 = l2 > l1 - Assert.True(v2LongerThanv1) + if vMin = v1 then + let v1LongerThanOrEqualTov2 = l1 >= l2 + Assert.True(v1LongerThanOrEqualTov2) + else + let v2LongerThanv1 = l2 > l1 + Assert.True(v2LongerThanv1) [] let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector2, v2: Vector2) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector2.MagnitudeMin(ref v1, ref v2) + let vMin = Vector2.MagnitudeMin(ref v1, ref v2) - if vMin = v1 then - let v1ShorterThanv2 = l1 < l2 - Assert.True(v1ShorterThanv2) - else - let v2ShorterThanOrEqualTov1 = l2 <= l1 - Assert.True(v2ShorterThanOrEqualTov1) + if vMin = v1 then + let v1ShorterThanv2 = l1 < l2 + Assert.True(v1ShorterThanv2) + else + let v2ShorterThanOrEqualTov1 = l2 <= l1 + Assert.True(v2ShorterThanOrEqualTov1) [] let ``MagnitudeMax by reference selects the vector with equal greater magnitude given two vectors`` (v1 : Vector2, v2: Vector2) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector2.MagnitudeMax(ref v1, ref v2) + let vMin = Vector2.MagnitudeMax(ref v1, ref v2) - if vMin = v1 then - let v1LongerThanOrEqualTov2 = l1 >= l2 - Assert.True(v1LongerThanOrEqualTov2) - else - let v2LongerThanv1 = l2 > l1 - Assert.True(v2LongerThanv1) + if vMin = v1 then + let v1LongerThanOrEqualTov2 = l1 >= l2 + Assert.True(v1LongerThanOrEqualTov2) + else + let v2LongerThanv1 = l2 > l1 + Assert.True(v2LongerThanv1) - [ |])>] + [ |], MaxTest = 10000)>] module ``Component min and max`` = // [] @@ -556,7 +569,7 @@ module Vector2 = Assert.True(isComponentLargest vMax.X v1.X v2.X) Assert.True(isComponentLargest vMax.Y v1.Y v2.Y) - [ |])>] + [ |], MaxTest = 10000)>] module Transformation = // [] @@ -579,7 +592,7 @@ module Vector2 = Assert.ApproximatelyEqual(transformedVector, Vector2.Transform(ref v, ref q)) - [ |])>] + [ |], MaxTest = 10000)>] module Serialization = // [] diff --git a/tests/OpenTK.Tests/Vector3Tests.fs b/tests/OpenTK.Tests/Vector3Tests.fs index 8987c9f..6428684 100644 --- a/tests/OpenTK.Tests/Vector3Tests.fs +++ b/tests/OpenTK.Tests/Vector3Tests.fs @@ -8,7 +8,7 @@ open System.Runtime.InteropServices open OpenTK module Vector3 = - [ |])>] + [ |], MaxTest = 10000)>] module Constructors = // [] @@ -65,7 +65,7 @@ module Vector3 = Assert.Equal(b, v2.Y) Assert.Equal(c, v2.Z) - [ |])>] + [ |], MaxTest = 10000)>] module Indexing = // [] @@ -100,7 +100,7 @@ module Vector3 = (fun() -> v.[4] |> ignore) |> Assert.ThrowsIndexExn - [ |])>] + [ |], MaxTest = 10000)>] module Length = // [] @@ -124,7 +124,7 @@ module Vector3 = Assert.Equal(lsq, v.LengthSquared) - [ |])>] + [ |], MaxTest = 10000)>] module Normalization = // [] @@ -167,16 +167,20 @@ module Vector3 = [] let ``Normalization by reference is the same as division by magnitude`` (a : Vector3) = - let norm = a / a.Length - let vRes = Vector3.Normalize(ref a) + // Zero-length vectors can't be normalized + if not (approxEq a.Length 0.0f) then + let norm = a / a.Length + let vRes = Vector3.Normalize(ref a) - Assert.ApproximatelyEqual(norm, vRes) + Assert.ApproximatelyEqual(norm, vRes) [] let ``Normalization is the same as division by magnitude`` (a : Vector3) = - let norm = a / a.Length + // Zero-length vectors can't be normalized + if not (approxEq a.Length 0.0f) then + let norm = a / a.Length - Assert.ApproximatelyEqual(norm, Vector3.Normalize(a)); + Assert.ApproximatelyEqual(norm, Vector3.Normalize(a)); [] let ``Fast approximate normalization by reference is the same as multiplication by the fast inverse square`` (a : Vector3) = @@ -195,7 +199,7 @@ module Vector3 = Assert.ApproximatelyEqual(norm, Vector3.NormalizeFast(a)); - [ |])>] + [ |], MaxTest = 10000)>] module Addition = // [] @@ -236,7 +240,7 @@ module Vector3 = Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Subtraction = // [] @@ -263,7 +267,7 @@ module Vector3 = Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Multiplication = // [] @@ -344,7 +348,7 @@ module Vector3 = Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Division = // [] @@ -358,37 +362,37 @@ module Vector3 = [] let ``Static Vector3-Vector3 division method is the same as component division`` (a : Vector3, b : Vector3) = + if not (anyZero3 a || anyZero3 b) then + let v1 = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z) + let sum = Vector3.Divide(a, b) - let v1 = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z) - let sum = Vector3.Divide(a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector3-Vector3 divison method by reference is the same as component division`` (a : Vector3, b : Vector3) = + if not (anyZero3 a || anyZero3 b) then + let v1 = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z) + let sum = Vector3.Divide(ref a, ref b) - let v1 = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z) - let sum = Vector3.Divide(ref a, ref b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector3-scalar division method is the same as component division`` (a : Vector3, b : float32) = + if not (approxEq b 0.0f) then // we don't support diving by zero. + let v1 = Vector3(a.X / b, a.Y / b, a.Z / b) + let sum = Vector3.Divide(a, b) - let v1 = Vector3(a.X / b, a.Y / b, a.Z / b) - let sum = Vector3.Divide(a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector3-scalar divison method by reference is the same as component division`` (a : Vector3, b : float32) = + if not (approxEq b 0.0f) then // we don't support diving by zero. + let v1 = Vector3(a.X / b, a.Y / b, a.Z / b) + let sum = Vector3.Divide(ref a, b) - let v1 = Vector3(a.X / b, a.Y / b, a.Z / b) - let sum = Vector3.Divide(ref a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Negation = // [] @@ -399,7 +403,7 @@ module Vector3 = Assert.Equal(-y, vNeg.Y) Assert.Equal(-z, vNeg.Z) - [ |])>] + [ |], MaxTest = 10000)>] module Equality = // [] @@ -430,7 +434,7 @@ module Vector3 = Assert.True(equality) Assert.False(inequalityByOtherType) - [ |])>] + [ |], MaxTest = 10000)>] module Swizzling = // [] @@ -475,7 +479,7 @@ module Vector3 = Assert.Equal(zx, v.Zx); Assert.Equal(zy, v.Zy); - [ |])>] + [ |], MaxTest = 10000)>] module Interpolation = // [] @@ -503,7 +507,7 @@ module Vector3 = let vRes = Vector3.BaryCentric(ref a, ref b, ref c, u, v) Assert.Equal(r, vRes) - [ |])>] + [ |], MaxTest = 10000)>] module ``Vector products`` = // [] @@ -527,66 +531,74 @@ module Vector3 = let vRes = Vector3.Cross(ref a, ref b) Assert.Equal(cross, vRes) - [ |])>] + [ |], MaxTest = 10000)>] module ``Magnitude min and max`` = // [] let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector3, v2: Vector3) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector3.MagnitudeMin(v1, v2) + let vMin = Vector3.MagnitudeMin(v1, v2) - if vMin = v1 then - let v1ShorterThanv2 = l1 < l2 - Assert.True(v1ShorterThanv2) - else - let v2ShorterThanOrEqualTov1 = l2 <= l1 - Assert.True(v2ShorterThanOrEqualTov1) + if vMin = v1 then + let v1ShorterThanv2 = l1 < l2 + Assert.True(v1ShorterThanv2) + else + let v2ShorterThanOrEqualTov1 = l2 <= l1 + Assert.True(v2ShorterThanOrEqualTov1) [] let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector3, v2: Vector3) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector3.MagnitudeMax(v1, v2) + let vMin = Vector3.MagnitudeMax(v1, v2) - if vMin = v1 then - let v1LongerThanOrEqualTov2 = l1 >= l2 - Assert.True(v1LongerThanOrEqualTov2) - else - let v2LongerThanv1 = l2 > l1 - Assert.True(v2LongerThanv1) + if vMin = v1 then + let v1LongerThanOrEqualTov2 = l1 >= l2 + Assert.True(v1LongerThanOrEqualTov2) + else + let v2LongerThanv1 = l2 > l1 + Assert.True(v2LongerThanv1) [] let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector3, v2: Vector3) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector3.MagnitudeMin(ref v1, ref v2) + let vMin = Vector3.MagnitudeMin(ref v1, ref v2) - if vMin = v1 then - let v1ShorterThanv2 = l1 < l2 - Assert.True(v1ShorterThanv2) - else - let v2ShorterThanOrEqualTov1 = l2 <= l1 - Assert.True(v2ShorterThanOrEqualTov1) + if vMin = v1 then + let v1ShorterThanv2 = l1 < l2 + Assert.True(v1ShorterThanv2) + else + let v2ShorterThanOrEqualTov1 = l2 <= l1 + Assert.True(v2ShorterThanOrEqualTov1) [] let ``MagnitudeMax by reference selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector3, v2: Vector3) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector3.MagnitudeMax(ref v1, ref v2) + let vMin = Vector3.MagnitudeMax(ref v1, ref v2) - if vMin = v1 then - let v1LongerThanOrEqualTov2 = l1 >= l2 - Assert.True(v1LongerThanOrEqualTov2) - else - let v2LongerThanv1 = l2 > l1 - Assert.True(v2LongerThanv1) + if vMin = v1 then + let v1LongerThanOrEqualTov2 = l1 >= l2 + Assert.True(v1LongerThanOrEqualTov2) + else + let v2LongerThanv1 = l2 > l1 + Assert.True(v2LongerThanv1) - [ |])>] + [ |], MaxTest = 10000)>] module ``Component min and max`` = // [] @@ -625,7 +637,7 @@ module Vector3 = Assert.True(isComponentLargest vMax.Y v1.Y v2.Y) Assert.True(isComponentLargest vMax.Z v1.Z v2.Z) - [ |])>] + [ |], MaxTest = 10000)>] module Clamping = // [] @@ -652,7 +664,7 @@ module Vector3 = Assert.Equal(expY, res.Y) Assert.Equal(expZ, res.Z) - [ |])>] + [ |], MaxTest = 10000)>] module ``Unit vectors``= // [] @@ -685,7 +697,7 @@ module Vector3 = Assert.Equal(Vector3.One, unitOne) - [ |])>] + [ |], MaxTest = 10000)>] module Serialization = // [] @@ -695,7 +707,7 @@ module Vector3 = Assert.Equal(expectedSize, Vector3.SizeInBytes) Assert.Equal(expectedSize, Marshal.SizeOf(Vector3())) - [ |])>] + [ |], MaxTest = 10000)>] module Transformation = // [] diff --git a/tests/OpenTK.Tests/Vector4Tests.fs b/tests/OpenTK.Tests/Vector4Tests.fs index addc160..df8a9b6 100644 --- a/tests/OpenTK.Tests/Vector4Tests.fs +++ b/tests/OpenTK.Tests/Vector4Tests.fs @@ -8,7 +8,7 @@ open System.Runtime.InteropServices open OpenTK module Vector4 = - [ |])>] + [ |], MaxTest = 10000)>] module Constructors = // [] @@ -85,7 +85,7 @@ module Vector4 = Assert.Equal(z, v2.Z) Assert.Equal(w, v2.W) - [ |])>] + [ |], MaxTest = 10000)>] module Indexing = // [] @@ -121,7 +121,7 @@ module Vector4 = (fun() -> v.[4] |> ignore) |> Assert.ThrowsIndexExn - [ |])>] + [ |], MaxTest = 10000)>] module Length = // [] @@ -145,7 +145,7 @@ module Vector4 = Assert.Equal(lsq, v.LengthSquared) - [ |])>] + [ |], MaxTest = 10000)>] module Normalization = // [] @@ -153,25 +153,29 @@ module Vector4 = let v = Vector4(x, y, z, w) let l = v.Length - let norm = v.Normalized() + // Zero-length vectors can't be normalized + if not (approxEq l 0.0f) then + let norm = v.Normalized() - Assert.ApproximatelyEqual(v.X / l, norm.X) - Assert.ApproximatelyEqual(v.Y / l, norm.Y) - Assert.ApproximatelyEqual(v.Z / l, norm.Z) - Assert.ApproximatelyEqual(v.W / l, norm.W) + Assert.ApproximatelyEqual(v.X / l, norm.X) + Assert.ApproximatelyEqual(v.Y / l, norm.Y) + Assert.ApproximatelyEqual(v.Z / l, norm.Z) + Assert.ApproximatelyEqual(v.W / l, norm.W) [] let ``Normalization of instance transforms the instance into a unit length vector with the correct components`` (x, y, z, w) = let v = Vector4(x, y, z, w) let l = v.Length - let norm = Vector4(x, y, z, w) - norm.Normalize() + // Zero-length vectors can't be normalized + if not (approxEq l 0.0f) then + let norm = Vector4(x, y, z, w) + norm.Normalize() - Assert.ApproximatelyEqual(v.X / l, norm.X) - Assert.ApproximatelyEqual(v.Y / l, norm.Y) - Assert.ApproximatelyEqual(v.Z / l, norm.Z) - Assert.ApproximatelyEqual(v.W / l, norm.W) + Assert.ApproximatelyEqual(v.X / l, norm.X) + Assert.ApproximatelyEqual(v.Y / l, norm.Y) + Assert.ApproximatelyEqual(v.Z / l, norm.Z) + Assert.ApproximatelyEqual(v.W / l, norm.W) [] let ``Fast approximate normalization of instance transforms the instance into a unit length vector with the correct components`` (x, y, z, w) = @@ -188,16 +192,20 @@ module Vector4 = [] let ``Normalization by reference is the same as division by magnitude`` (a : Vector4) = - let norm = a / a.Length - let vRes = Vector4.Normalize(ref a) + // Zero-length vectors can't be normalized + if not (approxEq a.Length 0.0f) then + let norm = a / a.Length + let vRes = Vector4.Normalize(ref a) - Assert.ApproximatelyEqual(norm, vRes) + Assert.ApproximatelyEqual(norm, vRes) [] let ``Normalization is the same as division by magnitude`` (a : Vector4) = - let norm = a / a.Length + // Zero-length vectors can't be normalized + if not (approxEq a.Length 0.0f) then + let norm = a / a.Length - Assert.ApproximatelyEqual(norm, Vector4.Normalize(a)); + Assert.ApproximatelyEqual(norm, Vector4.Normalize(a)); [] let ``Fast approximate normalization by reference is the same as multiplication by the fast inverse square`` (a : Vector4) = @@ -211,12 +219,11 @@ module Vector4 = [] let ``Fast approximate normalization is the same as multiplication by the fast inverse square`` (a : Vector4) = let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z + a.W * a.W) - let norm = a * scale Assert.ApproximatelyEqual(norm, Vector4.NormalizeFast(a)); - [ |])>] + [ |], MaxTest = 10000)>] module Addition = // [] @@ -258,7 +265,7 @@ module Vector4 = Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Subtraction = // [] @@ -286,7 +293,7 @@ module Vector4 = Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Multiplication = // [] @@ -374,7 +381,7 @@ module Vector4 = Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Division = // [] @@ -389,37 +396,37 @@ module Vector4 = [] let ``Static Vector4-Vector4 division method is the same as component division`` (a : Vector4, b : Vector4) = + if not (anyZero4 a || anyZero4 b) then + let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W) + let sum = Vector4.Divide(a, b) - let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W) - let sum = Vector4.Divide(a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector4-Vector4 divison method by reference is the same as component division`` (a : Vector4, b : Vector4) = + if not (anyZero4 a || anyZero4 b) then + let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W) + let sum = Vector4.Divide(ref a, ref b) - let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W) - let sum = Vector4.Divide(ref a, ref b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector4-scalar division method is the same as component division`` (a : Vector4, b : float32) = + if not (approxEq b 0.0f) then // we don't support diving by zero. + let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b) + let sum = Vector4.Divide(a, b) - let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b) - let sum = Vector4.Divide(a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) [] let ``Static Vector4-scalar divison method by reference is the same as component division`` (a : Vector4, b : float32) = + if not (approxEq b 0.0f) then // we don't support diving by zero. + let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b) + let sum = Vector4.Divide(ref a, b) - let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b) - let sum = Vector4.Divide(ref a, b) - - Assert.ApproximatelyEqual(v1, sum) + Assert.ApproximatelyEqual(v1, sum) - [ |])>] + [ |], MaxTest = 10000)>] module Negation = // [] @@ -431,7 +438,7 @@ module Vector4 = Assert.Equal(-z, vNeg.Z) Assert.Equal(-w, vNeg.W) - [ |])>] + [ |], MaxTest = 10000)>] module Equality = // [] @@ -471,7 +478,7 @@ module Vector4 = Assert.False(inequalityByOtherType) - [ |])>] + [ |], MaxTest = 10000)>] module Swizzling = // [] @@ -650,7 +657,7 @@ module Vector4 = Assert.Equal(wy, v.Wy) Assert.Equal(wz, v.Wz) - [ |])>] + [ |], MaxTest = 10000)>] module Interpolation = // [] @@ -679,7 +686,7 @@ module Vector4 = let vRes = Vector4.BaryCentric(ref a, ref b, ref c, u, v) Assert.Equal(r, vRes) - [ |])>] + [ |], MaxTest = 10000)>] module ``Vector products`` = // [] @@ -691,66 +698,74 @@ module Vector4 = let vRes = Vector4.Dot(ref a, ref b) Assert.Equal(dot, vRes) - [ |])>] + [ |], MaxTest = 10000)>] module ``Magnitude min and max`` = // [] let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector4, v2: Vector4) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector4.MagnitudeMin(v1, v2) + let vMin = Vector4.MagnitudeMin(v1, v2) - if vMin = v1 then - let v1ShorterThanv2 = l1 < l2 - Assert.True(v1ShorterThanv2) - else - let v2ShorterThanOrEqualTov1 = l2 <= l1 - Assert.True(v2ShorterThanOrEqualTov1) + if vMin = v1 then + let v1ShorterThanv2 = l1 < l2 + Assert.True(v1ShorterThanv2) + else + let v2ShorterThanOrEqualTov1 = l2 <= l1 + Assert.True(v2ShorterThanOrEqualTov1) [] let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector4, v2: Vector4) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector4.MagnitudeMax(v1, v2) + let vMin = Vector4.MagnitudeMax(v1, v2) - if vMin = v1 then - let v1LongerThanOrEqualTov2 = l1 >= l2 - Assert.True(v1LongerThanOrEqualTov2) - else - let v2LongerThanv1 = l2 > l1 - Assert.True(v2LongerThanv1) + if vMin = v1 then + let v1LongerThanOrEqualTov2 = l1 >= l2 + Assert.True(v1LongerThanOrEqualTov2) + else + let v2LongerThanv1 = l2 > l1 + Assert.True(v2LongerThanv1) [] let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector4, v2: Vector4) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector4.MagnitudeMin(ref v1, ref v2) + let vMin = Vector4.MagnitudeMin(ref v1, ref v2) - if vMin = v1 then - let v1ShorterThanv2 = l1 < l2 - Assert.True(v1ShorterThanv2) - else - let v2ShorterThanOrEqualTov1 = l2 <= l1 - Assert.True(v2ShorterThanOrEqualTov1) + if vMin = v1 then + let v1ShorterThanv2 = l1 < l2 + Assert.True(v1ShorterThanv2) + else + let v2ShorterThanOrEqualTov1 = l2 <= l1 + Assert.True(v2ShorterThanOrEqualTov1) [] let ``MagnitudeMax by reference selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector4, v2: Vector4) = - let l1 = v1.LengthSquared - let l2 = v2.LengthSquared + // Results do not matter for equal vectors + if not (v1 = v2) then + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared - let vMin = Vector4.MagnitudeMax(ref v1, ref v2) + let vMin = Vector4.MagnitudeMax(ref v1, ref v2) - if vMin = v1 then - let v1LongerThanOrEqualTov2 = l1 >= l2 - Assert.True(v1LongerThanOrEqualTov2) - else - let v2LongerThanv1 = l2 > l1 - Assert.True(v2LongerThanv1) + if vMin = v1 then + let v1LongerThanOrEqualTov2 = l1 >= l2 + Assert.True(v1LongerThanOrEqualTov2) + else + let v2LongerThanv1 = l2 > l1 + Assert.True(v2LongerThanv1) - [ |])>] + [ |], MaxTest = 10000)>] module ``Component min and max`` = // [] @@ -794,7 +809,7 @@ module Vector4 = Assert.True(isComponentLargest vMax.W v1.W v2.W) - [ |])>] + [ |], MaxTest = 10000)>] module Clamping = // [] @@ -825,7 +840,7 @@ module Vector4 = Assert.Equal(expZ, res.Z) Assert.Equal(expW, res.W) - [ |])>] + [ |], MaxTest = 10000)>] module ``Unit vectors``= // [] @@ -864,7 +879,7 @@ module Vector4 = Assert.Equal(Vector4.One, unitOne) - [ |])>] + [ |], MaxTest = 10000)>] module Serialization = // [] @@ -874,7 +889,7 @@ module Vector4 = Assert.Equal(expectedSize, Vector4.SizeInBytes) Assert.Equal(expectedSize, Marshal.SizeOf(Vector4())) - [ |])>] + [ |], MaxTest = 10000)>] module Transformation = // []