Merge pull request #507 from varon/fscheck_testing

Property-based testing
This commit is contained in:
varon 2017-06-08 13:29:19 +02:00 committed by GitHub
commit e3d324a9c5
35 changed files with 5660 additions and 950 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

@ -3,13 +3,14 @@
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*
*
* Contributions by Andy Gill, James Talton and Georg Wächter.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace OpenTK
@ -326,8 +327,149 @@ 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);
}
/// <summary>
/// Approximates double-precision floating point equality by an epsilon (maximum error) value.
/// This method is designed as a "fits-all" solution and attempts to handle as many cases as possible.
/// </summary>
/// <param name="a">The first float.</param>
/// <param name="b">The second float.</param>
/// <param name="epsilon">The maximum error between the two.</param>
/// <returns><value>true</value> if the values are approximately equal within the error margin; otherwise, <value>false</value>.</returns>
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
public static bool ApproximatelyEqualEpsilon(double a, double b, double epsilon)
{
const double doubleNormal = (1L << 52) * double.Epsilon;
double absA = Math.Abs(a);
double absB = Math.Abs(b);
double diff = Math.Abs(a - b);
if (a == b)
{
// Shortcut, handles infinities
return true;
}
if (a == 0.0f || b == 0.0f || diff < doubleNormal)
{
// a or b is zero, or both are extremely close to it.
// relative error is less meaningful here
return diff < (epsilon * doubleNormal);
}
// use relative error
return diff / Math.Min((absA + absB), double.MaxValue) < epsilon;
}
/// <summary>
/// Approximates single-precision floating point equality by an epsilon (maximum error) value.
/// This method is designed as a "fits-all" solution and attempts to handle as many cases as possible.
/// </summary>
/// <param name="a">The first float.</param>
/// <param name="b">The second float.</param>
/// <param name="epsilon">The maximum error between the two.</param>
/// <returns><value>true</value> if the values are approximately equal within the error margin; otherwise, <value>false</value>.</returns>
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
public static bool ApproximatelyEqualEpsilon(float a, float b, float epsilon)
{
const float floatNormal = (1 << 23) * float.Epsilon;
float absA = Math.Abs(a);
float absB = Math.Abs(b);
float diff = Math.Abs(a - b);
if (a == b)
{
// Shortcut, handles infinities
return true;
}
if (a == 0.0f || b == 0.0f || diff < floatNormal)
{
// a or b is zero, or both are extremely close to it.
// relative error is less meaningful here
return diff < (epsilon * floatNormal);
}
// use relative error
float relativeError = diff / Math.Min((absA + absB), float.MaxValue);
return relativeError < epsilon;
}
/// <summary>
/// Approximates equivalence between two single-precision floating-point numbers on a direct human scale.
/// It is important to note that this does not approximate equality - instead, it merely checks whether or not
/// two numbers could be considered equivalent to each other within a certain tolerance. The tolerance is
/// inclusive.
/// </summary>
/// <param name="a">The first value to compare.</param>
/// <param name="b">The second value to compare·</param>
/// <param name="tolerance">The tolerance within which the two values would be considered equivalent.</param>
/// <returns>Whether or not the values can be considered equivalent within the tolerance.</returns>
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
public static bool ApproximatelyEquivalent(float a, float b, float tolerance)
{
if (a == b)
{
// Early bailout, handles infinities
return true;
}
float diff = Math.Abs(a - b);
return diff <= tolerance;
}
/// <summary>
/// Approximates equivalence between two double-precision floating-point numbers on a direct human scale.
/// It is important to note that this does not approximate equality - instead, it merely checks whether or not
/// two numbers could be considered equivalent to each other within a certain tolerance. The tolerance is
/// inclusive.
/// </summary>
/// <param name="a">The first value to compare.</param>
/// <param name="b">The second value to compare·</param>
/// <param name="tolerance">The tolerance within which the two values would be considered equivalent.</param>
/// <returns>Whether or not the values can be considered equivalent within the tolerance.</returns>
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
public static bool ApproximatelyEquivalent(double a, double b, double tolerance)
{
if (a == b)
{
// Early bailout, handles infinities
return true;
}
double diff = Math.Abs(a - b);
return diff <= tolerance;
}
#endregion
#endregion
}
}

View file

@ -623,7 +623,8 @@ namespace OpenTK
/// <param name="result">Result of the operation.</param>
public static void Divide(ref Vector2 vector, float scale, out Vector2 result)
{
Multiply(ref vector, 1 / scale, out result);
result.X = vector.X / scale;
result.Y = vector.Y / scale;
}
/// <summary>
@ -654,7 +655,7 @@ namespace OpenTK
#region ComponentMin
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -667,7 +668,7 @@ namespace OpenTK
}
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -683,7 +684,7 @@ namespace OpenTK
#region ComponentMax
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -696,7 +697,7 @@ namespace OpenTK
}
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -709,6 +710,64 @@ namespace OpenTK
#endregion
#region MagnitudeMin
/// <summary>
/// Returns the Vector2 with the minimum magnitude. If the magnitudes are equal, the second vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector2</returns>
public static Vector2 MagnitudeMin(Vector2 left, Vector2 right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector2 with the minimum magnitude. If the magnitudes are equal, the second vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise minimum</param>
/// <returns>The minimum Vector2</returns>
public static void MagnitudeMin(ref Vector2 left, ref Vector2 right, out Vector2 result)
{
result = left.LengthSquared < right.LengthSquared ? left : right;
}
#endregion
#region MagnitudeMax
/// <summary>
/// Returns the Vector2 with the maximum magnitude. If the magnitudes are equal, the first vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The maximum Vector2</returns>
public static Vector2 MagnitudeMax(Vector2 left, Vector2 right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector2 with the maximum magnitude. If the magnitudes are equal, the first vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise maximum</param>
/// <returns>The maximum Vector2</returns>
public static void MagnitudeMax(ref Vector2 left, ref Vector2 right, out Vector2 result)
{
result = left.LengthSquared >= right.LengthSquared ? left : right;
}
#endregion
#region Min
/// <summary>
@ -717,6 +776,7 @@ namespace OpenTK
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
[Obsolete("Use MagnitudeMin() instead.")]
public static Vector2 Min(Vector2 left, Vector2 right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
@ -732,6 +792,7 @@ namespace OpenTK
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
[Obsolete("Use MagnitudeMax() instead.")]
public static Vector2 Max(Vector2 left, Vector2 right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
@ -1074,7 +1135,7 @@ namespace OpenTK
vec.Y *= scale.Y;
return vec;
}
/// <summary>
/// Divides the specified instance by a scalar.
/// </summary>
@ -1083,9 +1144,8 @@ namespace OpenTK
/// <returns>Result of the division.</returns>
public static Vector2 operator /(Vector2 vec, float scale)
{
float mult = 1.0f / scale;
vec.X *= mult;
vec.Y *= mult;
vec.X /= scale;
vec.Y /= scale;
return vec;
}

View file

@ -541,7 +541,8 @@ namespace OpenTK
/// <param name="result">Result of the operation.</param>
public static void Divide(ref Vector2d vector, double scale, out Vector2d result)
{
Multiply(ref vector, 1 / scale, out result);
result.X = vector.X / scale;
result.Y = vector.Y / scale;
}
/// <summary>
@ -577,6 +578,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
[Obsolete("Use ComponentMin() instead.")]
public static Vector2d Min(Vector2d a, Vector2d b)
{
a.X = a.X < b.X ? a.X : b.X;
@ -590,6 +592,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
[Obsolete("Use ComponentMin() instead.")]
public static void Min(ref Vector2d a, ref Vector2d b, out Vector2d result)
{
result.X = a.X < b.X ? a.X : b.X;
@ -606,6 +609,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
[Obsolete("Use ComponentMax() instead.")]
public static Vector2d Max(Vector2d a, Vector2d b)
{
a.X = a.X > b.X ? a.X : b.X;
@ -619,6 +623,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
[Obsolete("Use ComponentMax() instead.")]
public static void Max(ref Vector2d a, ref Vector2d b, out Vector2d result)
{
result.X = a.X > b.X ? a.X : b.X;
@ -627,6 +632,122 @@ namespace OpenTK
#endregion
#region ComponentMin
/// <summary>
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
public static Vector2d ComponentMin(Vector2d a, Vector2d b)
{
a.X = a.X < b.X ? a.X : b.X;
a.Y = a.Y < b.Y ? a.Y : b.Y;
return a;
}
/// <summary>
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
public static void ComponentMin(ref Vector2d a, ref Vector2d b, out Vector2d result)
{
result.X = a.X < b.X ? a.X : b.X;
result.Y = a.Y < b.Y ? a.Y : b.Y;
}
#endregion
#region ComponentMax
/// <summary>
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
public static Vector2d ComponentMax(Vector2d a, Vector2d b)
{
a.X = a.X > b.X ? a.X : b.X;
a.Y = a.Y > b.Y ? a.Y : b.Y;
return a;
}
/// <summary>
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
public static void ComponentMax(ref Vector2d a, ref Vector2d b, out Vector2d result)
{
result.X = a.X > b.X ? a.X : b.X;
result.Y = a.Y > b.Y ? a.Y : b.Y;
}
#endregion
#region MagnitudeMin
/// <summary>
/// Returns the Vector2d with the minimum magnitude. If the magnitudes are equal, the second vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector2d</returns>
public static Vector2d MagnitudeMin(Vector2d left, Vector2d right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector2d with the minimum magnitude. If the magnitudes are equal, the second vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise minimum</param>
/// <returns>The minimum Vector2d</returns>
public static void MagnitudeMin(ref Vector2d left, ref Vector2d right, out Vector2d result)
{
result = left.LengthSquared < right.LengthSquared ? left : right;
}
#endregion
#region MagnitudeMax
/// <summary>
/// Returns the Vector2d with the minimum magnitude. If the magnitudes are equal, the first vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector2d</returns>
public static Vector2d MagnitudeMax(Vector2d left, Vector2d right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector2d with the maximum magnitude. If the magnitudes are equal, the first vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise maximum</param>
/// <returns>The maximum Vector2d</returns>
public static void MagnitudeMax(ref Vector2d left, ref Vector2d right, out Vector2d result)
{
result = left.LengthSquared >= right.LengthSquared ? left : right;
}
#endregion
#region Clamp
/// <summary>
@ -936,7 +1057,7 @@ namespace OpenTK
vec.Y *= scale.Y;
return vec;
}
/// <summary>
/// Divides an instance by a scalar.
/// </summary>
@ -945,9 +1066,8 @@ namespace OpenTK
/// <returns>The result of the operation.</returns>
public static Vector2d operator /(Vector2d vec, double f)
{
double mult = 1.0 / f;
vec.X *= mult;
vec.Y *= mult;
vec.X /= f;
vec.Y /= f;
return vec;
}

View file

@ -629,7 +629,9 @@ namespace OpenTK
/// <param name="result">Result of the operation.</param>
public static void Divide(ref Vector3 vector, float scale, out Vector3 result)
{
Multiply(ref vector, 1 / scale, out result);
result.X = vector.X / scale;
result.Y = vector.Y / scale;
result.Z = vector.Z / scale;
}
/// <summary>
@ -660,7 +662,7 @@ namespace OpenTK
#region ComponentMin
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -674,7 +676,7 @@ namespace OpenTK
}
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -691,7 +693,7 @@ namespace OpenTK
#region ComponentMax
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -705,7 +707,7 @@ namespace OpenTK
}
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -719,6 +721,64 @@ namespace OpenTK
#endregion
#region MagnitudeMin
/// <summary>
/// Returns the Vector3 with the minimum magnitude. If the magnitudes are equal, the second vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
public static Vector3 MagnitudeMin(Vector3 left, Vector3 right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector3 with the minimum magnitude. If the magnitudes are equal, the second vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise minimum</param>
/// <returns>The minimum Vector3</returns>
public static void MagnitudeMin(ref Vector3 left, ref Vector3 right, out Vector3 result)
{
result = left.LengthSquared < right.LengthSquared ? left : right;
}
#endregion
#region MagnitudeMax
/// <summary>
/// Returns the Vector3 with the maximum magnitude. If the magnitudes are equal, the first vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The maximum Vector3</returns>
public static Vector3 MagnitudeMax(Vector3 left, Vector3 right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector3 with the maximum magnitude. If the magnitudes are equal, the first vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise maximum</param>
/// <returns>The maximum Vector3</returns>
public static void MagnitudeMax(ref Vector3 left, ref Vector3 right, out Vector3 result)
{
result = left.LengthSquared >= right.LengthSquared ? left : right;
}
#endregion
#region Min
/// <summary>
@ -727,6 +787,7 @@ namespace OpenTK
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
[Obsolete("Use MagnitudeMin() instead.")]
public static Vector3 Min(Vector3 left, Vector3 right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
@ -742,6 +803,7 @@ namespace OpenTK
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
[Obsolete("Use MagnitudeMax() instead.")]
public static Vector3 Max(Vector3 left, Vector3 right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
@ -1270,10 +1332,10 @@ namespace OpenTK
{
Vector4 result;
result.X =
vector.X * worldViewProjection.M11 +
vector.Y * worldViewProjection.M21 +
vector.Z * worldViewProjection.M31 +
result.X =
vector.X * worldViewProjection.M11 +
vector.Y * worldViewProjection.M21 +
vector.Z * worldViewProjection.M31 +
worldViewProjection.M41;
result.Y =
@ -1574,10 +1636,9 @@ namespace OpenTK
/// <returns>The result of the calculation.</returns>
public static Vector3 operator /(Vector3 vec, float scale)
{
float mult = 1.0f / scale;
vec.X *= mult;
vec.Y *= mult;
vec.Z *= mult;
vec.X /= scale;
vec.Y /= scale;
vec.Z /= scale;
return vec;
}

View file

@ -627,7 +627,9 @@ namespace OpenTK
/// <param name="result">Result of the operation.</param>
public static void Divide(ref Vector3d vector, double scale, out Vector3d result)
{
Multiply(ref vector, 1 / scale, out result);
result.X = vector.X / scale;
result.Y = vector.Y / scale;
result.Z = vector.Z / scale;
}
/// <summary>
@ -658,7 +660,7 @@ namespace OpenTK
#region ComponentMin
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -672,7 +674,7 @@ namespace OpenTK
}
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -689,7 +691,7 @@ namespace OpenTK
#region ComponentMax
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -703,7 +705,7 @@ namespace OpenTK
}
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
@ -717,6 +719,60 @@ namespace OpenTK
#endregion
#region MagnitudeMin
/// <summary>
/// Returns the Vector3d with the minimum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3d</returns>
public static Vector3d MagnitudeMin(Vector3d left, Vector3d right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector3d with the minimum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise minimum</param>
/// <returns>The minimum Vector3d</returns>
public static void MagnitudeMin(ref Vector3d left, ref Vector3d right, out Vector3d result)
{
result = left.LengthSquared < right.LengthSquared ? left : right;
}
#endregion
#region MagnitudeMax
/// <summary>
/// Returns the Vector3d with the minimum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3d</returns>
public static Vector3d MagnitudeMax(Vector3d left, Vector3d right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector3d with the maximum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise maximum</param>
/// <returns>The maximum Vector3d</returns>
public static void MagnitudeMax(ref Vector3d left, ref Vector3d right, out Vector3d result)
{
result = left.LengthSquared >= right.LengthSquared ? left : right;
}
#endregion
#region Min
/// <summary>
@ -725,6 +781,7 @@ namespace OpenTK
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
[Obsolete("Use MagnitudeMin() instead.")]
public static Vector3d Min(Vector3d left, Vector3d right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
@ -740,6 +797,7 @@ namespace OpenTK
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
[Obsolete("Use MagnitudeMax() instead.")]
public static Vector3d Max(Vector3d left, Vector3d right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
@ -1372,7 +1430,7 @@ namespace OpenTK
vec.Z *= scale;
return vec;
}
/// <summary>
/// Component-wise multiplication between the specified instance by a scale vector.
/// </summary>
@ -1386,7 +1444,7 @@ namespace OpenTK
vec.Z *= scale.Z;
return vec;
}
/// <summary>
/// Divides an instance by a scalar.
/// </summary>
@ -1395,10 +1453,9 @@ namespace OpenTK
/// <returns>The result of the calculation.</returns>
public static Vector3d operator /(Vector3d vec, double scale)
{
double mult = 1 / scale;
vec.X *= mult;
vec.Y *= mult;
vec.Z *= mult;
vec.X /= scale;
vec.Y /= scale;
vec.Z /= scale;
return vec;
}

View file

@ -514,11 +514,10 @@ namespace OpenTK
/// <returns>Result of the division</returns>
public static Vector4 Div(Vector4 a, float f)
{
float mult = 1.0f / f;
a.X *= mult;
a.Y *= mult;
a.Z *= mult;
a.W *= mult;
a.X /= f;
a.Y /= f;
a.Z /= f;
a.W /= f;
return a;
}
@ -530,11 +529,10 @@ namespace OpenTK
/// <param name="result">Result of the division</param>
public static void Div(ref Vector4 a, float f, out Vector4 result)
{
float mult = 1.0f / f;
result.X = a.X * mult;
result.Y = a.Y * mult;
result.Z = a.Z * mult;
result.W = a.W * mult;
result.X = a.X / f;
result.Y = a.Y / f;
result.Z = a.Z / f;
result.W = a.W / f;
}
#endregion
@ -667,7 +665,10 @@ namespace OpenTK
/// <param name="result">Result of the operation.</param>
public static void Divide(ref Vector4 vector, float scale, out Vector4 result)
{
Multiply(ref vector, 1 / scale, out result);
result.X = vector.X / scale;
result.Y = vector.Y / scale;
result.Z = vector.Z / scale;
result.W = vector.W / scale;
}
/// <summary>
@ -703,6 +704,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
[Obsolete("Use ComponentMin() instead.")]
public static Vector4 Min(Vector4 a, Vector4 b)
{
a.X = a.X < b.X ? a.X : b.X;
@ -718,6 +720,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
[Obsolete("Use ComponentMin() instead.")]
public static void Min(ref Vector4 a, ref Vector4 b, out Vector4 result)
{
result.X = a.X < b.X ? a.X : b.X;
@ -736,6 +739,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
[Obsolete("Use ComponentMax() instead.")]
public static Vector4 Max(Vector4 a, Vector4 b)
{
a.X = a.X > b.X ? a.X : b.X;
@ -751,6 +755,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
[Obsolete("Use ComponentMax() instead.")]
public static void Max(ref Vector4 a, ref Vector4 b, out Vector4 result)
{
result.X = a.X > b.X ? a.X : b.X;
@ -761,6 +766,130 @@ namespace OpenTK
#endregion
#region ComponentMin
/// <summary>
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
public static Vector4 ComponentMin(Vector4 a, Vector4 b)
{
a.X = a.X < b.X ? a.X : b.X;
a.Y = a.Y < b.Y ? a.Y : b.Y;
a.Z = a.Z < b.Z ? a.Z : b.Z;
a.W = a.W < b.W ? a.W : b.W;
return a;
}
/// <summary>
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
public static void ComponentMin(ref Vector4 a, ref Vector4 b, out Vector4 result)
{
result.X = a.X < b.X ? a.X : b.X;
result.Y = a.Y < b.Y ? a.Y : b.Y;
result.Z = a.Z < b.Z ? a.Z : b.Z;
result.W = a.W < b.W ? a.W : b.W;
}
#endregion
#region ComponentMax
/// <summary>
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
public static Vector4 ComponentMax(Vector4 a, Vector4 b)
{
a.X = a.X > b.X ? a.X : b.X;
a.Y = a.Y > b.Y ? a.Y : b.Y;
a.Z = a.Z > b.Z ? a.Z : b.Z;
a.W = a.W > b.W ? a.W : b.W;
return a;
}
/// <summary>
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
public static void ComponentMax(ref Vector4 a, ref Vector4 b, out Vector4 result)
{
result.X = a.X > b.X ? a.X : b.X;
result.Y = a.Y > b.Y ? a.Y : b.Y;
result.Z = a.Z > b.Z ? a.Z : b.Z;
result.W = a.W > b.W ? a.W : b.W;
}
#endregion
#region MagnitudeMin
/// <summary>
/// Returns the Vector4 with the minimum magnitude. If the magnitudes are equal, the second vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector4</returns>
public static Vector4 MagnitudeMin(Vector4 left, Vector4 right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector4 with the minimum magnitude. If the magnitudes are equal, the second vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise minimum</param>
/// <returns>The minimum Vector4</returns>
public static void MagnitudeMin(ref Vector4 left, ref Vector4 right, out Vector4 result)
{
result = left.LengthSquared < right.LengthSquared ? left : right;
}
#endregion
#region MagnitudeMax
/// <summary>
/// Returns the Vector4 with the maximum magnitude. If the magnitudes are equal, the first vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The maximum Vector4</returns>
public static Vector4 MagnitudeMax(Vector4 left, Vector4 right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector4 with the maximum magnitude. If the magnitudes are equal, the first vector
/// is selected.
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise maximum</param>
/// <returns>The maximum Vector4</returns>
public static void MagnitudeMax(ref Vector4 left, ref Vector4 right, out Vector4 result)
{
result = left.LengthSquared >= right.LengthSquared ? left : right;
}
#endregion
#region Clamp
/// <summary>
@ -774,8 +903,8 @@ namespace OpenTK
{
vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
vec.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
vec.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
vec.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
vec.W = vec.W < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
return vec;
}
@ -790,8 +919,8 @@ namespace OpenTK
{
result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
result.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
result.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
result.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
result.W = vec.W < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
}
#endregion
@ -1514,7 +1643,7 @@ namespace OpenTK
vec.W *= scale;
return vec;
}
/// <summary>
/// Component-wise multiplication between the specified instance by a scale vector.
/// </summary>
@ -1577,11 +1706,10 @@ namespace OpenTK
/// <returns>The result of the calculation.</returns>
public static Vector4 operator /(Vector4 vec, float scale)
{
float mult = 1.0f / scale;
vec.X *= mult;
vec.Y *= mult;
vec.Z *= mult;
vec.W *= mult;
vec.X /= scale;
vec.Y /= scale;
vec.Z /= scale;
vec.W /= scale;
return vec;
}

View file

@ -175,7 +175,7 @@ namespace OpenTK
#endregion
#region Public Members
/// <summary>
/// Gets or sets the value at the index of the Vector.
/// </summary>
@ -669,7 +669,10 @@ namespace OpenTK
/// <param name="result">Result of the operation.</param>
public static void Divide(ref Vector4d vector, double scale, out Vector4d result)
{
Multiply(ref vector, 1 / scale, out result);
result.X = vector.X / scale;
result.Y = vector.Y / scale;
result.Z = vector.Z / scale;
result.W = vector.W / scale;
}
/// <summary>
@ -705,6 +708,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
[Obsolete("Use ComponentMin() instead.")]
public static Vector4d Min(Vector4d a, Vector4d b)
{
a.X = a.X < b.X ? a.X : b.X;
@ -720,6 +724,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
[Obsolete("Use ComponentMin() instead.")]
public static void Min(ref Vector4d a, ref Vector4d b, out Vector4d result)
{
result.X = a.X < b.X ? a.X : b.X;
@ -738,6 +743,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
[Obsolete("Use ComponentMax() instead.")]
public static Vector4d Max(Vector4d a, Vector4d b)
{
a.X = a.X > b.X ? a.X : b.X;
@ -753,6 +759,7 @@ namespace OpenTK
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
[Obsolete("Use ComponentMax() instead.")]
public static void Max(ref Vector4d a, ref Vector4d b, out Vector4d result)
{
result.X = a.X > b.X ? a.X : b.X;
@ -763,6 +770,126 @@ namespace OpenTK
#endregion
#region ComponentMin
/// <summary>
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
public static Vector4d ComponentMin(Vector4d a, Vector4d b)
{
a.X = a.X < b.X ? a.X : b.X;
a.Y = a.Y < b.Y ? a.Y : b.Y;
a.Z = a.Z < b.Z ? a.Z : b.Z;
a.W = a.W < b.W ? a.W : b.W;
return a;
}
/// <summary>
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
public static void ComponentMin(ref Vector4d a, ref Vector4d b, out Vector4d result)
{
result.X = a.X < b.X ? a.X : b.X;
result.Y = a.Y < b.Y ? a.Y : b.Y;
result.Z = a.Z < b.Z ? a.Z : b.Z;
result.W = a.W < b.W ? a.W : b.W;
}
#endregion
#region ComponentMax
/// <summary>
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
public static Vector4d ComponentMax(Vector4d a, Vector4d b)
{
a.X = a.X > b.X ? a.X : b.X;
a.Y = a.Y > b.Y ? a.Y : b.Y;
a.Z = a.Z > b.Z ? a.Z : b.Z;
a.W = a.W > b.W ? a.W : b.W;
return a;
}
/// <summary>
/// Returns a vector created from the largest of the corresponding components of the given vectors.
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
public static void ComponentMax(ref Vector4d a, ref Vector4d b, out Vector4d result)
{
result.X = a.X > b.X ? a.X : b.X;
result.Y = a.Y > b.Y ? a.Y : b.Y;
result.Z = a.Z > b.Z ? a.Z : b.Z;
result.W = a.W > b.W ? a.W : b.W;
}
#endregion
#region MagnitudeMin
/// <summary>
/// Returns the Vector4d with the minimum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector4d</returns>
public static Vector4d MagnitudeMin(Vector4d left, Vector4d right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector4d with the minimum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise minimum</param>
/// <returns>The minimum Vector4d</returns>
public static void MagnitudeMin(ref Vector4d left, ref Vector4d right, out Vector4d result)
{
result = left.LengthSquared < right.LengthSquared ? left : right;
}
#endregion
#region MagnitudeMax
/// <summary>
/// Returns the Vector4d with the minimum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector4d</returns>
public static Vector4d MagnitudeMax(Vector4d left, Vector4d right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
}
/// <summary>
/// Returns the Vector4d with the maximum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <param name="result">The magnitude-wise maximum</param>
/// <returns>The maximum Vector4d</returns>
public static void MagnitudeMax(ref Vector4d left, ref Vector4d right, out Vector4d result)
{
result = left.LengthSquared >= right.LengthSquared ? left : right;
}
#endregion
#region Clamp
/// <summary>
@ -1493,7 +1620,7 @@ namespace OpenTK
vec.W *= scale;
return vec;
}
/// <summary>
/// Component-wise multiplication between the specified instance by a scale vector.
/// </summary>
@ -1517,11 +1644,10 @@ namespace OpenTK
/// <returns>The result of the calculation.</returns>
public static Vector4d operator /(Vector4d vec, double scale)
{
double mult = 1 / scale;
vec.X *= mult;
vec.Y *= mult;
vec.Z *= mult;
vec.W *= mult;
vec.X /= scale;
vec.Y /= scale;
vec.Z /= scale;
vec.W /= scale;
return vec;
}

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,76 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open OpenTK
[<AutoOpen>]
module private AssertHelpers =
[<Literal>]
let private BitAccuracy = 16
[<Literal>]
let private EquivalenceTolerance = 0.00005f
let approxEq a b = MathHelper.ApproximatelyEquivalent(a, b, EquivalenceTolerance)
let approxEqDelta a b = MathHelper.ApproximatelyEqual(a,b,BitAccuracy)
let approxEqSingleEpsilon a b = MathHelper.ApproximatelyEqualEpsilon(a, b, 0.00001f)
let approxEqDoubleEpsilon a b = MathHelper.ApproximatelyEqualEpsilon(a, b, 0.00001)
let approxEqSingleEpsilonWithError (a, b, c : float32) = MathHelper.ApproximatelyEqualEpsilon(a, b, c)
let approxEqDoubleEpsilonWithError (a, b, c : float) = MathHelper.ApproximatelyEqualEpsilon(a, b, c)
let anyZero2 (a : Vector2) = (approxEq a.X 0.0f || approxEq a.Y 0.0f)
let anyZero3 (a : Vector3) = (approxEq a.X 0.0f || approxEq a.Y 0.0f || approxEq a.Z 0.0f)
let anyZero4 (a : Vector4) = (approxEq a.X 0.0f || approxEq a.Y 0.0f || approxEq a.Z 0.0f || approxEq a.W 0.0f)
/// We use a full type here instead of a module, as the overloading semantics are more suitable for our desired goal.
[<Sealed>]
type internal Assert =
static member ApproximatelyEquivalent(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 ApproximatelyEquivalent(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 ApproximatelyEquivalent(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 ApproximatelyEquivalent(a : float32,b : float32) =
if not <| approxEq a b then raise <| new Xunit.Sdk.EqualException(a,b)
static member ApproximatelyEqualEpsilon(a : float32, b : float32) =
if not <| approxEqSingleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b)
static member ApproximatelyEqualEpsilon(a : float32, b : float32, c : float32) =
if not <| approxEqSingleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b)
static member ApproximatelyEqualEpsilon(a : float, b : float) =
if not <| approxEqDoubleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b)
static member ApproximatelyEqualEpsilon(a : float, b : float, c : float) =
if not <| approxEqDoubleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b)
static member NotApproximatelyEqualEpsilon(a : float32, b : float32) =
if approxEqSingleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b)
static member NotApproximatelyEqualEpsilon(a : float32, b : float32, c : float32) =
if approxEqSingleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b)
static member NotApproximatelyEqualEpsilon(a : float, b : float) =
if approxEqDoubleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b)
static member NotApproximatelyEqualEpsilon(a : float, b : float, c : float) =
if approxEqDoubleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b)
static member ThrowsIndexExn(f:unit -> unit) = Assert.Throws<IndexOutOfRangeException>(f) |> ignore

View file

@ -0,0 +1,80 @@
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
|> Gen.filter (fun v -> not <| (Single.IsNaN v.Length || Single.IsInfinity v.Length ))
|> Arb.fromGen
let vec3 =
singleArb
|> Gen.three
|> Gen.map Vector3
|> Gen.filter (fun v -> not <| (Single.IsNaN v.Length || Single.IsInfinity v.Length ))
|> Arb.fromGen
let vec4 =
singleArb
|> Gen.four
|> Gen.map Vector4
|> Gen.filter (fun v -> not <| (Single.IsNaN v.Length || Single.IsInfinity v.Length ))
|> 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,352 @@
namespace OpenTK.Tests
open Xunit
open FsCheck
open FsCheck.Xunit
open System
open OpenTK
module MathHelper =
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``ApproximatelyEqual (delta)`` =
/// 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))
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``ApproximatelyEqual (single-precision epsilon)`` =
//
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for large positive values``() =
Assert.ApproximatelyEqualEpsilon(1000000.0f, 1000001.0f);
Assert.ApproximatelyEqualEpsilon(1000001.0f, 1000000.0f);
Assert.NotApproximatelyEqualEpsilon(10000.0f, 10001.0f);
Assert.NotApproximatelyEqualEpsilon(10001.0f, 10000.0f);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for large negative values``() =
Assert.ApproximatelyEqualEpsilon(-1000000.0f, -1000001.0f);
Assert.ApproximatelyEqualEpsilon(-1000001.0f, -1000000.0f);
Assert.NotApproximatelyEqualEpsilon(-10000.0f, -10001.0f);
Assert.NotApproximatelyEqualEpsilon(-10001.0f, -10000.0f);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for positive values around 1``() =
Assert.ApproximatelyEqualEpsilon(1.0000001f, 1.0000002f);
Assert.ApproximatelyEqualEpsilon(1.0000002f, 1.0000001f);
Assert.NotApproximatelyEqualEpsilon(1.0002f, 1.0001f);
Assert.NotApproximatelyEqualEpsilon(1.0001f, 1.0002f);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for negative values around -1``() =
Assert.ApproximatelyEqualEpsilon(-1.000001f, -1.000002f);
Assert.ApproximatelyEqualEpsilon(-1.000002f, -1.000001f);
Assert.NotApproximatelyEqualEpsilon(-1.0001f, -1.0002f);
Assert.NotApproximatelyEqualEpsilon(-1.0002f, -1.0001f);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for values between 1 and 0``() =
Assert.ApproximatelyEqualEpsilon(0.000000001000001f, 0.000000001000002f);
Assert.ApproximatelyEqualEpsilon(0.000000001000002f, 0.000000001000001f);
Assert.NotApproximatelyEqualEpsilon(0.000000000001002f, 0.000000000001001f);
Assert.NotApproximatelyEqualEpsilon(0.000000000001001f, 0.000000000001002f);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for values between -1 and 0``() =
Assert.ApproximatelyEqualEpsilon(-0.000000001000001f, -0.000000001000002f);
Assert.ApproximatelyEqualEpsilon(-0.000000001000002f, -0.000000001000001f);
Assert.NotApproximatelyEqualEpsilon(-0.000000000001002f, -0.000000000001001f);
Assert.NotApproximatelyEqualEpsilon(-0.000000000001001f, -0.000000000001002f);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for comparisons involving 0``() =
Assert.ApproximatelyEqualEpsilon(0.0f, 0.0f);
Assert.ApproximatelyEqualEpsilon(0.0f, -0.0f);
Assert.ApproximatelyEqualEpsilon(-0.0f, -0.0f);
Assert.NotApproximatelyEqualEpsilon(0.00000001f, 0.0f);
Assert.NotApproximatelyEqualEpsilon(0.0f, 0.00000001f);
Assert.NotApproximatelyEqualEpsilon(-0.00000001f, 0.0f);
Assert.NotApproximatelyEqualEpsilon(0.0f, -0.00000001f);
Assert.ApproximatelyEqualEpsilon(0.0f, 1e-40f, 0.01f);
Assert.ApproximatelyEqualEpsilon(1e-40f, 0.0f, 0.01f);
Assert.NotApproximatelyEqualEpsilon(1e-40f, 0.0f, 0.000001f);
Assert.NotApproximatelyEqualEpsilon(0.0f, 1e-40f, 0.000001f);
Assert.ApproximatelyEqualEpsilon(0.0f, -1e-40f, 0.1f);
Assert.ApproximatelyEqualEpsilon(-1e-40f, 0.0f, 0.1f);
Assert.NotApproximatelyEqualEpsilon(-1e-40f, 0.0f, 0.00000001f);
Assert.NotApproximatelyEqualEpsilon(0.0f, -1e-40f, 0.00000001f);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for extreme values with overflow potential``() =
Assert.ApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.MaxValue);
Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, -System.Single.MaxValue);
Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.MaxValue);
Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.MaxValue / 2.0f);
Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, -System.Single.MaxValue / 2.0f);
Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.MaxValue / 2.0f);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for values involving infinities``() =
Assert.ApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.PositiveInfinity);
Assert.ApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.NegativeInfinity);
Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.PositiveInfinity);
Assert.NotApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.MaxValue);
Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, -System.Single.MaxValue);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for values involving NaN``() =
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, 0.0f);
Assert.NotApproximatelyEqualEpsilon(-0.0f, System.Single.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -0.0f);
Assert.NotApproximatelyEqualEpsilon(0.0f, System.Single.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.PositiveInfinity);
Assert.NotApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.NegativeInfinity);
Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.MaxValue);
Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -System.Single.MaxValue);
Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.Epsilon);
Assert.NotApproximatelyEqualEpsilon(System.Single.Epsilon, System.Single.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -System.Single.Epsilon);
Assert.NotApproximatelyEqualEpsilon(-System.Single.Epsilon, System.Single.NaN);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for values on opposite sides of 0``() =
Assert.NotApproximatelyEqualEpsilon(1.000000001f, -1.0f);
Assert.NotApproximatelyEqualEpsilon(-1.0f, 1.000000001f);
Assert.NotApproximatelyEqualEpsilon(-1.000000001f, 1.0f);
Assert.NotApproximatelyEqualEpsilon(1.0f, -1.000000001f);
Assert.ApproximatelyEqualEpsilon(10.0f * System.Single.Epsilon, 10.0f * -System.Single.Epsilon);
Assert.NotApproximatelyEqualEpsilon(10000.0f * System.Single.Epsilon, 10000.0f * -System.Single.Epsilon);
[<Fact>]
let ``ApproximatelyEqual (single precision) is correct for values very close to 0``() =
Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, System.Single.Epsilon);
Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, -System.Single.Epsilon);
Assert.ApproximatelyEqualEpsilon(-System.Single.Epsilon, System.Single.Epsilon);
Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, 0.0f);
Assert.ApproximatelyEqualEpsilon(0.0f, System.Single.Epsilon);
Assert.ApproximatelyEqualEpsilon(-System.Single.Epsilon, 0.0f);
Assert.ApproximatelyEqualEpsilon(0.0f, -System.Single.Epsilon);
Assert.NotApproximatelyEqualEpsilon(0.000000001f, -System.Single.Epsilon);
Assert.NotApproximatelyEqualEpsilon(0.000000001f, System.Single.Epsilon);
Assert.NotApproximatelyEqualEpsilon(System.Single.Epsilon, 0.000000001f);
Assert.NotApproximatelyEqualEpsilon(-System.Single.Epsilon, 0.000000001f);
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``ApproximatelyEqual (double-precision epsilon)`` =
//
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for large positive values``() =
Assert.ApproximatelyEqualEpsilon(1000000.0, 1000001.0);
Assert.ApproximatelyEqualEpsilon(1000001.0, 1000000.0);
Assert.NotApproximatelyEqualEpsilon(10000.0, 10001.0);
Assert.NotApproximatelyEqualEpsilon(10001.0, 10000.0);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for large negative values``() =
Assert.ApproximatelyEqualEpsilon(-1000000.0, -1000001.0);
Assert.ApproximatelyEqualEpsilon(-1000001.0, -1000000.0);
Assert.NotApproximatelyEqualEpsilon(-10000.0, -10001.0);
Assert.NotApproximatelyEqualEpsilon(-10001.0, -10000.0);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for positive values around 1``() =
Assert.ApproximatelyEqualEpsilon(1.0000001, 1.0000002);
Assert.ApproximatelyEqualEpsilon(1.0000002, 1.0000001);
Assert.NotApproximatelyEqualEpsilon(1.0002, 1.0001);
Assert.NotApproximatelyEqualEpsilon(1.0001, 1.0002);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for negative values around -1``() =
Assert.ApproximatelyEqualEpsilon(-1.000001, -1.000002);
Assert.ApproximatelyEqualEpsilon(-1.000002, -1.000001);
Assert.NotApproximatelyEqualEpsilon(-1.0001, -1.0002);
Assert.NotApproximatelyEqualEpsilon(-1.0002, -1.0001);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for values between 1 and 0``() =
Assert.ApproximatelyEqualEpsilon(0.000000001000001, 0.000000001000002);
Assert.ApproximatelyEqualEpsilon(0.000000001000002, 0.000000001000001);
Assert.NotApproximatelyEqualEpsilon(0.000000000001002, 0.000000000001001);
Assert.NotApproximatelyEqualEpsilon(0.000000000001001, 0.000000000001002);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for values between -1 and 0``() =
Assert.ApproximatelyEqualEpsilon(-0.000000001000001, -0.000000001000002);
Assert.ApproximatelyEqualEpsilon(-0.000000001000002, -0.000000001000001);
Assert.NotApproximatelyEqualEpsilon(-0.000000000001002, -0.000000000001001);
Assert.NotApproximatelyEqualEpsilon(-0.000000000001001, -0.000000000001002);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for comparisons involving 0``() =
Assert.ApproximatelyEqualEpsilon(0.0, 0.0);
Assert.ApproximatelyEqualEpsilon(0.0, -0.0);
Assert.ApproximatelyEqualEpsilon(-0.0, -0.0);
Assert.NotApproximatelyEqualEpsilon(0.00000001, 0.0);
Assert.NotApproximatelyEqualEpsilon(0.0, 0.00000001);
Assert.NotApproximatelyEqualEpsilon(-0.00000001, 0.0);
Assert.NotApproximatelyEqualEpsilon(0.0, -0.00000001);
Assert.ApproximatelyEqualEpsilon(0.0, 1e-310, 0.01);
Assert.ApproximatelyEqualEpsilon(1e-310, 0.0, 0.01);
Assert.NotApproximatelyEqualEpsilon(1e-310, 0.0, 0.000001);
Assert.NotApproximatelyEqualEpsilon(0.0, 1e-310, 0.000001);
Assert.ApproximatelyEqualEpsilon(0.0, -1e-310, 0.1);
Assert.ApproximatelyEqualEpsilon(-1e-310, 0.0, 0.1);
Assert.NotApproximatelyEqualEpsilon(-1e-310, 0.0, 0.00000001);
Assert.NotApproximatelyEqualEpsilon(0.0, -1e-310, 0.00000001);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for extreme values with overflow potential``() =
Assert.ApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.MaxValue);
Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, -System.Double.MaxValue);
Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.MaxValue);
Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.MaxValue / 2.0);
Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, -System.Double.MaxValue / 2.0);
Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.MaxValue / 2.0);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for values involving infinities``() =
Assert.ApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.PositiveInfinity);
Assert.ApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.NegativeInfinity);
Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.PositiveInfinity);
Assert.NotApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.MaxValue);
Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, -System.Double.MaxValue);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for values involving NaN``() =
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, 0.0);
Assert.NotApproximatelyEqualEpsilon(-0.0, System.Double.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -0.0);
Assert.NotApproximatelyEqualEpsilon(0.0, System.Double.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.PositiveInfinity);
Assert.NotApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.NegativeInfinity);
Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.MaxValue);
Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -System.Double.MaxValue);
Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.Epsilon);
Assert.NotApproximatelyEqualEpsilon(System.Double.Epsilon, System.Double.NaN);
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -System.Double.Epsilon);
Assert.NotApproximatelyEqualEpsilon(-System.Double.Epsilon, System.Double.NaN);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for values on opposite sides of 0``() =
Assert.NotApproximatelyEqualEpsilon(1.000000001, -1.0);
Assert.NotApproximatelyEqualEpsilon(-1.0, 1.000000001);
Assert.NotApproximatelyEqualEpsilon(-1.000000001, 1.0);
Assert.NotApproximatelyEqualEpsilon(1.0, -1.000000001);
Assert.ApproximatelyEqualEpsilon(10.0 * System.Double.Epsilon, 10.0 * -System.Double.Epsilon);
Assert.NotApproximatelyEqualEpsilon(100000000000.0 * System.Double.Epsilon, 100000000000.0 * -System.Double.Epsilon);
[<Fact>]
let ``ApproximatelyEqual (double precision) is correct for values very close to 0``() =
Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, System.Double.Epsilon);
Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, -System.Double.Epsilon);
Assert.ApproximatelyEqualEpsilon(-System.Double.Epsilon, System.Double.Epsilon);
Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, 0.0);
Assert.ApproximatelyEqualEpsilon(0.0, System.Double.Epsilon);
Assert.ApproximatelyEqualEpsilon(-System.Double.Epsilon, 0.0);
Assert.ApproximatelyEqualEpsilon(0.0, -System.Double.Epsilon);
Assert.NotApproximatelyEqualEpsilon(0.000000001, -System.Double.Epsilon);
Assert.NotApproximatelyEqualEpsilon(0.000000001, System.Double.Epsilon);
Assert.NotApproximatelyEqualEpsilon(System.Double.Epsilon, 0.000000001);
Assert.NotApproximatelyEqualEpsilon(-System.Double.Epsilon, 0.000000001);
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``ApproximatelyEquivalent (tolerance diff)`` =
[<Fact>]
let ``ApproximatelyEquivalent correctly approximates equivalence where the difference falls below the tolerance``() =
let a = 0.0001f
let b = 0.00019f
Assert.NotEqual(a,b)
Assert.True(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
[<Fact>]
let ``ApproximatelyEquivalent correctly approximates equivalence where the difference is the tolerance``() =
let a = 0.0001f
let b = 0.0002f
Assert.NotEqual(a,b)
Assert.True(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
[<Fact>]
let ``ApproximatelyEquivalent correctly approximates inequivalence where the difference exceeds the tolerance``() =
let a = 0.0001f
let b = 0.00021f
Assert.NotEqual(a,b)
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
[<Fact>]
let ``ApproximatelyEquivalent reports very different values as non-equal even with a high tolerance``() =
let a = 3.0f
let b = 1.0f
Assert.NotEqual(a,b)
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 1.0f))
[<Fact>]
let ``ApproximatelyEquivalent works with single zero value``() =
let a = 1.0f
let b = 0.0f
Assert.NotEqual(a,b)
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
[<Fact>]
let ``ApproximatelyEquivalent works with both zero values``() =
let a = 0.0f
let b = 0.0f
Assert.Equal(a,b)
Assert.True(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))

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,396 @@
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.ThrowsIndexExn
(fun() -> a.[1, -2] <- x) |> Assert.ThrowsIndexExn
(fun() -> a.[-1, -2] <- x) |> Assert.ThrowsIndexExn
[<Property>]
let ``Indexed get operator throws exception for negative indices`` (a : Matrix4) =
(fun() -> a.[-1, 2] |> ignore) |> Assert.ThrowsIndexExn
(fun() -> a.[1, -2] |> ignore) |> Assert.ThrowsIndexExn
(fun() -> a.[-1, -2] |> ignore) |> Assert.ThrowsIndexExn
[<Property>]
let ``Indexed set operator throws exception for large indices`` (a : Matrix4, x : float32) =
let mutable b = a
(fun() -> b.[5, 2] <- x) |> Assert.ThrowsIndexExn
(fun() -> b.[1, 6] <- x) |> Assert.ThrowsIndexExn
(fun() -> b.[7, 12] <- x) |> Assert.ThrowsIndexExn
[<Property>]
let ``Indexed get operator throws exception for large indices`` (a : Matrix4) =
(fun() -> a.[5, 2] |> ignore) |> Assert.ThrowsIndexExn
(fun() -> a.[1, 6] |> ignore) |> Assert.ThrowsIndexExn
(fun() -> a.[7, 12] |> ignore) |> Assert.ThrowsIndexExn
[<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,603 @@
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.ThrowsIndexExn
[<Property>]
let ``Indexed get operator throws exception for negative indices`` (x, y) =
let mutable v = Vector2(x, y)
(fun() -> v.[-1] |> ignore) |> Assert.ThrowsIndexExn
[<Property>]
let ``Indexed set operator throws exception for large indices`` (x, y) =
let mutable v = Vector2(x, y)
(fun() -> v.[2] <- x) |> Assert.ThrowsIndexExn
[<Property>]
let ``Indexed get operator throws exception for large indices`` (x, y) =
let mutable v = Vector2(x, y)
(fun() -> v.[2] |> ignore) |> Assert.ThrowsIndexExn
[<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.ApproximatelyEquivalent(a.X + b.X,c.X)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(v1, sum)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module Division =
//
[<Property>]
let ``Vector2-float division is the same as component-float division`` (a : Vector2, f : float32) =
if not (approxEq f 0.0f) then
let r = a / f
Assert.ApproximatelyEquivalent(a.X / f,r.X)
Assert.ApproximatelyEquivalent(a.Y / f,r.Y)
[<Property>]
let ``Static Vector2-Vector2 division method is the same as component division`` (a : Vector2, b : Vector2) =
if not (anyZero2 a || anyZero2 b) then
let v1 = Vector2(a.X / b.X, a.Y / b.Y)
let sum = Vector2.Divide(a, b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector2-Vector2 divison method by reference `` (a : Vector2, b : Vector2) =
if not (anyZero2 a || anyZero2 b) then
let v1 = Vector2(a.X / b.X, a.Y / b.Y)
let sum = Vector2.Divide(ref a, ref b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector2-scalar division method is the same as component division`` (a : Vector2, b : float32) =
if not (approxEq b 0.0f) then
let v1 = Vector2(a.X / b, a.Y / b)
let sum = Vector2.Divide(a, b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector2-scalar divison method by reference is the same as component division`` (a : Vector2, b : float32) =
if not (approxEq b 0.0f) then
let v1 = Vector2(a.X / b, a.Y / b)
let sum = Vector2.Divide(ref a, b)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(v.X / l, norm.X)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(v.X / l, norm.X)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(v.X * scale, norm.X)
Assert.ApproximatelyEquivalent(v.Y * scale, norm.Y)
[<Property>]
let ``Normalization by reference is the same as division by magnitude`` (a : Vector2) =
// Zero-length vectors can't be normalized
if not (approxEq a.Length 0.0f) then
let norm = a / a.Length
let vRes = Vector2.Normalize(ref a)
Assert.ApproximatelyEquivalent(norm, vRes)
[<Property>]
let ``Normalization is the same as division by magnitude`` (a : Vector2) =
// Zero-length vectors can't be normalized
if not (approxEq a.Length 0.0f) then
let norm = a / a.Length
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(norm, Vector2.NormalizeFast(a));
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Magnitude min and max`` =
//
[<Property>]
let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector2, v2: Vector2) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector2.MagnitudeMin(v1, v2)
if vMin = v1 then
let v1ShorterThanv2 = l1 < l2
Assert.True(v1ShorterThanv2)
else
let v2ShorterThanOrEqualTov1 = l2 <= l1
Assert.True(v2ShorterThanOrEqualTov1)
[<Property>]
let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector2, v2: Vector2) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector2.MagnitudeMax(v1, v2)
if vMin = v1 then
let v1LongerThanOrEqualTov2 = l1 >= l2
Assert.True(v1LongerThanOrEqualTov2)
else
let v2LongerThanv1 = l2 > l1
Assert.True(v2LongerThanv1)
[<Property>]
let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector2, v2: Vector2) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector2.MagnitudeMin(ref v1, ref v2)
if vMin = v1 then
let v1ShorterThanv2 = l1 < l2
Assert.True(v1ShorterThanv2)
else
let v2ShorterThanOrEqualTov1 = l2 <= l1
Assert.True(v2ShorterThanOrEqualTov1)
[<Property>]
let ``MagnitudeMax by reference selects the vector with equal greater magnitude given two vectors`` (v1 : Vector2, v2: Vector2) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector2.MagnitudeMax(ref v1, ref v2)
if vMin = v1 then
let v1LongerThanOrEqualTov2 = l1 >= l2
Assert.True(v1LongerThanOrEqualTov2)
else
let v2LongerThanv1 = l2 > l1
Assert.True(v2LongerThanv1)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Component min and max`` =
//
[<Property>]
let ``ComponentMin creates a new vector from the smallest components of given vectors`` (v1 : Vector2, v2: Vector2) =
let vMin = Vector2.ComponentMin(v1, v2)
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
[<Property>]
let ``ComponentMax creates a new vector from the greatest components of given vectors`` (v1 : Vector2, v2: Vector2) =
let vMax = Vector2.ComponentMax(v1, v2)
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
Assert.True(isComponentLargest vMax.X v1.X v2.X)
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
[<Property>]
let ``ComponentMin by reference creates a new vector from the smallest components of given vectors`` (v1 : Vector2, v2: Vector2) =
let vMin = Vector2.ComponentMin(ref v1, ref v2)
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
[<Property>]
let ``ComponentMax by reference creates a new vector from the greatest components of given vectors`` (v1 : Vector2, v2: Vector2) =
let vMax = Vector2.ComponentMax(ref v1, ref v2)
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
Assert.True(isComponentLargest vMax.X v1.X v2.X)
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
[<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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(transformedVector, Vector2.Transform(ref v, ref q))
[<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,754 @@
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.ThrowsIndexExn
[<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.ThrowsIndexExn
[<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.ThrowsIndexExn
[<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.ThrowsIndexExn
[<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.ApproximatelyEquivalent(v.X / l, norm.X)
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(v.X / l, norm.X)
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(v.X * scale, norm.X)
Assert.ApproximatelyEquivalent(v.Y * scale, norm.Y)
Assert.ApproximatelyEquivalent(v.Z * scale, norm.Z)
[<Property>]
let ``Normalization by reference is the same as division by magnitude`` (a : Vector3) =
// Zero-length vectors can't be normalized
if not (approxEq a.Length 0.0f) then
let norm = a / a.Length
let vRes = Vector3.Normalize(ref a)
Assert.ApproximatelyEquivalent(norm, vRes)
[<Property>]
let ``Normalization is the same as division by magnitude`` (a : Vector3) =
// Zero-length vectors can't be normalized
if not (approxEq a.Length 0.0f) then
let norm = a / a.Length
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(a.X + b.X,c.X)
Assert.ApproximatelyEquivalent(a.Y + b.Y,c.Y)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(a.X / f,r.X)
Assert.ApproximatelyEquivalent(a.Y / f,r.Y)
Assert.ApproximatelyEquivalent(a.Z / f,r.Z)
[<Property>]
let ``Static Vector3-Vector3 division method is the same as component division`` (a : Vector3, b : Vector3) =
if not (anyZero3 a || anyZero3 b) then
let v1 = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z)
let sum = Vector3.Divide(a, b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector3-Vector3 divison method by reference is the same as component division`` (a : Vector3, b : Vector3) =
if not (anyZero3 a || anyZero3 b) then
let v1 = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z)
let sum = Vector3.Divide(ref a, ref b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector3-scalar division method is the same as component division`` (a : Vector3, b : float32) =
if not (approxEq b 0.0f) then // we don't support diving by zero.
let v1 = Vector3(a.X / b, a.Y / b, a.Z / b)
let sum = Vector3.Divide(a, b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector3-scalar divison method by reference is the same as component division`` (a : Vector3, b : float32) =
if not (approxEq b 0.0f) then // we don't support diving by zero.
let v1 = Vector3(a.X / b, a.Y / b, a.Z / b)
let sum = Vector3.Divide(ref a, b)
Assert.ApproximatelyEquivalent(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 ``Magnitude min and max`` =
//
[<Property>]
let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector3, v2: Vector3) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector3.MagnitudeMin(v1, v2)
if vMin = v1 then
let v1ShorterThanv2 = l1 < l2
Assert.True(v1ShorterThanv2)
else
let v2ShorterThanOrEqualTov1 = l2 <= l1
Assert.True(v2ShorterThanOrEqualTov1)
[<Property>]
let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector3, v2: Vector3) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector3.MagnitudeMax(v1, v2)
if vMin = v1 then
let v1LongerThanOrEqualTov2 = l1 >= l2
Assert.True(v1LongerThanOrEqualTov2)
else
let v2LongerThanv1 = l2 > l1
Assert.True(v2LongerThanv1)
[<Property>]
let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector3, v2: Vector3) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector3.MagnitudeMin(ref v1, ref v2)
if vMin = v1 then
let v1ShorterThanv2 = l1 < l2
Assert.True(v1ShorterThanv2)
else
let v2ShorterThanOrEqualTov1 = l2 <= l1
Assert.True(v2ShorterThanOrEqualTov1)
[<Property>]
let ``MagnitudeMax by reference selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector3, v2: Vector3) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector3.MagnitudeMax(ref v1, ref v2)
if vMin = v1 then
let v1LongerThanOrEqualTov2 = l1 >= l2
Assert.True(v1LongerThanOrEqualTov2)
else
let v2LongerThanv1 = l2 > l1
Assert.True(v2LongerThanv1)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Component min and max`` =
//
[<Property>]
let ``ComponentMin creates a new vector from the smallest components of given vectors`` (v1 : Vector3, v2: Vector3) =
let vMin = Vector3.ComponentMin(v1, v2)
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
Assert.True(isComponentSmallest vMin.Z v1.Z v2.Z)
[<Property>]
let ``ComponentMax creates a new vector from the greatest components of given vectors`` (v1 : Vector3, v2: Vector3) =
let vMax = Vector3.ComponentMax(v1, v2)
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
Assert.True(isComponentLargest vMax.X v1.X v2.X)
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
Assert.True(isComponentLargest vMax.Z v1.Z v2.Z)
[<Property>]
let ``ComponentMin by reference creates a new vector from the smallest components of given vectors`` (v1 : Vector3, v2: Vector3) =
let vMin = Vector3.ComponentMin(ref v1, ref v2)
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
Assert.True(isComponentSmallest vMin.Z v1.Z v2.Z)
[<Property>]
let ``ComponentMax by reference creates a new vector from the greatest components of given vectors`` (v1 : Vector3, v2: Vector3) =
let vMax = Vector3.ComponentMax(ref v1, ref v2)
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
Assert.True(isComponentLargest vMax.X v1.X v2.X)
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
Assert.True(isComponentLargest vMax.Z v1.Z v2.Z)
[<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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(v, transformedVector)
Assert.ApproximatelyEquivalent(v, Vector3.Transform(v, q))
Assert.ApproximatelyEquivalent(transformedVector, Vector3.Transform(v, q))

View file

@ -0,0 +1,923 @@
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.ThrowsIndexExn
[<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.ThrowsIndexExn
[<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.ThrowsIndexExn
[<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.ThrowsIndexExn
[<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
// Zero-length vectors can't be normalized
if not (approxEq l 0.0f) then
let norm = v.Normalized()
Assert.ApproximatelyEquivalent(v.X / l, norm.X)
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
Assert.ApproximatelyEquivalent(v.Z / l, norm.Z)
Assert.ApproximatelyEquivalent(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
// Zero-length vectors can't be normalized
if not (approxEq l 0.0f) then
let norm = Vector4(x, y, z, w)
norm.Normalize()
Assert.ApproximatelyEquivalent(v.X / l, norm.X)
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
Assert.ApproximatelyEquivalent(v.Z / l, norm.Z)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(v.X * scale, norm.X)
Assert.ApproximatelyEquivalent(v.Y * scale, norm.Y)
Assert.ApproximatelyEquivalent(v.Z * scale, norm.Z)
Assert.ApproximatelyEquivalent(v.W * scale, norm.W)
[<Property>]
let ``Normalization by reference is the same as division by magnitude`` (a : Vector4) =
// Zero-length vectors can't be normalized
if not (approxEq a.Length 0.0f) then
let norm = a / a.Length
let vRes = Vector4.Normalize(ref a)
Assert.ApproximatelyEquivalent(norm, vRes)
[<Property>]
let ``Normalization is the same as division by magnitude`` (a : Vector4) =
// Zero-length vectors can't be normalized
if not (approxEq a.Length 0.0f) then
let norm = a / a.Length
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(a.X + b.X,c.X)
Assert.ApproximatelyEquivalent(a.Y + b.Y,c.Y)
Assert.ApproximatelyEquivalent(a.Z + b.Z,c.Z)
Assert.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(a.X / f, r.X)
Assert.ApproximatelyEquivalent(a.Y / f, r.Y)
Assert.ApproximatelyEquivalent(a.Z / f, r.Z)
Assert.ApproximatelyEquivalent(a.W / f, r.W)
[<Property>]
let ``Static Vector4-Vector4 division method is the same as component division`` (a : Vector4, b : Vector4) =
if not (anyZero4 a || anyZero4 b) then
let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W)
let sum = Vector4.Divide(a, b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector4-Vector4 divison method by reference is the same as component division`` (a : Vector4, b : Vector4) =
if not (anyZero4 a || anyZero4 b) then
let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W)
let sum = Vector4.Divide(ref a, ref b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector4-scalar division method is the same as component division`` (a : Vector4, b : float32) =
if not (approxEq b 0.0f) then // we don't support diving by zero.
let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b)
let sum = Vector4.Divide(a, b)
Assert.ApproximatelyEquivalent(v1, sum)
[<Property>]
let ``Static Vector4-scalar divison method by reference is the same as component division`` (a : Vector4, b : float32) =
if not (approxEq b 0.0f) then // we don't support diving by zero.
let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b)
let sum = Vector4.Divide(ref a, b)
Assert.ApproximatelyEquivalent(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 ``Magnitude min and max`` =
//
[<Property>]
let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector4, v2: Vector4) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector4.MagnitudeMin(v1, v2)
if vMin = v1 then
let v1ShorterThanv2 = l1 < l2
Assert.True(v1ShorterThanv2)
else
let v2ShorterThanOrEqualTov1 = l2 <= l1
Assert.True(v2ShorterThanOrEqualTov1)
[<Property>]
let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector4, v2: Vector4) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector4.MagnitudeMax(v1, v2)
if vMin = v1 then
let v1LongerThanOrEqualTov2 = l1 >= l2
Assert.True(v1LongerThanOrEqualTov2)
else
let v2LongerThanv1 = l2 > l1
Assert.True(v2LongerThanv1)
[<Property>]
let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector4, v2: Vector4) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector4.MagnitudeMin(ref v1, ref v2)
if vMin = v1 then
let v1ShorterThanv2 = l1 < l2
Assert.True(v1ShorterThanv2)
else
let v2ShorterThanOrEqualTov1 = l2 <= l1
Assert.True(v2ShorterThanOrEqualTov1)
[<Property>]
let ``MagnitudeMax by reference selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector4, v2: Vector4) =
// Results do not matter for equal vectors
if not (v1 = v2) then
let l1 = v1.LengthSquared
let l2 = v2.LengthSquared
let vMin = Vector4.MagnitudeMax(ref v1, ref v2)
if vMin = v1 then
let v1LongerThanOrEqualTov2 = l1 >= l2
Assert.True(v1LongerThanOrEqualTov2)
else
let v2LongerThanv1 = l2 > l1
Assert.True(v2LongerThanv1)
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
module ``Component min and max`` =
//
[<Property>]
let ``ComponentMin creates a new vector from the smallest components of given vectors`` (v1 : Vector4, v2: Vector4) =
let vMin = Vector4.ComponentMin(v1, v2)
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
Assert.True(isComponentSmallest vMin.Z v1.Z v2.Z)
Assert.True(isComponentSmallest vMin.W v1.W v2.W)
[<Property>]
let ``ComponentMax creates a new vector from the greatest components of given vectors`` (v1 : Vector4, v2: Vector4) =
let vMax = Vector4.ComponentMax(v1, v2)
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
Assert.True(isComponentLargest vMax.X v1.X v2.X)
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
Assert.True(isComponentLargest vMax.Z v1.Z v2.Z)
Assert.True(isComponentLargest vMax.W v1.W v2.W)
[<Property>]
let ``ComponentMin by reference creates a new vector from the smallest components of given vectors`` (v1 : Vector4, v2: Vector4) =
let vMin = Vector4.ComponentMin(ref v1, ref v2)
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
Assert.True(isComponentSmallest vMin.Z v1.Z v2.Z)
Assert.True(isComponentSmallest vMin.W v1.W v2.W)
[<Property>]
let ``ComponentMax by reference creates a new vector from the greatest components of given vectors`` (v1 : Vector4, v2: Vector4) =
let vMax = Vector4.ComponentMax(ref v1, ref v2)
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
Assert.True(isComponentLargest vMax.X v1.X v2.X)
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
Assert.True(isComponentLargest vMax.Z v1.Z v2.Z)
Assert.True(isComponentLargest vMax.W v1.W v2.W)
[<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 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
let res = Vector4.Clamp(w, a, b)
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 between corresponding components`` (a : Vector4, b : Vector4, w : Vector4) =
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
let res = Vector4.Clamp(ref w, ref a, ref b)
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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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.ApproximatelyEquivalent(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