Merge pull request #2 from Nihlus/fscheck-testing-rebased

Unit coverage, test porting and more tests
This commit is contained in:
varon 2017-06-02 13:49:01 +02:00 committed by GitHub
commit cbfbbf4126
11 changed files with 2634 additions and 164 deletions

2
.gitignore vendored
View file

@ -174,6 +174,8 @@ temp/
# Test results produced by build
TestResults.xml
output.mlpd
coverage.xml
# Nuget outputs
nuget/*.nupkg

View file

@ -7,3 +7,8 @@ before_install:
script:
- ./build.sh NuGet
after_script:
- mono --debug --profile=log:coverage,covfilter=+OpenTK,covfilter=-OpenTK.Tests,covfilter=-FSharp.Core,covfilter=-FsCheck,covfilter=-xunit.assert "packages/xunit.runner.console/tools/xunit.console.exe" "tests/OpenTK.Tests/bin/Release/OpenTK.Tests.dll" -parallel none
- mprof-report --reports=coverage --coverage-out=coverage.xml output.mlpd
- bash <(curl -s https://codecov.io/bash)

View file

@ -7,25 +7,25 @@ open System
open OpenTK
[<AutoOpen>]
module private AssertHelpers =
module private AssertHelpers =
[<Literal>]
let private BitAccuracy = 5
let private BitAccuracy = 9
let approxEq a b = MathHelper.ApproximatelyEqual(a,b,BitAccuracy)
/// We use a full type here instead of a module, as the overloading semantics are more suitable for our desired goal.
[<Sealed>]
type internal Assert =
static member ApproximatelyEqual(a : Vector2,b : Vector2) =
type internal Assert =
static member ApproximatelyEqual(a : Vector2,b : Vector2) =
if not <| approxEq a.X b.X && approxEq a.Y b.Y then raise <| new Xunit.Sdk.EqualException(a,b)
static member ApproximatelyEqual(a : Vector3,b : Vector3) =
static member ApproximatelyEqual(a : Vector3,b : Vector3) =
if not <| approxEq a.X b.X && approxEq a.Y b.Y && approxEq a.Z b.Z then raise <| new Xunit.Sdk.EqualException(a,b)
static member ApproximatelyEqual(a : Vector4,b : Vector4) =
if not <| approxEq a.X b.X && approxEq a.Y b.Y && approxEq a.Z b.Z && approxEq a.W b.W then
static member ApproximatelyEqual(a : Vector4,b : Vector4) =
if not <| approxEq a.X b.X && approxEq a.Y b.Y && approxEq a.Z b.Z && approxEq a.W b.W then
raise <| new Xunit.Sdk.EqualException(a,b)
static member ApproximatelyEqual(a : float32,b : float32) =
static member ApproximatelyEqual(a : float32,b : float32) =
if not <| approxEq a b then raise <| new Xunit.Sdk.EqualException(a,b)

View file

@ -7,62 +7,63 @@ open System
open OpenTK
[<AutoOpen>]
module private Generators =
module private Generators =
let private isValidFloat f = not (Single.IsNaN f || Single.IsInfinity f || Single.IsInfinity (f * f) || f = Single.MinValue || f = Single.MaxValue )
let private isValidDouble d = not (Double.IsNaN d || Double.IsInfinity d || Double.IsInfinity (d * d)|| d = Double.MinValue || d = Double.MaxValue)
let singleArb = Arb.Default.Float32() |> Arb.toGen |> Gen.filter isValidFloat
let single = singleArb |> Arb.fromGen
let double =
let double =
Arb.Default.Float() |> Arb.toGen
|> Gen.filter isValidDouble
|> Arb.fromGen
let vec2 =
let vec2 =
singleArb
|> Gen.two
|> Gen.map Vector2
|> Arb.fromGen
let vec3 =
let vec3 =
singleArb
|> Gen.three
|> Gen.map Vector3
|> Arb.fromGen
let vec4 =
let vec4 =
singleArb
|> Gen.four
|> Gen.map Vector4
|> Arb.fromGen
let quat =
let quat =
singleArb
|> Gen.four
|> Gen.map Quaternion
|> Gen.three
|> Gen.map (fun (x,y,z) -> Quaternion(x,y,z,0.0f) |> Quaternion.Normalize)
|> Gen.filter (fun q -> not <| (Single.IsNaN q.Length || Single.IsInfinity q.Length ))
|> Arb.fromGen
let mat2 =
let mat2 =
singleArb
|> Gen.four
|> Gen.map Matrix2
|> Arb.fromGen
let mat3 =
let mat3 =
vec3
|> Arb.toGen
|> Gen.three
|> Gen.map Matrix3
|> Arb.fromGen
let mat4 =
let mat4 =
vec4
|> Arb.toGen
|> Gen.four
|> Gen.map Matrix4
|> Arb.fromGen
type OpenTKGen =
type OpenTKGen =
static member Single() = single
static member float32() = single
static member Double() = double

View file

@ -7,48 +7,48 @@ open System
open OpenTK
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module MathHelper =
module MathHelper =
/// This test ensures that approximately equal can never get it 'wrong' about the values.
[<Property>]
let ``ApproximatelyEqual is never incorrect`` (a : float32,b : float32,bits : int32) =
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)
[<Property>]
let ``ApproximatelyEqual can return true if some values are not exactly equal`` (a : float32,b : float32,bits : int32) =
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)
[<Fact>]
let ``ApproximatelyEqual correctly approximates equality``() =
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)))
[<Fact>]
let ``ApproximatelyEqual reports very different values as non-equal even with high bit count``() =
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))
[<Fact>]
let ``ApproximatelyEqual works with single zero value``() =
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))
[<Fact>]
let ``ApproximatelyEqual works with both zero values``() =
let ``ApproximatelyEqual works with both zero values``() =
let a = 0.0f
let b = 0.0f
Assert.Equal(a,b)

View file

@ -0,0 +1,392 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open OpenTK
module Matrix4 =
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Constructors =
//
[<Property>]
let ``Sixteen value constructor sets all components to the correct values`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
Assert.Equal(a, A.M11)
Assert.Equal(b, A.M12)
Assert.Equal(c, A.M13)
Assert.Equal(d, A.M14)
Assert.Equal(e, A.M21)
Assert.Equal(f, A.M22)
Assert.Equal(g, A.M23)
Assert.Equal(h, A.M24)
Assert.Equal(i, A.M31)
Assert.Equal(j, A.M32)
Assert.Equal(k, A.M33)
Assert.Equal(l, A.M34)
Assert.Equal(m, A.M41)
Assert.Equal(n, A.M42)
Assert.Equal(o, A.M43)
Assert.Equal(p, A.M44)
[<Property>]
let ``Matrix3 partial constructor sets all components to the correct values`` (a, b, c, d, e, f, g, h, i) =
let B = Matrix3(a, b, c, d, e, f, g, h, i)
let A = Matrix4(B)
Assert.Equal(a, A.M11)
Assert.Equal(b, A.M12)
Assert.Equal(c, A.M13)
Assert.Equal(0.0f, A.M14)
Assert.Equal(d, A.M21)
Assert.Equal(e, A.M22)
Assert.Equal(f, A.M23)
Assert.Equal(0.0f, A.M24)
Assert.Equal(g, A.M31)
Assert.Equal(h, A.M32)
Assert.Equal(i, A.M33)
Assert.Equal(0.0f, A.M34)
Assert.Equal(0.0f, A.M41)
Assert.Equal(0.0f, A.M42)
Assert.Equal(0.0f, A.M43)
Assert.Equal(1.0f, A.M44)
[<Property>]
let ``Four-vector4 constructor sets all components to the correct values`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let v1 = Vector4(a, b, c, d)
let v2 = Vector4(e, f, g, h)
let v3 = Vector4(i, j, k, l)
let v4 = Vector4(m, n, o, p)
let A = Matrix4(v1, v2, v3, v4)
Assert.Equal(a, A.M11)
Assert.Equal(b, A.M12)
Assert.Equal(c, A.M13)
Assert.Equal(d, A.M14)
Assert.Equal(e, A.M21)
Assert.Equal(f, A.M22)
Assert.Equal(g, A.M23)
Assert.Equal(h, A.M24)
Assert.Equal(i, A.M31)
Assert.Equal(j, A.M32)
Assert.Equal(k, A.M33)
Assert.Equal(l, A.M34)
Assert.Equal(m, A.M41)
Assert.Equal(n, A.M42)
Assert.Equal(o, A.M43)
Assert.Equal(p, A.M44)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Equality =
//
[<Property>]
let ``Two matrices with identical values are equal`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let B = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let equality = A = B
Assert.True(equality)
[<Property>]
let ``A matrix is not equal to an object which is not a matrix`` (a : Matrix4, b : Vector3) =
Assert.False(a.Equals(b))
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Multiplication =
//
[<Property>]
let ``Matrix multiplication is done by row/column multiplication and summation`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let B = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let R11 = a*a + b*e + c*i + d*m
let R12 = a*b + b*f + c*j + d*n
let R13 = a*c + b*g + c*k + d*o
let R14 = a*d + b*h + c*l + d*p
let R21 = e*a + f*e + g*i + h*m
let R22 = e*b + f*f + g*j + h*n
let R23 = e*c + f*g + g*k + h*o
let R24 = e*d + f*h + g*l + h*p
let R31 = i*a + j*e + k*i + l*m
let R32 = i*b + j*f + k*j + l*n
let R33 = i*c + j*g + k*k + l*o
let R34 = i*d + j*h + k*l + l*p
let R41 = m*a + n*e + o*i + p*m
let R42 = m*b + n*f + o*j + p*n
let R43 = m*c + n*g + o*k + p*o
let R44 = m*d + n*h + o*l + p*p
let AB = A*B
Assert.Equal(R11, AB.M11)
Assert.Equal(R12, AB.M12)
Assert.Equal(R13, AB.M13)
Assert.Equal(R14, AB.M14)
Assert.Equal(R21, AB.M21)
Assert.Equal(R22, AB.M22)
Assert.Equal(R23, AB.M23)
Assert.Equal(R24, AB.M24)
Assert.Equal(R31, AB.M31)
Assert.Equal(R32, AB.M32)
Assert.Equal(R33, AB.M33)
Assert.Equal(R34, AB.M34)
Assert.Equal(R41, AB.M41)
Assert.Equal(R42, AB.M42)
Assert.Equal(R43, AB.M43)
Assert.Equal(R44, AB.M44)
[<Property>]
let ``Matrix multiplication by scalar is the same as row multiplication by scalar`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, scalar : float32) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let R1 = Vector4(a, b, c, d) * scalar
let R2 = Vector4(e, f, g, h) * scalar
let R3 = Vector4(i, j, k, l) * scalar
let R4 = Vector4(m, n, o, p) * scalar
let AScaled = A * scalar
Assert.Equal(R1, AScaled.Row0)
Assert.Equal(R2, AScaled.Row1)
Assert.Equal(R3, AScaled.Row2)
Assert.Equal(R4, AScaled.Row3)
[<Property>]
let ``Static method matrix multiplication by scalar is the same as row multiplication by scalar`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, scalar : float32) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let R1 = Vector4(a, b, c, d) * scalar
let R2 = Vector4(e, f, g, h) * scalar
let R3 = Vector4(i, j, k, l) * scalar
let R4 = Vector4(m, n, o, p) * scalar
let AScaled = Matrix4.Mult(A, scalar)
Assert.Equal(R1, AScaled.Row0)
Assert.Equal(R2, AScaled.Row1)
Assert.Equal(R3, AScaled.Row2)
Assert.Equal(R4, AScaled.Row3)
[<Property>]
let ``Static method matrix multiplication by reference by scalar is the same as row multiplication by scalar`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, scalar : float32) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let R1 = Vector4(a, b, c, d) * scalar
let R2 = Vector4(e, f, g, h) * scalar
let R3 = Vector4(i, j, k, l) * scalar
let R4 = Vector4(m, n, o, p) * scalar
let AScaled = Matrix4.Mult(ref A, scalar)
Assert.Equal(R1, AScaled.Row0)
Assert.Equal(R2, AScaled.Row1)
Assert.Equal(R3, AScaled.Row2)
Assert.Equal(R4, AScaled.Row3)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Addition =
//
[<Property>]
let ``Matrix addition adds corresponding components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let B = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let sum = A + B
Assert.Equal(a + a, sum.M11)
Assert.Equal(b + b, sum.M12)
Assert.Equal(c + c, sum.M13)
Assert.Equal(d + d, sum.M14)
Assert.Equal(e + e, sum.M21)
Assert.Equal(f + f, sum.M22)
Assert.Equal(g + g, sum.M23)
Assert.Equal(h + h, sum.M24)
Assert.Equal(i + i, sum.M31)
Assert.Equal(j + j, sum.M32)
Assert.Equal(k + k, sum.M33)
Assert.Equal(l + l, sum.M34)
Assert.Equal(m + m, sum.M41)
Assert.Equal(n + n, sum.M42)
Assert.Equal(o + o, sum.M43)
Assert.Equal(p + p, sum.M44)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Subtraction =
//
[<Property>]
let ``Matrix subtraction subtracts corresponding components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let B = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let sub = A - B
Assert.Equal(a - a, sub.M11)
Assert.Equal(b - b, sub.M12)
Assert.Equal(c - c, sub.M13)
Assert.Equal(d - d, sub.M14)
Assert.Equal(e - e, sub.M21)
Assert.Equal(f - f, sub.M22)
Assert.Equal(g - g, sub.M23)
Assert.Equal(h - h, sub.M24)
Assert.Equal(i - i, sub.M31)
Assert.Equal(j - j, sub.M32)
Assert.Equal(k - k, sub.M33)
Assert.Equal(l - l, sub.M34)
Assert.Equal(m - m, sub.M41)
Assert.Equal(n - n, sub.M42)
Assert.Equal(o - o, sub.M43)
Assert.Equal(p - p, sub.M44)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Indexing =
//
[<Property>]
let ``Matrix set indexing sets correct components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let mutable A = Matrix4()
A.[0, 0] <- a
A.[0, 1] <- b
A.[0, 2] <- c
A.[0, 3] <- d
A.[1, 0] <- e
A.[1, 1] <- f
A.[1, 2] <- g
A.[1, 3] <- h
A.[2, 0] <- i
A.[2, 1] <- j
A.[2, 2] <- k
A.[2, 3] <- l
A.[3, 0] <- m
A.[3, 1] <- n
A.[3, 2] <- o
A.[3, 3] <- p
Assert.Equal(a, A.M11)
Assert.Equal(b, A.M12)
Assert.Equal(c, A.M13)
Assert.Equal(d, A.M14)
Assert.Equal(e, A.M21)
Assert.Equal(f, A.M22)
Assert.Equal(g, A.M23)
Assert.Equal(h, A.M24)
Assert.Equal(i, A.M31)
Assert.Equal(j, A.M32)
Assert.Equal(k, A.M33)
Assert.Equal(l, A.M34)
Assert.Equal(m, A.M41)
Assert.Equal(n, A.M42)
Assert.Equal(o, A.M43)
Assert.Equal(p, A.M44)
[<Property>]
let ``Matrix get indexing accesses the correct components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
Assert.Equal(a, A.[0, 0])
Assert.Equal(b, A.[0, 1])
Assert.Equal(c, A.[0, 2])
Assert.Equal(d, A.[0, 3])
Assert.Equal(e, A.[1, 0])
Assert.Equal(f, A.[1, 1])
Assert.Equal(g, A.[1, 2])
Assert.Equal(h, A.[1, 3])
Assert.Equal(i, A.[2, 0])
Assert.Equal(j, A.[2, 1])
Assert.Equal(k, A.[2, 2])
Assert.Equal(l, A.[2, 3])
Assert.Equal(m, A.[3, 0])
Assert.Equal(n, A.[3, 1])
Assert.Equal(o, A.[3, 2])
Assert.Equal(p, A.[3, 3])
[<Property>]
let ``Indexed set operator throws exception for negative indices`` (b : Matrix4, x : float32) =
let mutable a = b
(fun() -> a.[-1, 2] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
(fun() -> a.[1, -2] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
(fun() -> a.[-1, -2] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed get operator throws exception for negative indices`` (a : Matrix4) =
(fun() -> a.[-1, 2] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
(fun() -> a.[1, -2] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
(fun() -> a.[-1, -2] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed set operator throws exception for large indices`` (a : Matrix4, x : float32) =
let mutable b = a
(fun() -> b.[5, 2] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
(fun() -> b.[1, 6] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
(fun() -> b.[7, 12] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed get operator throws exception for large indices`` (a : Matrix4) =
(fun() -> a.[5, 2] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
(fun() -> a.[1, 6] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
(fun() -> a.[7, 12] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Row and column properties`` =
//
[<Property>]
let ``Matrix row properties return the correct components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
let R0 = A.Row0
let R1 = A.Row1
let R2 = A.Row2
let R3 = A.Row3
Assert.Equal(a, R0.X)
Assert.Equal(b, R0.Y)
Assert.Equal(c, R0.Z)
Assert.Equal(d, R0.W)
Assert.Equal(e, R1.X)
Assert.Equal(f, R1.Y)
Assert.Equal(g, R1.Z)
Assert.Equal(h, R1.W)
Assert.Equal(i, R2.X)
Assert.Equal(j, R2.Y)
Assert.Equal(k, R2.Z)
Assert.Equal(l, R2.W)
Assert.Equal(m, R3.X)
Assert.Equal(n, R3.Y)
Assert.Equal(o, R3.Z)
Assert.Equal(p, R3.W)

View file

@ -58,12 +58,15 @@
-->
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<None Include="paket.references" />
<Compile Include="Assertions.fs" />
<Compile Include="Generators.fs" />
<Compile Include="MathHelper.fs" />
<Compile Include="Vectors.fs" />
<Compile Include="MathHelperTests.fs" />
<Compile Include="Matrix4Tests.fs" />
<Compile Include="Vector2Tests.fs" />
<Compile Include="Vector3Tests.fs" />
<Compile Include="Vector4Tests.fs" />
<Content Include="App.config" />
<None Include="paket.references" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib" />

View file

@ -0,0 +1,596 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open System.Runtime.InteropServices
open OpenTK
module Vector2 =
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Constructors =
//
[<Property>]
let ``Single value constructor sets all components to the same value`` (f : float32) =
let v = Vector2(f)
Assert.Equal(f,v.X)
Assert.Equal(f,v.Y)
[<Property>]
let ``Two value constructor sets all components correctly`` (x,y) =
let v = Vector2(x,y)
Assert.Equal(x,v.X)
Assert.Equal(y,v.Y)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Clamping =
//
[<Property>]
let ``Clamping one vector between two other vectors clamps all components between corresponding components`` (a : Vector2, b : Vector2, w : Vector2) =
let res = Vector2.Clamp(w, a, b)
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
Assert.Equal(expX, res.X)
Assert.Equal(expY, res.Y)
[<Property>]
let ``Clamping one vector between two other vectors by reference clamps all components`` (a : Vector2, b : Vector2, w : Vector2) =
let res = Vector2.Clamp(ref w, ref a, ref b)
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
Assert.Equal(expX, res.X)
Assert.Equal(expY, res.Y)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Length =
//
[<Property>]
let ``Length is always >= 0`` (a : Vector2) =
//
Assert.True(a.Length >= 0.0f)
[<Property>]
let ``Length follows the pythagorean theorem`` (a, b) =
let v = Vector2(a, b)
let l = System.Math.Sqrt((float)(a * a + b * b))
Assert.Equal((float32)l, v.Length)
[<Property>]
let ``Fast length method works`` (a, b) =
let v = Vector2(a, b)
let l = 1.0f / MathHelper.InverseSqrtFast(a * a + b * b)
Assert.Equal(l, v.LengthFast)
[<Property>]
let ``Length squared method works`` (a, b) =
let v = Vector2(a, b)
let lsq = a * a + b * b
Assert.Equal(lsq, v.LengthSquared)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Unit vectors and perpendicularity`` =
//
[<Property>]
let ``Perpendicular vector to the right is correct`` (a, b) =
let v = Vector2(a, b)
let perp = Vector2(b, -a)
Assert.Equal(perp, v.PerpendicularRight)
[<Property>]
let ``Perpendicular vector to the left is correct`` (a, b) =
let v = Vector2(a, b)
let perp = Vector2(-b, a)
Assert.Equal(perp, v.PerpendicularLeft)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Indexing =
//
[<Property>]
let ``Index operator accesses the correct components`` (x, y) =
let v = Vector2(x, y)
Assert.Equal(x, v.[0])
Assert.Equal(y, v.[1])
[<Property>]
let ``Indexed set operator throws exception for negative indices`` (x, y) =
let mutable v = Vector2(x, y)
(fun() -> v.[-1] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed get operator throws exception for negative indices`` (x, y) =
let mutable v = Vector2(x, y)
(fun() -> v.[-1] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed set operator throws exception for large indices`` (x, y) =
let mutable v = Vector2(x, y)
(fun() -> v.[2] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed get operator throws exception for large indices`` (x, y) =
let mutable v = Vector2(x, y)
(fun() -> v.[2] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Simple Properties`` =
//
[<Property>]
let ``Vector equality is by component`` (a : Vector2,b : Vector2) =
//
Assert.Equal((a.X = b.X && a.Y = b.Y),(a = b))
[<Property>]
let ``Vector length is always >= 0`` (a : Vector2) =
//
Assert.True(a.Length >= 0.0f)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Addition =
//
[<Property>]
let ``Vector addition is the same as component addition`` (a : Vector2,b : Vector2) =
let c = a + b
Assert.ApproximatelyEqual(a.X + b.X,c.X)
Assert.ApproximatelyEqual(a.Y + b.Y,c.Y)
[<Property>]
let ``Vector addition is commutative`` (a : Vector2,b : Vector2) =
let c = a + b
let c2 = b + a
Assert.ApproximatelyEqual(c,c2)
[<Property>]
let ``Vector addition is associative`` (a : Vector2,b : Vector2,c : Vector2) =
let r1 = (a + b) + c
let r2 = a + (b + c)
Assert.ApproximatelyEqual(r1,r2)
[<Property>]
let ``Static Vector2 addition method is the same as component addition`` (a : Vector2, b : Vector2) =
let v1 = Vector2(a.X + b.X, a.Y + b.Y)
let sum = Vector2.Add(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector2 addition method by reference is the same as component addition`` (a : Vector2, b : Vector2) =
let v1 = Vector2(a.X + b.X, a.Y + b.Y)
let sum = Vector2.Add(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Multiplication =
//
[<Property>]
let ``Vector2 multiplication is the same as component multiplication`` (a : Vector2, b : Vector2) =
let c = a * b
Assert.Equal(a.X * b.X,c.X)
Assert.Equal(a.Y * b.Y,c.Y)
[<Property>]
let ``Vector2 multiplication is commutative`` (a : Vector2, b : Vector2) =
let r1 = a * b
let r2 = b * a
Assert.Equal(r1,r2)
[<Property>]
let ``Left-handed Vector2-scalar multiplication is the same as component-scalar multiplication`` (a : Vector2, f : float32) =
let r = a * f
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
[<Property>]
let ``Right-handed Vector2-scalar multiplication is the same as component-scalar multiplication`` (a : Vector2, f : float32) =
let r = f * a
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
[<Property>]
let ``Static Vector2 multiplication method is the same as component multiplication`` (a : Vector2, b : Vector2) =
let v1 = Vector2(a.X * b.X, a.Y * b.Y)
let sum = Vector2.Multiply(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector2 multiplication method by reference is the same as component multiplication`` (a : Vector2, b : Vector2) =
let v1 = Vector2(a.X * b.X, a.Y * b.Y)
let sum = Vector2.Multiply(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static method Vector2-scalar multiplication is the same as component-scalar multiplication`` (a : Vector2, f : float32) =
let r = Vector2.Multiply(a, f)
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Subtraction =
//
[<Property>]
let ``Vector2 subtraction is the same as component subtraction`` (a : Vector2, b : Vector2) =
let c = a - b
Assert.Equal(a.X - b.X,c.X)
Assert.Equal(a.Y - b.Y,c.Y)
[<Property>]
let ``Static Vector2 subtraction method is the same as component addition`` (a : Vector2, b : Vector2) =
let v1 = Vector2(a.X - b.X, a.Y - b.Y)
let sum = Vector2.Subtract(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector2 subtraction method by reference is the same as component addition`` (a : Vector2, b : Vector2) =
let v1 = Vector2(a.X - b.X, a.Y - b.Y)
let sum = Vector2.Subtract(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Division =
//
[<Property>]
let ``Vector2-float division is the same as component-float division`` (a : Vector2, f : float32) =
let r = a / f
Assert.ApproximatelyEqual(a.X / f,r.X)
Assert.ApproximatelyEqual(a.Y / f,r.Y)
[<Property>]
let ``Static Vector2-Vector2 division method is the same as component division`` (a : Vector2, b : Vector2) =
let v1 = Vector2(a.X / b.X, a.Y / b.Y)
let sum = Vector2.Divide(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector2-Vector2 divison method by reference `` (a : Vector2, b : Vector2) =
let v1 = Vector2(a.X / b.X, a.Y / b.Y)
let sum = Vector2.Divide(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector2-scalar division method is the same as component division`` (a : Vector2, b : float32) =
let v1 = Vector2(a.X / b, a.Y / b)
let sum = Vector2.Divide(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector2-scalar divison method by reference is the same as component division`` (a : Vector2, b : float32) =
let v1 = Vector2(a.X / b, a.Y / b)
let sum = Vector2.Divide(ref a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Negation =
//
[<Property>]
let ``Vector negation operator negates all components`` (x, y) =
let v = Vector2(x, y)
let vNeg = -v
Assert.Equal(-x, vNeg.X)
Assert.Equal(-y, vNeg.Y)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Equality =
//
[<Property>]
let ``Vector equality operator is by component`` (x, y) =
let v1 = Vector2(x, y)
let v2 = Vector2(x, y)
let equality = v1 = v2
Assert.True(equality)
[<Property>]
let ``Vector inequality operator is by component`` (x, y) =
let v1 = Vector2(x, y)
let v2 = Vector2(x + 1.0f , y + 1.0f)
let inequality = v1 <> v2
Assert.True(inequality)
[<Property>]
let ``Vector equality method is by component`` (x, y) =
let v1 = Vector2(x, y)
let v2 = Vector2(x, y)
let notVector = Matrix2()
let equality = v1.Equals(v2)
let inequalityByOtherType = v1.Equals(notVector)
Assert.True(equality)
Assert.False(inequalityByOtherType)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Swizzling =
//
[<Property>]
let ``Vector swizzling returns the correct composites`` (x, y) =
let v1 = Vector2(x, y)
let v2 = Vector2(y, x)
let v1yx = v1.Yx;
Assert.Equal(v2, v1yx);
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Interpolation =
//
[<Property>]
let ``Linear interpolation is by component`` (a : Vector2, b : Vector2, q) =
let blend = q
let rX = blend * (b.X - a.X) + a.X
let rY = blend * (b.Y - a.Y) + a.Y
let vExp = Vector2(rX, rY)
Assert.Equal(vExp, Vector2.Lerp(a, b, q))
let vRes = Vector2.Lerp(ref a, ref b, q)
Assert.Equal(vExp, vRes)
[<Property>]
let ``Barycentric interpolation follows the barycentric formula`` (a : Vector2, b : Vector2, c : Vector2, u, v) =
let r = a + u * (b - a) + v * (c - a)
Assert.Equal(r, Vector2.BaryCentric(a, b, c, u, v))
let vRes = Vector2.BaryCentric(ref a, ref b, ref c, u, v)
Assert.Equal(r, vRes)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Vector products`` =
//
[<Property>]
let ``Dot product follows the dot product formula`` (a : Vector2, b : Vector2) =
let dot = a.X * b.X + a.Y * b.Y
Assert.Equal(dot, Vector2.Dot(a, b));
let vRes = Vector2.Dot(ref a, ref b)
Assert.Equal(dot, vRes)
[<Property>]
let ``Perpendicular dot product follows the perpendicular dot product formula`` (a : Vector2, b : Vector2) =
let perpDot = a.X * b.Y - a.Y * b.X
Assert.Equal(perpDot, Vector2.PerpDot(a, b));
let vRes = Vector2.PerpDot(ref a, ref b)
Assert.Equal(perpDot, vRes)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Normalization =
//
[<Property>]
let ``Normalization creates a new unit length vector with the correct components`` (a, b) =
let v = Vector2(a, b)
let l = v.Length
// Dividing by zero is not supported
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)
[<Property>]
let ``Normalization of instance transforms the instance into a unit length vector with the correct components`` (a, b) =
let v = Vector2(a, b)
let l = v.Length
if not (approxEq l 0.0f) then
let norm = Vector2(a, b)
norm.Normalize()
Assert.ApproximatelyEqual(v.X / l, norm.X)
Assert.ApproximatelyEqual(v.Y / l, norm.Y)
[<Property>]
let ``Fast approximate normalization of instance transforms the instance into a unit length vector with the correct components`` (a, b) =
let v = Vector2(a, b)
let norm = Vector2(a, b)
norm.NormalizeFast()
let scale = MathHelper.InverseSqrtFast(a * a + b * b)
Assert.ApproximatelyEqual(v.X * scale, norm.X)
Assert.ApproximatelyEqual(v.Y * scale, norm.Y)
[<Property>]
let ``Normalization by reference is the same as division by magnitude`` (a : Vector2) =
let norm = a / a.Length
let vRes = Vector2.Normalize(ref a)
Assert.ApproximatelyEqual(norm, vRes)
[<Property>]
let ``Normalization is the same as division by magnitude`` (a : Vector2) =
let norm = a / a.Length
Assert.ApproximatelyEqual(norm, Vector2.Normalize(a));
[<Property>]
let ``Fast approximate normalization by reference is the same as multiplication by the fast inverse square`` (a : Vector2) =
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y)
let norm = a * scale
let vRes = Vector2.NormalizeFast(ref a)
Assert.ApproximatelyEqual(norm, vRes)
[<Property>]
let ``Fast approximate normalization is the same as multiplication by the fast inverse square`` (a : Vector2) =
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y)
let norm = a * scale
Assert.ApproximatelyEqual(norm, Vector2.NormalizeFast(a));
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Component min and max`` =
//
[<Property>]
let ``ComponentMin produces a new vector from the smallest components of the given vectors`` (x, y, u, w) =
let v1 = Vector2(x, y)
let v2 = Vector2(u, w)
let vMin = Vector2.ComponentMin(v1, v2)
Assert.True(vMin.X <= v1.X)
Assert.True(vMin.X <= v2.X)
Assert.True(vMin.Y <= v1.Y)
Assert.True(vMin.Y <= v2.Y)
[<Property>]
let ``ComponentMax produces a new vector from the largest components of the given vectors`` (x, y, u, w) =
let v1 = Vector2(x, y)
let v2 = Vector2(u, w)
let vMax = Vector2.ComponentMax(v1, v2)
Assert.True(vMax.X >= v1.X)
Assert.True(vMax.X >= v2.X)
Assert.True(vMax.Y >= v1.Y)
Assert.True(vMax.Y >= v2.Y)
[<Property>]
let ``ComponentMin by reference produces a new vector from the smallest components of the given vectors`` (x, y, u, w) =
let v1 = Vector2(x, y)
let v2 = Vector2(u, w)
let vMin = Vector2.ComponentMin(ref v1, ref v2)
Assert.True(vMin.X <= v1.X)
Assert.True(vMin.X <= v2.X)
Assert.True(vMin.Y <= v1.Y)
Assert.True(vMin.Y <= v2.Y)
[<Property>]
let ``ComponentMax by reference produces a new vector from the largest components of the given vectors`` (x, y, u, w) =
let v1 = Vector2(x, y)
let v2 = Vector2(u, w)
let vMax = Vector2.ComponentMax(ref v1, ref v2)
Assert.True(vMax.X >= v1.X)
Assert.True(vMax.X >= v2.X)
Assert.True(vMax.Y >= v1.Y)
Assert.True(vMax.Y >= v2.Y)
[<Property>]
let ``Min selects the vector with lesser magnitude given two vectors`` (x, y, u, w) =
let v1 = Vector2(x, y)
let v2 = Vector2(u, w)
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector2.Min(v1, v2)
if l1 < l2 then
let equalsFirst = vMin = v1
Assert.True(equalsFirst)
else
let equalsLast = vMin = v2
Assert.True(equalsLast)
[<Property>]
let ``Max selects the vector with greater magnitude given two vectors`` (x, y, u, w) =
let v1 = Vector2(x, y)
let v2 = Vector2(u, w)
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector2.Max(v1, v2)
if l1 >= l2 then
let equalsFirst = vMin = v1
Assert.True(equalsFirst)
else
let equalsLast = vMin = v2
Assert.True(equalsLast)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Transformation =
//
[<Property>]
let ``Transformation by quaternion is the same as multiplication by quaternion and its conjugate`` (v : Vector2, q : Quaternion) =
let vectorQuat = Quaternion(v.X, v.Y, 0.0f, 0.0f)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = Vector2(transformedQuat.X, transformedQuat.Y)
Assert.Equal(transformedVector, Vector2.Transform(v, q))
[<Property>]
let ``Transformation by quaternion by reference is the same as multiplication by quaternion and its conjugate`` (v : Vector2, q : Quaternion) =
let vectorQuat = Quaternion(v.X, v.Y, 0.0f, 0.0f)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = Vector2(transformedQuat.X, transformedQuat.Y)
Assert.Equal(transformedVector, Vector2.Transform(ref v, ref q))
// TODO: Implement multiplication operator for Vector2 and Quaternion
// [<Property>]
// let ``Transformation by quaternion by multiplication using right-handed notation is the same as multiplication by quaternion and its conjugate`` (v : Vector2, q : Quaternion) =
// let vectorQuat = Quaternion(v.X, v.Y, 0.0f, 0.0f)
// let inverse = Quaternion.Invert(q)
//
// let transformedQuat = q * vectorQuat * inverse
// let transformedVector = Vector2(transformedQuat.X, transformedQuat.Y)
//
// Assert.Equal(transformedVector, q * v)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Serialization =
//
[<Property>]
let ``The absolute size of a Vector2 is always the size of its components`` (v : Vector2) =
let expectedSize = sizeof<float32> * 2
Assert.Equal(expectedSize, Vector2.SizeInBytes)
Assert.Equal(expectedSize, Marshal.SizeOf(Vector2()))

View file

@ -0,0 +1,745 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open System.Runtime.InteropServices
open OpenTK
module Vector3 =
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Constructors =
//
[<Property>]
let ``Triple value constructor sets all components to the correct values`` (a, b, c) =
let v = Vector3(a, b, c)
Assert.Equal(a, v.X)
Assert.Equal(b, v.Y)
Assert.Equal(c, v.Z)
[<Property>]
let ``Single value constructor sets all components to the correct values`` (a : float32) =
let v = Vector3(a)
Assert.Equal(a, v.X)
Assert.Equal(a, v.Y)
Assert.Equal(a, v.Z)
[<Property>]
let ``Vector2 value constructor sets all components to the correct values`` (a, b) =
let v1 = Vector2(a, b)
let v2 = Vector3(v1)
Assert.Equal(v1.X, v2.X)
Assert.Equal(v1.Y, v2.Y)
Assert.Equal(a, v2.X)
Assert.Equal(b, v2.Y)
Assert.Equal(0.0f, v2.Z)
[<Property>]
let ``Vector3 value constructor sets all components to the correct values`` (a, b, c) =
let v1 = Vector3(a, b, c)
let v2 = Vector3(v1)
Assert.Equal(v1.X, v2.X)
Assert.Equal(v1.Y, v2.Y)
Assert.Equal(v1.Z, v2.Z)
Assert.Equal(a, v2.X)
Assert.Equal(b, v2.Y)
Assert.Equal(c, v2.Z)
[<Property>]
let ``Vector4 value constructor sets all components to the correct values`` (a, b, c, d) =
let v1 = Vector4(a, b, c, d)
let v2 = Vector3(v1)
Assert.Equal(v1.X, v2.X)
Assert.Equal(v1.Y, v2.Y)
Assert.Equal(v1.Z, v2.Z)
Assert.Equal(a, v2.X)
Assert.Equal(b, v2.Y)
Assert.Equal(c, v2.Z)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Indexing =
//
[<Property>]
let ``Index operator accesses the correct components`` (x, y, z) =
let v = Vector3(x, y, z)
Assert.Equal(x, v.[0])
Assert.Equal(y, v.[1])
Assert.Equal(z, v.[2])
[<Property>]
let ``Indexed set operator throws exception for negative indices`` (x, y, z) =
let mutable v = Vector3(x, y, z)
(fun() -> v.[-1] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed get operator throws exception for negative indices`` (x, y, z) =
let mutable v = Vector3(x, y, z)
(fun() -> v.[-1] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed set operator throws exception for large indices`` (x, y, z) =
let mutable v = Vector3(x, y, z)
(fun() -> v.[4] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed get operator throws exception for large indices`` (x, y, z) =
let mutable v = Vector3(x, y, z)
(fun() -> v.[4] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Length =
//
[<Property>]
let ``Length method follows the pythagorean theorem`` (a, b, c) =
let v = Vector3(a, b, c)
let l = System.Math.Sqrt((float)(a * a + b * b + c * c))
Assert.Equal((float32)l, v.Length)
[<Property>]
let ``Fast length method is the same as one divided by the fast inverse square`` (a, b, c) =
let v = Vector3(a, b, c)
let l = 1.0f / MathHelper.InverseSqrtFast(a * a + b * b + c * c)
Assert.Equal(l, v.LengthFast)
[<Property>]
let ``Length squared method returns each component squared and summed`` (a, b, c) =
let v = Vector3(a, b, c)
let lsq = a * a + b * b + c * c
Assert.Equal(lsq, v.LengthSquared)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Normalization =
//
[<Property>]
let ``Normalization creates a new unit length vector with the correct components`` (a, b, c) =
let v = Vector3(a, b, c)
let l = v.Length
// Dividing by zero is not supported
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)
[<Property>]
let ``Normalization of instance transforms the instance into a unit length vector with the correct components`` (a, b, c) =
let v = Vector3(a, b, c)
let l = v.Length
if not (approxEq l 0.0f) then
let norm = Vector3(a, b, c)
norm.Normalize()
Assert.ApproximatelyEqual(v.X / l, norm.X)
Assert.ApproximatelyEqual(v.Y / l, norm.Y)
Assert.ApproximatelyEqual(v.Z / l, norm.Z)
[<Property>]
let ``Fast approximate normalization of instance transforms the instance into a unit length vector with the correct components`` (a, b, c) =
let v = Vector3(a, b, c)
let norm = Vector3(a, b, c)
norm.NormalizeFast()
let scale = MathHelper.InverseSqrtFast(a * a + b * b + c * c)
Assert.ApproximatelyEqual(v.X * scale, norm.X)
Assert.ApproximatelyEqual(v.Y * scale, norm.Y)
Assert.ApproximatelyEqual(v.Z * scale, norm.Z)
[<Property>]
let ``Normalization by reference is the same as division by magnitude`` (a : Vector3) =
let norm = a / a.Length
let vRes = Vector3.Normalize(ref a)
Assert.ApproximatelyEqual(norm, vRes)
[<Property>]
let ``Normalization is the same as division by magnitude`` (a : Vector3) =
let norm = a / a.Length
Assert.ApproximatelyEqual(norm, Vector3.Normalize(a));
[<Property>]
let ``Fast approximate normalization by reference is the same as multiplication by the fast inverse square`` (a : Vector3) =
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z)
let norm = a * scale
let vRes = Vector3.NormalizeFast(ref a)
Assert.ApproximatelyEqual(norm, vRes)
[<Property>]
let ``Fast approximate normalization is the same as multiplication by fast inverse square`` (a : Vector3) =
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z)
let norm = a * scale
Assert.ApproximatelyEqual(norm, Vector3.NormalizeFast(a));
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Addition =
//
[<Property>]
let ``Vector3 addition is the same as component addition`` (a : Vector3, b : Vector3) =
let c = a + b
Assert.ApproximatelyEqual(a.X + b.X,c.X)
Assert.ApproximatelyEqual(a.Y + b.Y,c.Y)
Assert.ApproximatelyEqual(a.Z + b.Z,c.Z)
[<Property>]
let ``Vector3 addition is commutative`` (a : Vector3, b : Vector3) =
let c = a + b
let c2 = b + a
Assert.ApproximatelyEqual(c, c2)
[<Property>]
let ``Vector3 addition is associative`` (a : Vector3, b : Vector3, c : Vector3) =
let r1 = (a + b) + c
let r2 = a + (b + c)
Assert.ApproximatelyEqual(r1, r2)
[<Property>]
let ``Static Vector3 addition method is the same as component addition`` (a : Vector3, b : Vector3) =
let v1 = Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z)
let sum = Vector3.Add(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector3 addition method by reference is the same as component addition`` (a : Vector3, b : Vector3) =
let v1 = Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z)
let sum = Vector3.Add(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Subtraction =
//
[<Property>]
let ``Vector3 subtraction is the same as component subtraction`` (a : Vector3, b : Vector3) =
let c = a - b
Assert.Equal(a.X - b.X,c.X)
Assert.Equal(a.Y - b.Y,c.Y)
Assert.Equal(a.Z - b.Z,c.Z)
[<Property>]
let ``Static Vector3 subtraction method is the same as component addition`` (a : Vector3, b : Vector3) =
let v1 = Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z)
let sum = Vector3.Subtract(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector3 subtraction method by reference is the same as component addition`` (a : Vector3, b : Vector3) =
let v1 = Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z)
let sum = Vector3.Subtract(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Multiplication =
//
[<Property>]
let ``Vector3 multiplication is the same as component multiplication`` (a : Vector3, b : Vector3) =
let c = a * b
Assert.Equal(a.X * b.X,c.X)
Assert.Equal(a.Y * b.Y,c.Y)
Assert.Equal(a.Z * b.Z,c.Z)
[<Property>]
let ``Vector3 multiplication is commutative`` (a : Vector3, b : Vector3) =
let r1 = a * b
let r2 = b * a
Assert.Equal(r1, r2)
[<Property>]
let ``Left-handed Vector3-scalar multiplication is the same as component-scalar multiplication`` (a : Vector3, f : float32) =
let r = a * f
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
Assert.Equal(a.Z * f,r.Z)
[<Property>]
let ``Right-handed Vector3-scalar multiplication is the same as component-scalar multiplication`` (a : Vector3, f : float32) =
let r = f * a
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
Assert.Equal(a.Z * f,r.Z)
[<Property>]
let ``Static method Vector3-scalar multiplication is the same as component-scalar multiplication`` (a : Vector3, f : float32) =
let r = Vector3.Multiply(a, f)
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
Assert.Equal(a.Z * f,r.Z)
[<Property>]
let ``Vector3-Matrix3 multiplication using right-handed notation is the same as vector/row multiplication and summation`` (a : Matrix3, b : Vector3) =
let res = a*b
let c1 = b.X * a.M11 + b.Y * a.M12 + b.Z * a.M13
let c2 = b.X * a.M21 + b.Y * a.M22 + b.Z * a.M23
let c3 = b.X * a.M31 + b.Y * a.M32 + b.Z * a.M33
let exp = Vector3(c1, c2, c3)
Assert.Equal(exp, res)
[<Property>]
let ``Vector3-Matrix3 multiplication using left-handed notation is the same as vector/column multiplication and summation`` (a : Matrix3, b : Vector3) =
let res = b*a
let c1 = b.X * a.M11 + b.Y * a.M21 + b.Z * a.M31
let c2 = b.X * a.M12 + b.Y * a.M22 + b.Z * a.M32
let c3 = b.X * a.M13 + b.Y * a.M23 + b.Z * a.M33
let exp = Vector3(c1, c2, c3)
Assert.Equal(exp, res)
[<Property>]
let ``Static Vector3 multiplication method is the same as component multiplication`` (a : Vector3, b : Vector3) =
let v1 = Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z)
let sum = Vector3.Multiply(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector3 multiplication method by reference is the same as component multiplication`` (a : Vector3, b : Vector3) =
let v1 = Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z)
let sum = Vector3.Multiply(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Division =
//
[<Property>]
let ``Vector3-float division is the same as component-float division`` (a : Vector3, f : float32) =
if not (approxEq f 0.0f) then // we don't support diving by zero.
let r = a / f
Assert.ApproximatelyEqual(a.X / f,r.X)
Assert.ApproximatelyEqual(a.Y / f,r.Y)
Assert.ApproximatelyEqual(a.Z / f,r.Z)
[<Property>]
let ``Static Vector3-Vector3 division method is the same as component division`` (a : Vector3, b : Vector3) =
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)
[<Property>]
let ``Static Vector3-Vector3 divison method by reference is the same as component division`` (a : Vector3, b : Vector3) =
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)
[<Property>]
let ``Static Vector3-scalar division method is the same as component division`` (a : Vector3, b : float32) =
let v1 = Vector3(a.X / b, a.Y / b, a.Z / b)
let sum = Vector3.Divide(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector3-scalar divison method by reference is the same as component division`` (a : Vector3, b : float32) =
let v1 = Vector3(a.X / b, a.Y / b, a.Z / b)
let sum = Vector3.Divide(ref a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Negation =
//
[<Property>]
let ``Vector negation operator negates all components`` (x, y, z) =
let v = Vector3(x, y, z)
let vNeg = -v
Assert.Equal(-x, vNeg.X)
Assert.Equal(-y, vNeg.Y)
Assert.Equal(-z, vNeg.Z)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Equality =
//
[<Property>]
let ``Vector equality operator is by component`` (x, y, z) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(x, y, z)
let equality = v1 = v2
Assert.True(equality)
[<Property>]
let ``Vector inequality operator is by component`` (x, y, z) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(x + 1.0f , y + 1.0f, z + 1.0f)
let inequality = v1 <> v2
Assert.True(inequality)
[<Property>]
let ``Vector equality method is by component`` (x, y, z) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(x, y, z)
let notVector = Matrix2()
let equality = v1.Equals(v2)
let inequalityByOtherType = v1.Equals(notVector)
Assert.True(equality)
Assert.False(inequalityByOtherType)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Swizzling =
//
[<Property>]
let ``Vector swizzling returns the correct composite for X-primary components`` (x, y, z) =
let v = Vector3(x, y, z)
let xyz = Vector3(x, y, z)
let xzy = Vector3(x, z, y)
let xy = Vector2(x, y)
let xz = Vector2(x, z)
Assert.Equal(xyz, v);
Assert.Equal(xzy, v.Xzy);
Assert.Equal(xy, v.Xy);
Assert.Equal(xz, v.Xz);
[<Property>]
let ``Vector swizzling returns the correct composite for Y-primary components`` (x, y, z) =
let v = Vector3(x, y, z)
let yxz = Vector3(y, x, z)
let yzx = Vector3(y, z, x)
let yx = Vector2(y, x)
let yz = Vector2(y, z)
Assert.Equal(yxz, v.Yxz);
Assert.Equal(yzx, v.Yzx);
Assert.Equal(yx, v.Yx);
Assert.Equal(yz, v.Yz);
[<Property>]
let ``Vector swizzling returns the correct composite for Z-primary components`` (x, y, z) =
let v = Vector3(x, y, z)
let zxy = Vector3(z, x, y)
let zyx = Vector3(z, y, x)
let zx = Vector2(z, x)
let zy = Vector2(z, y);
Assert.Equal(zxy, v.Zxy);
Assert.Equal(zyx, v.Zyx);
Assert.Equal(zx, v.Zx);
Assert.Equal(zy, v.Zy);
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Interpolation =
//
[<Property>]
let ``Linear interpolation is by component`` (a : Vector3, b : Vector3, q) =
let blend = q
let rX = blend * (b.X - a.X) + a.X
let rY = blend * (b.Y - a.Y) + a.Y
let rZ = blend * (b.Z - a.Z) + a.Z
let vExp = Vector3(rX, rY, rZ)
Assert.Equal(vExp, Vector3.Lerp(a, b, q))
let vRes = Vector3.Lerp(ref a, ref b, q)
Assert.Equal(vExp, vRes)
[<Property>]
let ``Barycentric interpolation follows the barycentric formula`` (a : Vector3, b : Vector3, c : Vector3, u, v) =
let r = a + u * (b - a) + v * (c - a)
Assert.Equal(r, Vector3.BaryCentric(a, b, c, u, v))
let vRes = Vector3.BaryCentric(ref a, ref b, ref c, u, v)
Assert.Equal(r, vRes)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Vector products`` =
//
[<Property>]
let ``Dot product follows the dot product formula`` (a : Vector3, b : Vector3) =
let dot = a.X * b.X + a.Y * b.Y + a.Z * b.Z
Assert.Equal(dot, Vector3.Dot(a, b));
let vRes = Vector3.Dot(ref a, ref b)
Assert.Equal(dot, vRes)
[<Property>]
let ``Cross product follows the cross product formula`` (a : Vector3, b : Vector3) =
let crossX = a.Y * b.Z - a.Z * b.Y
let crossY = a.Z * b.X - a.X * b.Z
let crossZ = a.X * b.Y - a.Y * b.X
let cross = Vector3(crossX, crossY, crossZ)
Assert.Equal(cross, Vector3.Cross(a, b));
let vRes = Vector3.Cross(ref a, ref b)
Assert.Equal(cross, vRes)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Component min and max`` =
//
[<Property>]
let ``ComponentMin produces a new vector from the smallest components of the given vectors`` (x, y, z, u, w, q) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(u, w, q)
let vMin = Vector3.ComponentMin(v1, v2)
Assert.True(vMin.X <= v1.X)
Assert.True(vMin.X <= v2.X)
Assert.True(vMin.Y <= v1.Y)
Assert.True(vMin.Y <= v2.Y)
Assert.True(vMin.Z <= v1.Z)
Assert.True(vMin.Z <= v2.Z)
[<Property>]
let ``ComponentMax producing a new vector from the largest components of the given vectors`` (x, y, z, u, w, q) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(u, w, q)
let vMax = Vector3.ComponentMax(v1, v2)
Assert.True(vMax.X >= v1.X)
Assert.True(vMax.X >= v2.X)
Assert.True(vMax.Y >= v1.Y)
Assert.True(vMax.Y >= v2.Y)
Assert.True(vMax.Z >= v1.Z)
Assert.True(vMax.Z >= v2.Z)
[<Property>]
let ``ComponentMin by reference produces a new vector from the smallest components of the given vectors`` (x, y, z, u, w, q) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(u, w, q)
let vMin = Vector3.ComponentMin(ref v1, ref v2)
Assert.True(vMin.X <= v1.X)
Assert.True(vMin.X <= v2.X)
Assert.True(vMin.Y <= v1.Y)
Assert.True(vMin.Y <= v2.Y)
Assert.True(vMin.Z <= v1.Z)
Assert.True(vMin.Z <= v2.Z)
[<Property>]
let ``ComponentMax produces a new vector from the smallest components of the given vectors`` (x, y, z, u, w, q) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(u, w, q)
let vMax = Vector3.ComponentMax(ref v1, ref v2)
Assert.True(vMax.X >= v1.X)
Assert.True(vMax.X >= v2.X)
Assert.True(vMax.Y >= v1.Y)
Assert.True(vMax.Y >= v2.Y)
Assert.True(vMax.Z >= v1.Z)
Assert.True(vMax.Z >= v2.Z)
[<Property>]
let ``Min selects the vector with lesser magnitude given two vectors`` (x, y, z, u, w, q) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(u, w, q)
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector3.Min(v1, v2)
if l1 < l2 then
let equalsFirst = vMin = v1
Assert.True(equalsFirst)
else
let equalsLast = vMin = v2
Assert.True(equalsLast)
[<Property>]
let ``Max selects the vector with greater magnitude given two vectors`` (x, y, z, u, w, q) =
let v1 = Vector3(x, y, z)
let v2 = Vector3(u, w, q)
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector3.Max(v1, v2)
if l1 >= l2 then
let equalsFirst = vMin = v1
Assert.True(equalsFirst)
else
let equalsLast = vMin = v2
Assert.True(equalsLast)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Clamping =
//
[<Property>]
let ``Clamping one vector between two other vectors clamps all components between corresponding components`` (a : Vector3, b : Vector3, w : Vector3) =
let res = Vector3.Clamp(w, a, b)
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z
Assert.Equal(expX, res.X)
Assert.Equal(expY, res.Y)
Assert.Equal(expZ, res.Z)
[<Property>]
let ``Clamping one vector between two other vectors by reference clamps all components between corresponding components`` (a : Vector3, b : Vector3, w : Vector3) =
let res = Vector3.Clamp(ref w, ref a, ref b)
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z
Assert.Equal(expX, res.X)
Assert.Equal(expY, res.Y)
Assert.Equal(expZ, res.Z)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Unit vectors``=
//
[<Property>]
let ``Unit X is correct`` =
let unitX = Vector3(1.0f, 0.0f, 0.0f)
Assert.Equal(Vector3.UnitX, unitX)
[<Property>]
let ``Unit Y is correct`` =
let unitY = Vector3(0.0f, 1.0f, 0.0f)
Assert.Equal(Vector3.UnitY, unitY)
[<Property>]
let ``Unit Z is correct`` =
let unitZ = Vector3(0.0f, 0.0f, 1.0f)
Assert.Equal(Vector3.UnitZ, unitZ)
[<Property>]
let ``Unit zero is correct`` =
let unitZero = Vector3(0.0f, 0.0f, 0.0f)
Assert.Equal(Vector3.Zero, unitZero)
[<Property>]
let ``Unit one is correct`` =
let unitOne = Vector3(1.0f, 1.0f, 1.0f)
Assert.Equal(Vector3.One, unitOne)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Serialization =
//
[<Property>]
let ``The absolute size of a Vector3 is always the size of its components`` (v : Vector3) =
let expectedSize = sizeof<float32> * 3
Assert.Equal(expectedSize, Vector3.SizeInBytes)
Assert.Equal(expectedSize, Marshal.SizeOf(Vector3()))
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Transformation =
//
[<Property>]
let ``Transformation by quaternion is the same as multiplication by quaternion and its conjugate`` (v : Vector3, q : Quaternion) =
let vectorQuat = Quaternion(v.X, v.Y, v.Z, 0.0f)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = transformedQuat.Xyz
Assert.ApproximatelyEqual(transformedVector, Vector3.Transform(v, q))
[<Property>]
let ``Transformation by quaternion by reference is the same as multiplication by quaternion and its conjugate`` (v : Vector3, q : Quaternion) =
let vectorQuat = Quaternion(v.X, v.Y, v.Z, 0.0f)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = transformedQuat.Xyz
Assert.ApproximatelyEqual(transformedVector, Vector3.Transform(ref v, ref q))
[<Property>]
let ``Transformation by quaternion by multiplication using right-handed notation is the same as multiplication by quaternion and its conjugate`` (v : Vector3, q : Quaternion) =
let vectorQuat = Quaternion(v.X, v.Y, v.Z, 0.0f)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = transformedQuat.Xyz
Assert.ApproximatelyEqual(transformedVector, q * v)
[<Property>]
let ``Transformation by identity quaternion does not alter vector`` (v : Vector3) =
let q = Quaternion.Identity
let vectorQuat = Quaternion(v.X, v.Y, v.Z, 0.0f)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = transformedQuat.Xyz
Assert.ApproximatelyEqual(v, transformedVector)
Assert.ApproximatelyEqual(v, Vector3.Transform(v, q))
Assert.ApproximatelyEqual(transformedVector, Vector3.Transform(v, q))

View file

@ -0,0 +1,842 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open System.Runtime.InteropServices
open OpenTK
module Vector4 =
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Constructors =
//
[<Property>]
let ``Triple value constructor sets all components to the correct values`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
Assert.Equal(x, v.X)
Assert.Equal(y, v.Y)
Assert.Equal(z, v.Z)
Assert.Equal(w, v.W)
[<Property>]
let ``Single value constructor sets all components to the correct values`` (a : float32) =
let v = Vector4(a)
Assert.Equal(a, v.X)
Assert.Equal(a, v.Y)
Assert.Equal(a, v.Z)
Assert.Equal(a, v.W)
[<Property>]
let ``Vector2 value constructor sets all components to the correct values`` (x, y) =
let v1 = Vector2(x, y)
let v2 = Vector4(v1)
Assert.Equal(v1.X, v2.X)
Assert.Equal(v1.Y, v2.Y)
Assert.Equal(x, v2.X)
Assert.Equal(y, v2.Y)
Assert.Equal(0.0f, v2.Z)
Assert.Equal(0.0f, v2.W)
[<Property>]
let ``Vector3 value constructor sets all components to the correct values`` (x, y, z) =
let v1 = Vector3(x, y, z)
let v2 = Vector4(v1)
Assert.Equal(v1.X, v2.X)
Assert.Equal(v1.Y, v2.Y)
Assert.Equal(v1.Z, v2.Z)
Assert.Equal(x, v2.X)
Assert.Equal(y, v2.Y)
Assert.Equal(z, v2.Z)
Assert.Equal(0.0f, v2.W)
[<Property>]
let ``Vector3 value and scalar constructor sets all components to the correct values`` (x, y, z, w) =
let v1 = Vector3(x, y, z)
let v2 = Vector4(v1, w)
Assert.Equal(v1.X, v2.X)
Assert.Equal(v1.Y, v2.Y)
Assert.Equal(v1.Z, v2.Z)
Assert.Equal(x, v2.X)
Assert.Equal(y, v2.Y)
Assert.Equal(z, v2.Z)
Assert.Equal(w, v2.W)
[<Property>]
let ``Vector4 value constructor sets all components to the correct values`` (x, y, z, w) =
let v1 = Vector4(x, y, z, w)
let v2 = Vector4(v1)
Assert.Equal(v1.X, v2.X)
Assert.Equal(v1.Y, v2.Y)
Assert.Equal(v1.Z, v2.Z)
Assert.Equal(v1.W, v2.W)
Assert.Equal(x, v2.X)
Assert.Equal(y, v2.Y)
Assert.Equal(z, v2.Z)
Assert.Equal(w, v2.W)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Indexing =
//
[<Property>]
let ``Index operator accesses the correct components`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
Assert.Equal(x, v.[0])
Assert.Equal(y, v.[1])
Assert.Equal(z, v.[2])
Assert.Equal(w, v.[3])
[<Property>]
let ``Indexed set operator throws exception for negative indices`` (x, y, z, w) =
let mutable v = Vector4(x, y, z, w)
(fun() -> v.[-1] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed get operator throws exception for negative indices`` (x, y, z, w) =
let mutable v = Vector4(x, y, z, w)
(fun() -> v.[-1] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed set operator throws exception for large indices`` (x, y, z, w) =
let mutable v = Vector4(x, y, z, w)
(fun() -> v.[4] <- x) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Property>]
let ``Indexed get operator throws exception for large indices`` (x, y, z, w) =
let mutable v = Vector4(x, y, z, w)
(fun() -> v.[4] |> ignore) |> Assert.Throws<IndexOutOfRangeException> |> ignore
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Length =
//
[<Property>]
let ``Length method follows the pythagorean theorem`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let l = System.Math.Sqrt((float)(x * x + y * y + z * z + w * w))
Assert.Equal((float32)l, v.Length)
[<Property>]
let ``Fast length method is the same as one divided by the fast inverse square`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let l = 1.0f / MathHelper.InverseSqrtFast(x * x + y * y + z * z + w * w)
Assert.Equal(l, v.LengthFast)
[<Property>]
let ``Length squared method returns each component squared and summed`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let lsq = x * x + y * y + z * z + w * w
Assert.Equal(lsq, v.LengthSquared)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Normalization =
//
[<Property>]
let ``Normalization creates a new unit length vector with the correct components`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let l = v.Length
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)
[<Property>]
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()
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)
[<Property>]
let ``Fast approximate 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 norm = Vector4(x, y, z, w)
norm.NormalizeFast()
let scale = MathHelper.InverseSqrtFast(x * x + y * y + z * z + w * w)
Assert.ApproximatelyEqual(v.X * scale, norm.X)
Assert.ApproximatelyEqual(v.Y * scale, norm.Y)
Assert.ApproximatelyEqual(v.Z * scale, norm.Z)
Assert.ApproximatelyEqual(v.W * scale, norm.W)
[<Property>]
let ``Normalization by reference is the same as division by magnitude`` (a : Vector4) =
let norm = a / a.Length
let vRes = Vector4.Normalize(ref a)
Assert.ApproximatelyEqual(norm, vRes)
[<Property>]
let ``Normalization is the same as division by magnitude`` (a : Vector4) =
let norm = a / a.Length
Assert.ApproximatelyEqual(norm, Vector4.Normalize(a));
[<Property>]
let ``Fast approximate normalization by reference 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
let vRes = Vector4.NormalizeFast(ref a)
Assert.ApproximatelyEqual(norm, vRes)
[<Property>]
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));
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Addition =
//
[<Property>]
let ``Vector4 addition is the same as component addition`` (a : Vector4, b : Vector4) =
let c = a + b
Assert.ApproximatelyEqual(a.X + b.X,c.X)
Assert.ApproximatelyEqual(a.Y + b.Y,c.Y)
Assert.ApproximatelyEqual(a.Z + b.Z,c.Z)
Assert.ApproximatelyEqual(a.W + b.W,c.W)
[<Property>]
let ``Vector4 addition is commutative`` (a : Vector4, b : Vector4) =
let c = a + b
let c2 = b + a
Assert.ApproximatelyEqual(c, c2)
[<Property>]
let ``Vector4 addition is associative`` (a : Vector4, b : Vector4, c : Vector4) =
let r1 = (a + b) + c
let r2 = a + (b + c)
Assert.ApproximatelyEqual(r1, r2)
[<Property>]
let ``Static Vector4 addition method is the same as component addition`` (a : Vector4, b : Vector4) =
let v1 = Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W)
let sum = Vector4.Add(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector4 addition method by reference is the same as component addition`` (a : Vector4, b : Vector4) =
let v1 = Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W)
let sum = Vector4.Add(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Subtraction =
//
[<Property>]
let ``Vector4 subtraction is the same as component subtraction`` (a : Vector4, b : Vector4) =
let c = a - b
Assert.Equal(a.X - b.X,c.X)
Assert.Equal(a.Y - b.Y,c.Y)
Assert.Equal(a.Z - b.Z,c.Z)
Assert.Equal(a.W - b.W,c.W)
[<Property>]
let ``Static Vector4 subtraction method is the same as component addition`` (a : Vector4, b : Vector4) =
let v1 = Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W)
let sum = Vector4.Subtract(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector4 subtraction method by reference is the same as component addition`` (a : Vector4, b : Vector4) =
let v1 = Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W)
let sum = Vector4.Subtract(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Multiplication =
//
[<Property>]
let ``Vector4 multiplication is the same as component multiplication`` (a : Vector4, b : Vector4) =
let c = a * b
Assert.Equal(a.X * b.X,c.X)
Assert.Equal(a.Y * b.Y,c.Y)
Assert.Equal(a.Z * b.Z,c.Z)
Assert.Equal(a.W * b.W,c.W)
[<Property>]
let ``Vector4 multiplication is commutative`` (a : Vector4, b : Vector4) =
let r1 = a * b
let r2 = b * a
Assert.Equal(r1, r2)
[<Property>]
let ``Left-handed Vector4-scalar multiplication is the same as component-scalar multiplication`` (a : Vector4, f : float32) =
let r = a * f
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
Assert.Equal(a.Z * f,r.Z)
Assert.Equal(a.W * f,r.W)
[<Property>]
let ``Right-handed Vector4-scalar multiplication is the same as component-scalar multiplication`` (a : Vector4, f : float32) =
let r = f * a
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
Assert.Equal(a.Z * f,r.Z)
Assert.Equal(a.W * f,r.W)
[<Property>]
let ``Static method Vector4-scalar multiplication is the same as component-scalar multiplication`` (a : Vector4, f : float32) =
let r = Vector4.Multiply(a, f)
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
Assert.Equal(a.Z * f,r.Z)
Assert.Equal(a.W * f,r.W)
[<Property>]
let ``Vector4-Matrix4 multiplication using right-handed notation is the same as vector/row multiplication and summation`` (a : Matrix4, b : Vector4) =
let res = a*b
let c1 = b.X * a.M11 + b.Y * a.M12 + b.Z * a.M13 + b.W * a.M14
let c2 = b.X * a.M21 + b.Y * a.M22 + b.Z * a.M23 + b.W * a.M24
let c3 = b.X * a.M31 + b.Y * a.M32 + b.Z * a.M33 + b.W * a.M34
let c4 = b.X * a.M41 + b.Y * a.M42 + b.Z * a.M43 + b.W * a.M44
let exp = Vector4(c1, c2, c3, c4)
Assert.Equal(exp, res)
[<Property>]
let ``Vector4-Matrix4 multiplication using left-handed notation is the same as vector/column multiplication and summation`` (a : Matrix4, b : Vector4) =
let res = b*a
let c1 = b.X * a.M11 + b.Y * a.M21 + b.Z * a.M31 + b.W * a.M41
let c2 = b.X * a.M12 + b.Y * a.M22 + b.Z * a.M32 + b.W * a.M42
let c3 = b.X * a.M13 + b.Y * a.M23 + b.Z * a.M33 + b.W * a.M43
let c4 = b.X * a.M14 + b.Y * a.M24 + b.Z * a.M34 + b.W * a.M44
let exp = Vector4(c1, c2, c3, c4)
Assert.Equal(exp, res)
[<Property>]
let ``Static Vector4 multiplication method is the same as component multiplication`` (a : Vector4, b : Vector4) =
let v1 = Vector4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W)
let sum = Vector4.Multiply(a, b)
Assert.ApproximatelyEqual(v1, sum)
[<Property>]
let ``Static Vector4 multiplication method by reference is the same as component multiplication`` (a : Vector4, b : Vector4) =
let v1 = Vector4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W)
let sum = Vector4.Multiply(ref a, ref b)
Assert.ApproximatelyEqual(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Division =
//
[<Property>]
let ``Vector4-float division is the same as component-float division`` (a : Vector4, f : float32) =
if not (approxEq f 0.0f) then // we don't support diving by zero.
let r = a / f
Assert.ApproximatelyEqual(a.X / f, r.X)
Assert.ApproximatelyEqual(a.Y / f, r.Y)
Assert.ApproximatelyEqual(a.Z / f, r.Z)
Assert.ApproximatelyEqual(a.W / f, r.W)
[<Property>]
let ``Static Vector4-Vector4 division method is the same as component division`` (a : Vector4, b : Vector4) =
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)
[<Property>]
let ``Static Vector4-Vector4 divison method by reference is the same as component division`` (a : Vector4, b : Vector4) =
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)
[<Property>]
let ``Static Vector4-scalar division method is the same as component division`` (a : Vector4, b : float32) =
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)
[<Property>]
let ``Static Vector4-scalar divison method by reference is the same as component division`` (a : Vector4, b : float32) =
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)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Negation =
//
[<Property>]
let ``Vector negation operator negates all components`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let vNeg = -v
Assert.Equal(-x, vNeg.X)
Assert.Equal(-y, vNeg.Y)
Assert.Equal(-z, vNeg.Z)
Assert.Equal(-w, vNeg.W)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Equality =
//
[<Property>]
let ``Vector equality operator is by component`` (x, y, z, w) =
let v1 = Vector4(x, y, z, w)
let v2 = Vector4(x, y, z, w)
let equality = v1 = v2
Assert.True(equality)
[<Property>]
let ``Vector inequality operator is by component`` (x, y, z, w) =
let v1 = Vector4(x, y, z, w)
let v2 = Vector4(x + 1.0f , y + 1.0f, z + 1.0f, w + 1.0f)
let inequality = v1 <> v2
Assert.True(inequality)
[<Property>]
let ``Vector equality method is by component`` (x, y, z, w) =
let v1 = Vector4(x, y, z, w)
let v2 = Vector4(x, y, z, w)
let notVector = Matrix2()
let equality = v1.Equals(v2)
let inequalityByOtherType = v1.Equals(notVector)
Assert.True(equality)
Assert.False(inequalityByOtherType)
[<Property>]
let ``Vector equality method returns false for other classes`` (x, y, z, w) =
let v1 = Vector4(x, y, z, w)
let notVector = Matrix2()
let inequalityByOtherType = v1.Equals(notVector)
Assert.False(inequalityByOtherType)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Swizzling =
//
[<Property>]
let ``Vector swizzling returns the correct composite for X-primary components`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let xyzw = v
let xywz = Vector4(x, y, w, z)
let xzyw = Vector4(x, z, y, w)
let xzwy = Vector4(x, z, w, y)
let xwyz = Vector4(x, w, y, z)
let xwzy = Vector4(x, w, z, y)
let xyz = Vector3(x, y, z)
let xyw = Vector3(x, y, w)
let xzy = Vector3(x, z, y)
let xzw = Vector3(x, z, w)
let xwy = Vector3(x, w, y)
let xwz = Vector3(x, w, z)
let xy = Vector2(x, y)
let xz = Vector2(x, z)
let xw = Vector2(x, w)
// X primary
Assert.Equal(xyzw, v)
Assert.Equal(xywz, v.Xywz)
Assert.Equal(xzyw, v.Xzyw)
Assert.Equal(xzwy, v.Xzwy)
Assert.Equal(xwyz, v.Xwyz)
Assert.Equal(xwzy, v.Xwzy)
Assert.Equal(xyz, v.Xyz)
Assert.Equal(xyw, v.Xyw)
Assert.Equal(xzy, v.Xzy)
Assert.Equal(xzw, v.Xzw)
Assert.Equal(xwy, v.Xwy)
Assert.Equal(xwz, v.Xwz)
Assert.Equal(xy, v.Xy)
Assert.Equal(xz, v.Xz)
Assert.Equal(xw, v.Xw)
[<Property>]
let ``Vector swizzling returns the correct composite for Y-primary components`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let yxzw = Vector4(y, x, z, w)
let yxwz = Vector4(y, x, w, z)
let yyzw = Vector4(y, y, z, w)
let yywz = Vector4(y, y, w, z)
let yzxw = Vector4(y, z, x, w)
let yzwx = Vector4(y, z, w, x)
let ywxz = Vector4(y, w, x, z)
let ywzx = Vector4(y, w, z, x)
let yxz = Vector3(y, x, z)
let yxw = Vector3(y, x, w)
let yzx = Vector3(y, z, x)
let yzw = Vector3(y, z, w)
let ywx = Vector3(y, w, x)
let ywz = Vector3(y, w, z)
let yx = Vector2(y, x)
let yz = Vector2(y, z)
let yw = Vector2(y, w)
// Y primary
Assert.Equal(yxzw, v.Yxzw)
Assert.Equal(yxwz, v.Yxwz)
Assert.Equal(yyzw, v.Yyzw)
Assert.Equal(yywz, v.Yywz)
Assert.Equal(yzxw, v.Yzxw)
Assert.Equal(yzwx, v.Yzwx)
Assert.Equal(ywxz, v.Ywxz)
Assert.Equal(ywzx, v.Ywzx)
Assert.Equal(yxz, v.Yxz)
Assert.Equal(yxw, v.Yxw)
Assert.Equal(yzx, v.Yzx)
Assert.Equal(yzw, v.Yzw)
Assert.Equal(ywx, v.Ywx)
Assert.Equal(ywz, v.Ywz)
Assert.Equal(yx, v.Yx)
Assert.Equal(yz, v.Yz)
Assert.Equal(yw, v.Yw)
[<Property>]
let ``Vector swizzling returns the correct composite for Z-primary components`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let zxyw = Vector4(z, x, y, w)
let zxwy = Vector4(z, x, w, y)
let zyxw = Vector4(z, y, x, w)
let zywx = Vector4(z, y, w, x)
let zwxy = Vector4(z, w, x, y)
let zwyx = Vector4(z, w, y, x)
let zwzy = Vector4(z, w, z, y)
let zxy = Vector3(z, x, y)
let zxw = Vector3(z, x, w)
let zyx = Vector3(z, y, x)
let zyw = Vector3(z, y, w)
let zwx = Vector3(z, w, x)
let zwy = Vector3(z, w, y)
let zx = Vector2(z, x)
let zy = Vector2(z, y)
let zw = Vector2(z, w)
// Z primary
Assert.Equal(zxyw, v.Zxyw)
Assert.Equal(zxwy, v.Zxwy)
Assert.Equal(zyxw, v.Zyxw)
Assert.Equal(zywx, v.Zywx)
Assert.Equal(zwxy, v.Zwxy)
Assert.Equal(zwyx, v.Zwyx)
Assert.Equal(zwzy, v.Zwzy)
Assert.Equal(zxy, v.Zxy)
Assert.Equal(zxw, v.Zxw)
Assert.Equal(zyx, v.Zyx)
Assert.Equal(zyw, v.Zyw)
Assert.Equal(zwx, v.Zwx)
Assert.Equal(zwy, v.Zwy)
Assert.Equal(zx, v.Zx)
Assert.Equal(zy, v.Zy)
Assert.Equal(zw, v.Zw)
[<Property>]
let ``Vector swizzling returns the correct composite for W-primary components`` (x, y, z, w) =
let v = Vector4(x, y, z, w)
let wxyz = Vector4(w, x, y, z)
let wxzy = Vector4(w, x, z, y)
let wyxz = Vector4(w, y, x, z)
let wyzx = Vector4(w, y, z, x)
let wzxy = Vector4(w, z, x, y)
let wzyx = Vector4(w, z, y, x)
let wzyw = Vector4(w, z, y, w)
let wxy = Vector3(w, x, y)
let wxz = Vector3(w, x, z)
let wyx = Vector3(w, y, x)
let wyz = Vector3(w, y, z)
let wzx = Vector3(w, z, x)
let wzy = Vector3(w, z, y)
let wx = Vector2(w, x)
let wy = Vector2(w, y)
let wz = Vector2(w, z)
// W primary
Assert.Equal(wxyz, v.Wxyz)
Assert.Equal(wxzy, v.Wxzy)
Assert.Equal(wyxz, v.Wyxz)
Assert.Equal(wyzx, v.Wyzx)
Assert.Equal(wzxy, v.Wzxy)
Assert.Equal(wzyx, v.Wzyx)
Assert.Equal(wzyw, v.Wzyw)
Assert.Equal(wxy, v.Wxy)
Assert.Equal(wxz, v.Wxz)
Assert.Equal(wyx, v.Wyx)
Assert.Equal(wyz, v.Wyz)
Assert.Equal(wzx, v.Wzx)
Assert.Equal(wzy, v.Wzy)
Assert.Equal(wx, v.Wx)
Assert.Equal(wy, v.Wy)
Assert.Equal(wz, v.Wz)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Interpolation =
//
[<Property>]
let ``Linear interpolation is by component`` (a : Vector4, b : Vector4, q) =
let blend = q
let rX = blend * (b.X - a.X) + a.X
let rY = blend * (b.Y - a.Y) + a.Y
let rZ = blend * (b.Z - a.Z) + a.Z
let rW = blend * (b.W - a.W) + a.W
let vExp = Vector4(rX, rY, rZ, rW)
Assert.Equal(vExp, Vector4.Lerp(a, b, q))
let vRes = Vector4.Lerp(ref a, ref b, q)
Assert.Equal(vExp, vRes)
[<Property>]
let ``Barycentric interpolation follows the barycentric formula`` (a : Vector4, b : Vector4, c : Vector4, u, v) =
let r = a + u * (b - a) + v * (c - a)
Assert.Equal(r, Vector4.BaryCentric(a, b, c, u, v))
let vRes = Vector4.BaryCentric(ref a, ref b, ref c, u, v)
Assert.Equal(r, vRes)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Vector products`` =
//
[<Property>]
let ``Dot product method follows the dot product formula`` (a : Vector4, b : Vector4) =
let dot = a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W
Assert.Equal(dot, Vector4.Dot(a, b));
let vRes = Vector4.Dot(ref a, ref b)
Assert.Equal(dot, vRes)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Component min and max`` =
//
[<Property>]
let ``Min selects the vector with lesser magnitude given two vectors`` (x, y, z, w, a, b, c, d) =
let v1 = Vector4(x, y, z, w)
let v2 = Vector4(a, b, c, d)
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector4.Min(v1, v2)
if vMin = v1 then
let v1ShorterThanv2 = l1 < l2
Assert.True(v1ShorterThanv2)
else
let v2ShorterThanv1 = l2 < l1
Assert.True(v2ShorterThanv1)
[<Property>]
let ``Max selects the vector with greater magnitude given two vectors`` (x, y, z, w, a, b, c, d) =
let v1 = Vector4(x, y, z, w)
let v2 = Vector4(a, b, c, d)
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector4.Max(v1, v2)
if vMin = v1 then
let v1LongerThanOrEqualTov2 = l1 >= l2
Assert.True(v1LongerThanOrEqualTov2)
else
let v2LongerThanv1 = l2 > l1
Assert.True(v2LongerThanv1)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Clamping =
//
[<Property>]
let ``Clamping one vector between two other vectors clamps all components between corresponding components`` (a : Vector4, b : Vector4, w : Vector4) =
let res = Vector4.Clamp(w, a, b)
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z
let expW = if w.W < a.W then a.W else if w.W > b.W then b.W else w.W
Assert.Equal(expX, res.X)
Assert.Equal(expY, res.Y)
Assert.Equal(expZ, res.Z)
Assert.Equal(expW, res.W)
[<Property>]
let ``Clamping one vector between two other vectors by reference clamps all components`` (a : Vector4, b : Vector4, w : Vector4) =
let res = Vector4.Clamp(ref w, ref a, ref b)
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z
let expW = if w.W < a.W then a.W else if w.W > b.W then b.W else w.W
Assert.Equal(expX, res.X)
Assert.Equal(expY, res.Y)
Assert.Equal(expZ, res.Z)
Assert.Equal(expW, res.W)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Unit vectors``=
//
[<Property>]
let ``Unit X is correct`` =
let unitX = Vector4(1.0f, 0.0f, 0.0f, 0.0f)
Assert.Equal(Vector4.UnitX, unitX)
[<Property>]
let ``Unit Y is correct`` =
let unitY = Vector4(0.0f, 1.0f, 0.0f, 0.0f)
Assert.Equal(Vector4.UnitY, unitY)
[<Property>]
let ``Unit Z is correct`` =
let unitZ = Vector4(0.0f, 0.0f, 1.0f, 0.0f)
Assert.Equal(Vector4.UnitZ, unitZ)
[<Property>]
let ``Unit W is correct`` =
let unitW = Vector4(0.0f, 0.0f, 0.0f, 1.0f)
Assert.Equal(Vector4.UnitW, unitW)
[<Property>]
let ``Unit zero is correct`` =
let unitZero = Vector4(0.0f, 0.0f, 0.0f, 0.0f)
Assert.Equal(Vector4.Zero, unitZero)
[<Property>]
let ``Unit one is correct`` =
let unitOne = Vector4(1.0f, 1.0f, 1.0f, 1.0f)
Assert.Equal(Vector4.One, unitOne)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Serialization =
//
[<Property>]
let ``The absolute size of a Vector4 is always the size of its components`` (v : Vector4) =
let expectedSize = sizeof<float32> * 4
Assert.Equal(expectedSize, Vector4.SizeInBytes)
Assert.Equal(expectedSize, Marshal.SizeOf(Vector4()))
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Transformation =
//
[<Property>]
let ``Transformation by quaternion with static method is the same as multiplication by quaternion and its conjugate`` (v : Vector4, q : Quaternion) =
let vectorQuat = Quaternion(v.X, v.Y, v.Z, v.W)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = Vector4(transformedQuat.X, transformedQuat.Y, transformedQuat.Z, transformedQuat.W)
Assert.Equal(transformedVector, Vector4.Transform(v, q))
[<Property>]
let ``Transformation by quaternion with static method by reference is the same as multiplication by quaternion and its conjugate`` (v : Vector4, q : Quaternion) =
let vectorQuat = Quaternion(v.X, v.Y, v.Z, v.W)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = Vector4(transformedQuat.X, transformedQuat.Y,transformedQuat.Z, transformedQuat.W)
Assert.Equal(transformedVector, Vector4.Transform(ref v, ref q))
[<Property>]
let ``Transformation by quaternion by multiplication using right-handed notation is the same as multiplication by quaternion and its conjugate`` (v : Vector4, q : Quaternion) =
let vectorQuat = Quaternion(v.X, v.Y, v.Z, v.W)
let inverse = Quaternion.Invert(q)
let transformedQuat = q * vectorQuat * inverse
let transformedVector = Vector4(transformedQuat.X, transformedQuat.Y, transformedQuat.Z, transformedQuat.W)
Assert.Equal(transformedVector, q * v)

View file

@ -1,116 +0,0 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open OpenTK
module Vector2 =
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Constructors =
//
[<Property>]
let ``Single value constructor sets all components to the same value`` (f : float32) =
let v = Vector2(f)
Assert.Equal(f,v.X)
Assert.Equal(f,v.Y)
[<Property>]
let ``Two value constructor sets all components correctly`` (x,y) =
let v = Vector2(x,y)
Assert.Equal(x,v.X)
Assert.Equal(y,v.Y)
[<Property>]
let ``Index operators work for the correct components`` (x,y) =
let v = Vector2(x,y)
Assert.Equal(v.[0],v.X)
Assert.Equal(v.[1],v.Y)
// [<Property>]
// disabled - behaviour needs discussion
let ``Clamping works for each component`` (a : Vector2,b : Vector2,c : Vector2) =
let inline clamp (value : float32) minV maxV = MathHelper.Clamp(value,minV,maxV)
let r = Vector2.Clamp(a,b,c)
Assert.Equal(clamp a.X b.X c.X,r.X)
Assert.Equal(clamp a.Y b.Y c.Y,r.Y)
[<Property>]
let ``Length is always >= 0`` (a : Vector2) =
//
Assert.True(a.Length >= 0.0f)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Simple Properties`` =
//
[<Property>]
let ``Vector equality is by component`` (a : Vector2,b : Vector2) =
//
Assert.Equal((a.X = b.X && a.Y = b.Y),(a = b))
[<Property>]
let ``Vector length is always >= 0`` (a : Vector2) =
//
Assert.True(a.Length >= 0.0f)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Addition =
//
[<Property>]
let ``Vector addition is the same as component addition`` (a : Vector2,b : Vector2) =
let c = a + b
Assert.ApproximatelyEqual(a.X + b.X,c.X)
Assert.ApproximatelyEqual(a.Y + b.Y,c.Y)
[<Property>]
let ``Vector addition is commutative`` (a : Vector2,b : Vector2) =
let c = a + b
let c2 = b + a
Assert.ApproximatelyEqual(c,c2)
[<Property>]
let ``Vector addition is associative`` (a : Vector2,b : Vector2,c : Vector2) =
let r1 = (a + b) + c
let r2 = a + (b + c)
Assert.ApproximatelyEqual(r1,r2)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Multiplication =
//
[<Property>]
let ``Vector multiplication is the same as component multiplication`` (a : Vector2,b : Vector2) =
let c = a * b
Assert.Equal(a.X * b.X,c.X)
Assert.Equal(a.Y * b.Y,c.Y)
[<Property>]
let ``Vector multiplication is commutative`` (a : Vector2,b : Vector2) =
let r1 = a * b
let r2 = b * a
Assert.Equal(r1,r2)
[<Property>]
let ``Vector-float multiplication is the same as component-float multiplication`` (a : Vector2,f : float32) =
let r = a * f
Assert.Equal(a.X * f,r.X)
Assert.Equal(a.Y * f,r.Y)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Subtraction =
//
[<Property>]
let ``Vector subtraction is the same as component subtraction`` (a : Vector2,b : Vector2) =
let c = a - b
Assert.Equal(a.X - b.X,c.X)
Assert.Equal(a.Y - b.Y,c.Y)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Division =
//
[<Property>]
let ``Vector-float division is the same as component-float division`` (a : Vector2,f : float32) =
if not (approxEq f 0.0f) then // we don't support diving by zero.
let r = a / f
Assert.ApproximatelyEqual(a.X / f,r.X)
Assert.ApproximatelyEqual(a.Y / f,r.Y)