Merge branch 'fscheck-testing-rebased' into fix-vector4-clamp

This commit is contained in:
Jarl Gullberg 2017-06-02 19:14:04 +02:00
commit 828dfd49fc
No known key found for this signature in database
GPG key ID: 750FF6F6BDA72D23
29 changed files with 4480 additions and 882 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

@ -21,8 +21,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTK.GLWidget", "src\Open
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1857BB8E-1A35-4EBF-9F6D-685F11DC025B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTK.Tests", "tests\OpenTK.Tests\OpenTK.Tests.csproj", "{930A780C-A67C-422F-9EED-DB38DAA47AB0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.API.Desktop", "tests\Test.API.Desktop\Test.API.Desktop.csproj", "{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{F1A57014-71CE-4032-A652-01B7E35E14DB}"
@ -38,6 +36,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{5EEE
RELEASE_NOTES.md = RELEASE_NOTES.md
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "OpenTK.Tests", "tests\OpenTK.Tests\OpenTK.Tests.fsproj", "{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -76,21 +76,21 @@ Global
{A625BE87-0000-0000-0000-000000000000}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A625BE87-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A625BE87-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU
{930A780C-A67C-422F-9EED-DB38DAA47AB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{930A780C-A67C-422F-9EED-DB38DAA47AB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{930A780C-A67C-422F-9EED-DB38DAA47AB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{930A780C-A67C-422F-9EED-DB38DAA47AB0}.Release|Any CPU.Build.0 = Release|Any CPU
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}.Release|Any CPU.Build.0 = Release|Any CPU
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{930A780C-A67C-422F-9EED-DB38DAA47AB0} = {1857BB8E-1A35-4EBF-9F6D-685F11DC025B}
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99} = {1857BB8E-1A35-4EBF-9F6D-685F11DC025B}
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7} = {1857BB8E-1A35-4EBF-9F6D-685F11DC025B}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = Source\Examples\OpenTK.Examples.csproj

View file

@ -86,8 +86,9 @@ let activeProjects =
f
-- "**/OpenTK.Android.csproj"
-- "**/OpenTK.iOS.csproj"
!! "src/**/*.??proj"
++ "tests/**/OpenTK.Tests.fsproj"
-- "**/OpenTK.GLWidget.csproj"
|> xamarinFilter
@ -194,7 +195,7 @@ Target "All" DoNothing
==> "AssemblyInfo"
==> "Build"
==> "CopyBinaries"
// ==> "RunTests"
==> "RunTests"
==> "All"
"All"

View file

@ -3,6 +3,7 @@ source https://nuget.org/api/v2
#Open packages
nuget FSharp.Formatting
nuget FsCheck
nuget FsCheck.Xunit
nuget xunit.runner.console
nuget xunit.assert

View file

@ -11,7 +11,12 @@ using System.Reflection;
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "3.0.0";
internal const string InformationalVersion = "3.0.0";
internal const System.String AssemblyTitle = "Generator.Bind";
internal const System.String AssemblyProduct = "OpenTK";
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
internal const System.String AssemblyVersion = "3.0.0";
internal const System.String AssemblyFileVersion = "3.0.0";
internal const System.Boolean CLSCompliant = true;
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
}
}

View file

@ -11,7 +11,12 @@ using System.Reflection;
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "3.0.0";
internal const string InformationalVersion = "3.0.0";
internal const System.String AssemblyTitle = "Generator.Convert";
internal const System.String AssemblyProduct = "OpenTK";
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
internal const System.String AssemblyVersion = "3.0.0";
internal const System.String AssemblyFileVersion = "3.0.0";
internal const System.Boolean CLSCompliant = true;
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
}
}

View file

@ -11,7 +11,12 @@ using System.Reflection;
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "3.0.0";
internal const string InformationalVersion = "3.0.0";
internal const System.String AssemblyTitle = "Generator.Rewrite";
internal const System.String AssemblyProduct = "OpenTK";
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
internal const System.String AssemblyVersion = "3.0.0";
internal const System.String AssemblyFileVersion = "3.0.0";
internal const System.Boolean CLSCompliant = true;
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
}
}

View file

@ -11,7 +11,12 @@ using System.Reflection;
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "3.0.0";
internal const string InformationalVersion = "3.0.0";
internal const System.String AssemblyTitle = "OpenTK.GLControl";
internal const System.String AssemblyProduct = "OpenTK";
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
internal const System.String AssemblyVersion = "3.0.0";
internal const System.String AssemblyFileVersion = "3.0.0";
internal const System.Boolean CLSCompliant = true;
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
}
}

View file

@ -113,7 +113,7 @@
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3')">
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3' Or $(TargetFrameworkVersion) == 'v4.7')">
<PropertyGroup>
<__paket__GtkSharp_targets>net45\GtkSharp</__paket__GtkSharp_targets>
</PropertyGroup>
@ -126,7 +126,7 @@
</PostBuildEvent>
</PropertyGroup>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3')">
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3' Or $(TargetFrameworkVersion) == 'v4.7')">
<ItemGroup>
<Reference Include="cairo-sharp">
<HintPath>..\..\packages\GtkSharp\lib\net45\cairo-sharp.dll</HintPath>

View file

@ -11,7 +11,12 @@ using System.Reflection;
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "3.0.0";
internal const string InformationalVersion = "3.0.0";
internal const System.String AssemblyTitle = "OpenTK.GLWidget";
internal const System.String AssemblyProduct = "OpenTK";
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
internal const System.String AssemblyVersion = "3.0.0";
internal const System.String AssemblyFileVersion = "3.0.0";
internal const System.Boolean CLSCompliant = true;
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
}
}

View file

@ -326,8 +326,36 @@ namespace OpenTK
return Math.Max(Math.Min(n, max), min);
}
#endregion
private static unsafe int FloatToInt32Bits(float f) {
return *((int*) &f);
}
#endregion
}
/// <summary>
/// Approximates floating point equality with a maximum number of different bits.
/// This is typically used in place of an epsilon comparison.
/// see: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
/// see: https://stackoverflow.com/questions/3874627/floating-point-comparison-functions-for-c-sharp
/// </summary>
/// <param name="a">the first value to compare</param>
/// <param name="b">>the second value to compare</param>
/// <param name="maxDeltaBits">the number of floating point bits to check</param>
/// <returns></returns>
public static bool ApproximatelyEqual(float a, float b, int maxDeltaBits) {
// we use longs here, otherwise we run into a two's complement problem, causing this to fail with -2 and 2.0
long aInt = FloatToInt32Bits(a);
if (aInt < 0)
aInt = Int32.MinValue - aInt;
long bInt = FloatToInt32Bits(b);
if (bInt < 0)
bInt = Int32.MinValue - bInt;
long intDiff = Math.Abs(aInt - bInt);
return intDiff <= (1 << maxDeltaBits);
}
#endregion
#endregion
}
}

View file

@ -11,7 +11,12 @@ using System.Reflection;
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "3.0.0";
internal const string InformationalVersion = "3.0.0";
internal const System.String AssemblyTitle = "OpenTK";
internal const System.String AssemblyProduct = "OpenTK";
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
internal const System.String AssemblyVersion = "3.0.0";
internal const System.String AssemblyFileVersion = "3.0.0";
internal const System.Boolean CLSCompliant = true;
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
}
}

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.4.0.0" newVersion="4.4.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<!--<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>-->
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

View file

@ -0,0 +1,41 @@
namespace OpenTK.Tests.AssemblyInfo
open System.Reflection
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[<assembly: AssemblyTitle("OpenTK.Tests")>]
[<assembly: AssemblyDescription("")>]
[<assembly: AssemblyConfiguration("")>]
[<assembly: AssemblyCompany("")>]
[<assembly: AssemblyProduct("OpenTK.Tests")>]
[<assembly: AssemblyCopyright("Copyright © 2017")>]
[<assembly: AssemblyTrademark("")>]
[<assembly: AssemblyCulture("")>]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[<assembly: ComVisible(false)>]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[<assembly: Guid("6801c263-adda-4a7b-979d-649bcb5a1df7")>]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [<assembly: AssemblyVersion("1.0.*")>]
[<assembly: AssemblyVersion("1.0.0.0")>]
[<assembly: AssemblyFileVersion("1.0.0.0")>]
do
()

View file

@ -0,0 +1,31 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open OpenTK
[<AutoOpen>]
module private AssertHelpers =
[<Literal>]
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) =
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) =
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
raise <| new Xunit.Sdk.EqualException(a,b)
static member ApproximatelyEqual(a : float32,b : float32) =
if not <| approxEq a b then raise <| new Xunit.Sdk.EqualException(a,b)

View file

@ -0,0 +1,77 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open OpenTK
[<AutoOpen>]
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 =
Arb.Default.Float() |> Arb.toGen
|> Gen.filter isValidDouble
|> Arb.fromGen
let vec2 =
singleArb
|> Gen.two
|> Gen.map Vector2
|> Arb.fromGen
let vec3 =
singleArb
|> Gen.three
|> Gen.map Vector3
|> Arb.fromGen
let vec4 =
singleArb
|> Gen.four
|> Gen.map Vector4
|> Arb.fromGen
let quat =
singleArb
|> 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 =
singleArb
|> Gen.four
|> Gen.map Matrix2
|> Arb.fromGen
let mat3 =
vec3
|> Arb.toGen
|> Gen.three
|> Gen.map Matrix3
|> Arb.fromGen
let mat4 =
vec4
|> Arb.toGen
|> Gen.four
|> Gen.map Matrix4
|> Arb.fromGen
type OpenTKGen =
static member Single() = single
static member float32() = single
static member Double() = double
static member float() = double
static member Vector2() = vec2
static member Vector3() = vec3
static member Vector4() = vec4
static member Quaternion() = quat
static member Matrix2() = mat2
static member Matrix3() = mat3
static member Matrix4() = mat4

View file

@ -0,0 +1,55 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open OpenTK
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
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 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 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 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 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 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 a = 0.0f
let b = 0.0f
Assert.Equal(a,b)
Assert.True(MathHelper.ApproximatelyEqual(a,b,0))

View file

@ -1,289 +0,0 @@
using System;
using NUnit.Framework;
using OpenTK;
namespace OpenTK.Tests
{
[TestFixture]
public class Matrix4Test
{
[Test]
public void Matrix4_SixteenValueConstructor()
{
Matrix4 A = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Assert.AreEqual(0, A.M11);
Assert.AreEqual(1, A.M12);
Assert.AreEqual(2, A.M13);
Assert.AreEqual(3, A.M14);
Assert.AreEqual(4, A.M21);
Assert.AreEqual(5, A.M22);
Assert.AreEqual(6, A.M23);
Assert.AreEqual(7, A.M24);
Assert.AreEqual(8, A.M31);
Assert.AreEqual(9, A.M32);
Assert.AreEqual(10, A.M33);
Assert.AreEqual(11, A.M34);
Assert.AreEqual(12, A.M41);
Assert.AreEqual(13, A.M42);
Assert.AreEqual(14, A.M43);
Assert.AreEqual(15, A.M44);
}
[Test]
public void Matrix4_Matrix3Constructor()
{
Matrix3 B = new Matrix3( 1, 2, 3,
4, 5, 6,
7, 8, 9);
Matrix4 A = new Matrix4(B);
Assert.AreEqual(B.M11, A.M11);
Assert.AreEqual(B.M12, A.M12);
Assert.AreEqual(B.M13, A.M13);
Assert.AreEqual(B.M21, A.M21);
Assert.AreEqual(B.M22, A.M22);
Assert.AreEqual(B.M23, A.M23);
Assert.AreEqual(B.M31, A.M31);
Assert.AreEqual(B.M32, A.M32);
Assert.AreEqual(B.M33, A.M33);
}
[Test]
public void Matrix4_FourVector4Constructor()
{
Vector4 V = new Vector4(1, 2, 3, 4);
Vector4 U = new Vector4(5, 6, 7, 8);
Vector4 S = new Vector4(9, 10, 11, 12);
Vector4 T = new Vector4(13, 14, 15, 16);
Matrix4 A = new Matrix4(V, U, S, T);
Assert.AreEqual(V.X, A.M11);
Assert.AreEqual(V.Y, A.M12);
Assert.AreEqual(V.Z, A.M13);
Assert.AreEqual(V.W, A.M14);
Assert.AreEqual(U.X, A.M21);
Assert.AreEqual(U.Y, A.M22);
Assert.AreEqual(U.Z, A.M23);
Assert.AreEqual(U.W, A.M24);
Assert.AreEqual(S.X, A.M31);
Assert.AreEqual(S.Y, A.M32);
Assert.AreEqual(S.Z, A.M33);
Assert.AreEqual(S.W, A.M34);
Assert.AreEqual(T.X, A.M41);
Assert.AreEqual(T.Y, A.M42);
Assert.AreEqual(T.Z, A.M43);
Assert.AreEqual(T.W, A.M44);
}
[Test]
public void Matrix4_Equal_operator()
{
Matrix4 A = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Matrix4 B = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Assert.IsTrue(A == B);
}
[Test]
public void Matrix4_Matrix4TimesMatrix4_operator()
{
Matrix4 A = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Matrix4 B = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Matrix4 expected = new Matrix4( 56, 62, 68, 74,
152, 174, 196, 218,
248, 286, 324, 362,
344, 398, 452, 506);
Matrix4 result = A * B;
Assert.IsTrue(expected == result);
}
[Test]
public void Matrix4_Matrix4PlusMatrix4_operator()
{
Matrix4 A = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Matrix4 B = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Matrix4 expected = new Matrix4( 0, 2, 4, 6,
8, 10, 12, 14,
16, 18, 20, 22,
24, 26, 28, 30);
Matrix4 result = A + B;
Assert.IsTrue(expected == result);
}
[Test]
public void Matrix4_Matrix4MinusMatrix4_operator()
{
Matrix4 A = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Matrix4 B = new Matrix4( 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15);
Matrix4 expected = new Matrix4( 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0);
Matrix4 result = A - B;
Assert.IsTrue(expected == result);
}
[Test]
public void Matrix4_Index_Operator()
{
Matrix4 A = new Matrix4();
A[0, 0] = 0;
A[0, 1] = 1;
A[0, 2] = 2;
A[0, 3] = 3;
A[1, 0] = 4;
A[1, 1] = 5;
A[1, 2] = 6;
A[1, 3] = 7;
A[2, 0] = 8;
A[2, 1] = 9;
A[2, 2] = 10;
A[2, 3] = 11;
A[3, 0] = 12;
A[3, 1] = 13;
A[3, 2] = 14;
A[3, 3] = 15;
Assert.AreEqual(0, A[0, 0]);
Assert.AreEqual(1, A[0, 1]);
Assert.AreEqual(2, A[0, 2]);
Assert.AreEqual(3, A[0, 3]);
Assert.AreEqual(4, A[1, 0]);
Assert.AreEqual(5, A[1, 1]);
Assert.AreEqual(6, A[1, 2]);
Assert.AreEqual(7, A[1, 3]);
Assert.AreEqual(8, A[2, 0]);
Assert.AreEqual(9, A[2, 1]);
Assert.AreEqual(10, A[2, 2]);
Assert.AreEqual(11, A[2, 3]);
Assert.AreEqual(12, A[3, 0]);
Assert.AreEqual(13, A[3, 1]);
Assert.AreEqual(14, A[3, 2]);
Assert.AreEqual(15, A[3, 3]);
}
[Test]
public void Matrix4_Index_NegativeIndexException()
{
Matrix4 A = new Matrix4();
bool negativeIndexException = false;
try
{
A[-1, 2] = 0;
}
catch(Exception)
{
negativeIndexException = true;
}
Assert.IsTrue(negativeIndexException);
negativeIndexException = false;
try
{
A[1, -2] = 0;
}
catch (Exception)
{
negativeIndexException = true;
}
Assert.IsTrue(negativeIndexException);
negativeIndexException = false;
try
{
A[-1, -2] = 0;
}
catch (Exception)
{
negativeIndexException = true;
}
Assert.IsTrue(negativeIndexException);
}
[Test]
public void Matrix4_Index_LargeIndexException()
{
Matrix4 A = new Matrix4();
bool largeIndexException = false;
try
{
A[5, 2] = 0;
}
catch (Exception)
{
largeIndexException = true;
}
Assert.IsTrue(largeIndexException);
largeIndexException = false;
try
{
A[1, 6] = 0;
}
catch (Exception)
{
largeIndexException = true;
}
Assert.IsTrue(largeIndexException);
largeIndexException = false;
try
{
A[7, 12] = 0;
}
catch (Exception)
{
largeIndexException = true;
}
Assert.IsTrue(largeIndexException);
}
}
}

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

@ -1,87 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{930A780C-A67C-422F-9EED-DB38DAA47AB0}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenTK.Tests</RootNamespace>
<AssemblyName>OpenTK.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="nunit.core.interfaces, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.util, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="NUnit.VisualStudio.TestAdapter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=4cb40d35494691ac, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Matrix4Test.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Vector3Tests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\OpenTK\OpenTK.csproj">
<Project>{a37a7e14-0000-0000-0000-000000000000}</Project>
<Name>OpenTK</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

File diff suppressed because it is too large Load diff

View file

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenTK.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OpenTK.Tests")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8a03c40d-007c-4a15-ab0c-2111969ea6df")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

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

@ -1,439 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using OpenTK;
namespace OpenTK.Tests
{
[TestFixture]
public class Vector3Tests
{
[Test]
public void Vector3_SingleValueConstructor()
{
Vector3 V = new Vector3(1);
Assert.AreEqual(1, V.X);
Assert.AreEqual(1, V.Y);
Assert.AreEqual(1, V.Z);
}
[Test]
public void Vector3_ThreeValueConstructor()
{
Vector3 V = new Vector3(1,2,3);
Assert.AreEqual(1, V.X);
Assert.AreEqual(2, V.Y);
Assert.AreEqual(3, V.Z);
}
[Test]
public void Vector3_Vector2Constructor()
{
Vector2 T = new Vector2(1, 2);
Vector3 V = new Vector3(T);
Assert.AreEqual(T.X, V.X);
Assert.AreEqual(T.Y, V.Y);
Assert.AreEqual(0, V.Z);
}
[Test]
public void Vector3_Vector3Constructor()
{
Vector3 U = new Vector3(1, 2, 3);
Vector3 V = new Vector3(U);
Assert.IsTrue(U == V);
}
[Test]
public void Vector3_Vector4Constructor()
{
Vector4 T = new Vector4(1, 2, 3, 0);
Vector3 V = new Vector3(T);
Assert.AreEqual(T.X, V.X);
Assert.AreEqual(T.Y, V.Y);
Assert.AreEqual(T.Z, V.Z);
}
[Test]
public void Vector3_Index_operator()
{
Vector3 V = new Vector3();
V[0] = 1; V[1] = 2; V[2] = 3;
Assert.AreEqual(1, V[0]);
Assert.AreEqual(2, V[1]);
Assert.AreEqual(3, V[2]);
}
[Test]
public void Vector3_Index_NegativeExceptin()
{
//the syntax for an expected exception changes from
//NUnit 2.6.4 / Microsoft Unit Test to NUnit 3+
//but a try-catch block is always guaranteed to work
Vector3 V = new Vector3();
bool negativeIndexExceptionFound = false;
try
{
V[-1] = 5;
}
catch (Exception)
{
negativeIndexExceptionFound = true;
}
Assert.IsTrue(negativeIndexExceptionFound);
}
[Test]
public void Vector3_Index_LargeIndexExceptin()
{
//the syntax for an expected exception changes from
//NUnit 2.6.4 / Microsoft Unit Test to NUnit 3+
//but a try-catch block is always guaranteed to work
Vector3 V = new Vector3();
bool largeIndexExceptionFound = false;
try
{
V[3] = 6;
}
catch (Exception)
{
largeIndexExceptionFound = true;
}
Assert.IsTrue(largeIndexExceptionFound);
}
[Test]
public void Vector3_Length()
{
float X = 1, Y = 2, Z = 2;
Vector3 U = new Vector3(X, Y, Z);
Assert.AreEqual((float)System.Math.Sqrt(X * X + Y * Y + Z * Z), U.Length);
}
[Test]
public void Vector3_LengthFast()
{
float X = 1, Y = 2, Z = 2;
Vector3 U = new Vector3(X, Y, Z);
Assert.AreEqual(1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z), U.LengthFast);
}
[Test]
public void Vector3_Normalized()
{
float X = 2, Y = 4, Z = 16;
Vector3 U = new Vector3(X, Y, Z);
float length = U.Length;
Vector3 V = U.Normalized();
Assert.AreEqual(U.X / length, V.X);
Assert.AreEqual(U.Y / length, V.Y);
Assert.AreEqual(U.Z / length, V.Z);
}
[Test]
public void Vector3_NormalizeFast_Instance()
{
float X = 2, Y = 4, Z = 16;
Vector3 U = new Vector3(X, Y, Z);
Vector3 V = U;
V.NormalizeFast();
float scale = MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z);
Assert.AreEqual(U.X * scale, V.X);
Assert.AreEqual(U.Y * scale, V.Y);
Assert.AreEqual(U.Z * scale, V.Z);
}
[Test]
public void Vector3_Add()
{
Vector3 T = new Vector3(7, 8, 9);
Vector3 U = new Vector3(23, 89, -34);
Vector3 V = Vector3.Add(T, U);
Assert.AreEqual(T.X + U.X, V.X);
Assert.AreEqual(T.Y + U.Y, V.Y);
Assert.AreEqual(T.Z + U.Z, V.Z);
}
[Test]
public void Vector3_Subtract()
{
Vector3 T = new Vector3(7, 8, 9);
Vector3 U = new Vector3(23, 89, -34);
Vector3 V = Vector3.Subtract(T, U);
Assert.AreEqual(T.X - U.X, V.X);
Assert.AreEqual(T.Y - U.Y, V.Y);
Assert.AreEqual(T.Z - U.Z, V.Z);
}
[Test]
public void Vector3_Multiply_Scalar()
{
float scalar = 5.5f;
Vector3 U = new Vector3(23, 89, -34);
Vector3 V = Vector3.Multiply(U, scalar);
Assert.AreEqual(U.X * scalar, V.X);
Assert.AreEqual(U.Y * scalar, V.Y);
Assert.AreEqual(U.Z * scalar, V.Z);
}
[Test]
public void Vector3_Multiply_Componentwise()
{
Vector3 T = new Vector3(7, 8, 0.5f);
Vector3 U = new Vector3(23, 89, -34);
Vector3 V = Vector3.Multiply(T, U);
Assert.AreEqual(T.X * U.X, V.X);
Assert.AreEqual(T.Y * U.Y, V.Y);
Assert.AreEqual(T.Z * U.Z, V.Z);
}
[Test]
public void Vector3_Divide_Scalar()
{
float scalar = 5.5f;
Vector3 U = new Vector3(23, 89, -34);
Vector3 V = Vector3.Divide(U, scalar);
//we have to account for a small amount of round off error
//in this division test
Assert.IsTrue(Math.Abs((U.X / scalar) - V.X) < 1e-5);
Assert.IsTrue(Math.Abs((U.Y / scalar) - V.Y) < 1e-5);
Assert.IsTrue(Math.Abs((U.Z / scalar) - V.Z) < 1e-5);
}
[Test]
public void Vector3_ComponentMin()
{
Vector3 T = new Vector3(1, 55, -100);
Vector3 U = new Vector3(24, 3, 1);
Vector3 V = Vector3.ComponentMin(T, U);
Assert.AreEqual(1, V.X);
Assert.AreEqual(3, V.Y);
Assert.AreEqual(-100, V.Z);
}
[Test]
public void Vector3_ComponentMinOut()
{
Vector3 T = new Vector3(1, 55, -100);
Vector3 U = new Vector3(24, 3, 1);
Vector3 V;
Vector3.ComponentMin(ref T, ref U, out V);
Assert.AreEqual(1, V.X);
Assert.AreEqual(3, V.Y);
Assert.AreEqual(-100, V.Z);
}
[Test]
public void Vector3_ComponentMax()
{
Vector3 T = new Vector3(1, 55, -100);
Vector3 U = new Vector3(24, 3, 1);
Vector3 V = Vector3.ComponentMax(T, U);
Assert.AreEqual(24, V.X);
Assert.AreEqual(55, V.Y);
Assert.AreEqual(1, V.Z);
}
[Test]
public void Vector3_ComponentMaxOut()
{
Vector3 T = new Vector3(1, 55, -100);
Vector3 U = new Vector3(24, 3, 1);
Vector3 V;
Vector3.ComponentMax(ref T, ref U, out V);
Assert.AreEqual(24, V.X);
Assert.AreEqual(55, V.Y);
Assert.AreEqual(1, V.Z);
}
[Test]
public void Vector3_Min()
{
Vector3 T = new Vector3(1, 2, 3);
Vector3 U = new Vector3(24, 300, 88);
Vector3 result = Vector3.Min(T, U);
Assert.IsTrue(result == T);
}
[Test]
public void Vector3_Max()
{
Vector3 T = new Vector3(1, 2, 3);
Vector3 U = new Vector3(24, 300, 88);
Vector3 result = Vector3.Max(T, U);
Assert.IsTrue(result == U);
}
[Test]
public void Vector3_Clamp()
{
Vector3 V = new Vector3(-6, 302, -22);
Vector3 min = new Vector3(-5, -10, -20);
Vector3 max = new Vector3(24, 300, 55);
Vector3 result = Vector3.Clamp(V, min, max);
Assert.AreEqual(result.X, -5);
Assert.AreEqual(result.Y, 300);
Assert.AreEqual(result.Z, -20);
}
[Test]
public void Vector3_ClampOut()
{
Vector3 V = new Vector3(-6, 302, -22);
Vector3 min = new Vector3(-5, -10, -20);
Vector3 max = new Vector3(24, 300, 55);
Vector3 result;
Vector3.Clamp(ref V, ref min, ref max, out result);
Assert.AreEqual(result.X, -5);
Assert.AreEqual(result.Y, 300);
Assert.AreEqual(result.Z, -20);
}
[Test]
public void Vector3_Normalize()
{
float X = 64, Y = 144, Z = 16;
Vector3 U = new Vector3(X, Y, Z);
Vector3 V = Vector3.Normalize(U);
float length = U.Length;
Assert.IsTrue(Math.Abs((U.X / length) - V.X) < 1e-5);
Assert.IsTrue(Math.Abs((U.Y / length) - V.Y) < 1e-5);
Assert.IsTrue(Math.Abs((U.Z / length) - V.Z) < 1e-5);
}
[Test]
public void Vector3_NormalizeOut()
{
float X = 64, Y = 144, Z = 16;
Vector3 U = new Vector3(X, Y, Z);
Vector3 V;
Vector3.Normalize(ref U, out V);
float length = U.Length;
Assert.IsTrue(Math.Abs((U.X / length) - V.X) < 1e-5);
Assert.IsTrue(Math.Abs((U.Y / length) - V.Y) < 1e-5);
Assert.IsTrue(Math.Abs((U.Z / length) - V.Z) < 1e-5);
}
[Test]
public void Vector3_NormalizeFast_Static()
{
float X = 64, Y = 144, Z = 16;
Vector3 U = new Vector3(X, Y, Z);
Vector3 V = Vector3.NormalizeFast(U);
float scale = MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z);
Assert.AreEqual(U.X * scale, V.X);
Assert.AreEqual(U.Y * scale, V.Y);
Assert.AreEqual(U.Z * scale, V.Z);
}
[Test]
public void Vector3_NormalizeFast()
{
float X = 64, Y = 144, Z = 16;
Vector3 U = new Vector3(X, Y, Z);
Vector3 V;
Vector3.NormalizeFast(ref U, out V);
float scale = MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z);
Assert.AreEqual(U.X * scale, V.X);
Assert.AreEqual(U.Y * scale, V.Y);
Assert.AreEqual(U.Z * scale, V.Z);
}
[Test]
public void Vector3_Dot()
{
Vector3 T = new Vector3(7, 8, 9);
Vector3 U = new Vector3(23, 89, -34);
float dot = Vector3.Dot(T, U);
float expected = T.X * U.X + T.Y * U.Y + T.Z * U.Z;
Assert.AreEqual(expected, dot);
}
[Test]
public void Vector3_Cross()
{
Vector3 T = new Vector3(7, 8, 9);
Vector3 U = new Vector3(23, 89, -34);
Vector3 expected = new Vector3(-1073, 445, 439);
Vector3 result = Vector3.Cross(T, U);
Assert.IsTrue(expected == result);
}
[Test]
public void Vector3_Lerp()
{
Vector3 T = new Vector3(7, 8, 9);
Vector3 U = new Vector3(23, 89, -34);
float blend = 0.25f;
Vector3 expected = blend * (U - T) + T;
Vector3 result = Vector3.Lerp(T, U, blend);
Assert.IsTrue(expected == result);
}
[Test]
public void Vector3_LerpOut()
{
Vector3 T = new Vector3(7, 8, 9);
Vector3 U = new Vector3(23, 89, -34);
float blend = 0.25f;
Vector3 expected = blend * (U - T) + T;
Vector3 result;
Vector3.Lerp(ref T, ref U, blend, out result);
Assert.IsTrue(expected == result);
}
[Test]
public void Vector3_BaryCentric()
{
Vector3 a = new Vector3(7, 8, 9);
Vector3 b = new Vector3(23, 89, -34);
Vector3 c = new Vector3(88, -42, 39);
float u = 0.25f;
float v = 0.75f;
Vector3 expected = a + u * (b - a) + v * (c - a);
Vector3 result = Vector3.BaryCentric(a, b, c, u, v);
Assert.IsTrue(expected == result);
}
[Test]
public void Vector3_BaryCentricOut()
{
Vector3 a = new Vector3(7, 8, 9);
Vector3 b = new Vector3(23, 89, -34);
Vector3 c = new Vector3(88, -42, 39);
float u = 0.25f;
float v = 0.75f;
Vector3 expected = a + u * (b - a) + v * (c - a);
Vector3 result;
Vector3.BaryCentric(ref a, ref b, ref c, u, v, out result);
Assert.IsTrue(expected == result);
}
[Test]
public void Vector3_Matrix3TimesVector3_operator()
{
Matrix3 A = new Matrix3();
A[0, 0] = 16; A[0, 1] = 15; A[0, 2] = 14;
A[1, 0] = 12; A[1, 1] = 11; A[1, 2] = 10;
A[2, 0] = 8; A[2, 1] = 7; A[2, 2] = 6;
Vector3 input = new Vector3(1, 5, 9);
Vector3 result = A * input;
OpenTK.Vector3 expected = new OpenTK.Vector3(217, 157, 97);
Assert.IsTrue(expected == result);
}
[Test]
public void Vector3_Equal_operator()
{
Vector3 V = new Vector3(1, 2, 3);
Vector3 U = new Vector3(1, 2, 3);
Assert.IsTrue(U == V);
}
}
}

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,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="2.6.4" targetFramework="net45" />
<package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" />
</packages>

View file

@ -0,0 +1,2 @@
FsCheck.Xunit
xunit.assert