diff --git a/tests/OpenTK.Tests/OpenTK.Tests.fsproj b/tests/OpenTK.Tests/OpenTK.Tests.fsproj index 09bd26c0..d269e1c3 100644 --- a/tests/OpenTK.Tests/OpenTK.Tests.fsproj +++ b/tests/OpenTK.Tests/OpenTK.Tests.fsproj @@ -64,6 +64,7 @@ + diff --git a/tests/OpenTK.Tests/Vector3Tests.fs b/tests/OpenTK.Tests/Vector3Tests.fs index 8ac1b4ae..87b2dc92 100644 --- a/tests/OpenTK.Tests/Vector3Tests.fs +++ b/tests/OpenTK.Tests/Vector3Tests.fs @@ -206,6 +206,7 @@ module Vector3 = Assert.ApproximatelyEqual(a.X + b.X,c.X) Assert.ApproximatelyEqual(a.Y + b.Y,c.Y) + Assert.ApproximatelyEqual(a.Z + b.Z,c.Z) [] let ``Vector3 addition is commutative`` (a : Vector3, b : Vector3) = diff --git a/tests/OpenTK.Tests/Vector4Tests.fs b/tests/OpenTK.Tests/Vector4Tests.fs new file mode 100644 index 00000000..b0b9c3a5 --- /dev/null +++ b/tests/OpenTK.Tests/Vector4Tests.fs @@ -0,0 +1,789 @@ +namespace OpenTK.Tests + +open Xunit +open FsCheck +open FsCheck.Xunit +open System +open System.Runtime.InteropServices +open OpenTK + +module Vector4 = + [ |])>] + module Constructors = + // + [] + 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) + + [] + 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) + + [] + 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((float32)0, v2.Z) + Assert.Equal((float32)0, v2.W) + + [] + 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((float32)0, v2.W) + + [] + 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) + + [ |])>] + module Indexing = + // + [] + 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]) + + [] + let ``Index operator throws exception for negative indices`` (x, y, z, w) = + let mutable v = Vector4(x, y, z, w) + + let invalidIndexingAccess = fun() -> v.[-1] |> ignore + let invalidIndexingAssignment = fun() -> v.[-1] <- x + + Assert.Throws(invalidIndexingAccess) |> ignore + Assert.Throws(invalidIndexingAssignment) |> ignore + + [] + let ``Index operator throws exception for large indices`` (x, y, z, w) = + let mutable v = Vector4(x, y, z, w) + + let invalidIndexingAccess = fun() -> v.[4] |> ignore + let invalidIndexingAssignment = fun() -> v.[4] <- x + + Assert.Throws(invalidIndexingAccess) |> ignore + Assert.Throws(invalidIndexingAssignment) |> ignore + + [ |])>] + module Length = + // + [] + let ``Length method works`` (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) + + [] + let ``Fast length method works`` (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) + + [] + let ``Length squared method works`` (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) + + [ |])>] + module Normalization = + // + [] + let ``Normalization of instance, creating a new vector, works`` (x, y, z, w) = + let v = Vector4(x, y, z, w) + let l = v.Length + + // Dividing by zero is not supported + if not (approxEq l 0.0f) then + let norm = v.Normalized() + + Assert.ApproximatelyEqual(v.X / l, norm.X) + Assert.ApproximatelyEqual(v.Y / l, norm.Y) + Assert.ApproximatelyEqual(v.Z / l, norm.Z) + Assert.ApproximatelyEqual(v.W / l, norm.W) + + [] + let ``Normalization of instance works`` (x, y, z, w) = + let v = Vector4(x, y, z, w) + let l = v.Length + + if not (approxEq l 0.0f) then + let norm = Vector4(x, y, z, w) + norm.Normalize() + + Assert.ApproximatelyEqual(v.X / l, norm.X) + Assert.ApproximatelyEqual(v.Y / l, norm.Y) + Assert.ApproximatelyEqual(v.Z / l, norm.Z) + Assert.ApproximatelyEqual(v.W / l, norm.W) + + [] + let ``Fast approximate normalization of instance works`` (x, y, z, w) = + let v = Vector4(x, y, z, w) + let norm = Vector4(x, y, z, w) + norm.NormalizeFast() + + let scale = MathHelper.InverseSqrtFast(x * x + y * y + z * z + w * w) + + Assert.ApproximatelyEqual(v.X * scale, norm.X) + Assert.ApproximatelyEqual(v.Y * scale, norm.Y) + Assert.ApproximatelyEqual(v.Z * scale, norm.Z) + Assert.ApproximatelyEqual(v.W * scale, norm.W) + + [] // TODO: Eliminate coefficient calculation, rounding error + let ``Normalization by reference works`` (a : Vector4) = + if not (approxEq a.Length 0.0f) then + let scale = 1.0f / a.Length + let norm = Vector4(a.X * scale, a.Y * scale, a.Z * scale, a.W * scale) + let vRes = Vector4.Normalize(ref a) + + Assert.ApproximatelyEqual(norm, vRes) + + [] // TODO: Eliminate coefficient calculation, rounding error + let ``Normalization works`` (a : Vector4) = + if not (approxEq a.Length 0.0f) then + let scale = 1.0f / a.Length + let norm = Vector4(a.X * scale, a.Y * scale, a.Z * scale, a.W * scale) + + Assert.ApproximatelyEqual(norm, Vector4.Normalize(a)); + + [] + let ``Fast approximate normalization by reference works`` (a : Vector4) = + let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z + a.W * a.W) + + let norm = Vector4(a.X * scale, a.Y * scale, a.Z * scale, a.W * scale) + let vRes = Vector4.NormalizeFast(ref a) + + Assert.ApproximatelyEqual(norm, vRes) + + [] + let ``Fast approximate normalization works`` (a : Vector4) = + let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z + a.W * a.W) + + let norm = Vector4(a.X * scale, a.Y * scale, a.Z * scale, a.W * scale) + + Assert.ApproximatelyEqual(norm, Vector4.NormalizeFast(a)); + + [ |])>] + module Addition = + // + [] + let ``Vector4 addition is the same as component addition`` (a : Vector4, b : Vector4) = + let c = a + b + + Assert.ApproximatelyEqual(a.X + b.X,c.X) + Assert.ApproximatelyEqual(a.Y + b.Y,c.Y) + Assert.ApproximatelyEqual(a.Z + b.Z,c.Z) + Assert.ApproximatelyEqual(a.W + b.W,c.W) + + [] + let ``Vector4 addition is commutative`` (a : Vector4, b : Vector4) = + let c = a + b + let c2 = b + a + + Assert.ApproximatelyEqual(c, c2) + + [] + let ``Vector4 addition is associative`` (a : Vector4, b : Vector4, c : Vector4) = + let r1 = (a + b) + c + let r2 = a + (b + c) + + Assert.ApproximatelyEqual(r1, r2) + + [] + let ``Static Vector4 addition method is the same as component addition`` (a : Vector4, b : Vector4) = + + let v1 = Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W) + let sum = Vector4.Add(a, b) + + Assert.ApproximatelyEqual(v1, sum) + + [] + let ``Static Vector4 addition method by reference is the same as component addition`` (a : Vector4, b : Vector4) = + + let v1 = Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W) + let sum = Vector4.Add(ref a, ref b) + + Assert.ApproximatelyEqual(v1, sum) + + [ |])>] + module Subtraction = + // + [] + 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) + + [] + let ``Static Vector4 subtraction method is the same as component addition`` (a : Vector4, b : Vector4) = + + let v1 = Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W) + let sum = Vector4.Subtract(a, b) + + Assert.ApproximatelyEqual(v1, sum) + + [] + let ``Static Vector4 subtraction method by reference is the same as component addition`` (a : Vector4, b : Vector4) = + + let v1 = Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W) + let sum = Vector4.Subtract(ref a, ref b) + + Assert.ApproximatelyEqual(v1, sum) + + [ |])>] + module Multiplication = + // + [] + 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) + + + [] + let ``Vector4 multiplication is commutative`` (a : Vector4, b : Vector4) = + let r1 = a * b + let r2 = b * a + + Assert.Equal(r1, r2) + + [] + 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) + + [] + 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) + + [] + 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) + + [] + let ``Vector4-Matrix4 multiplication works for right-handed notation`` (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) + + [] + let ``Vector4-Matrix4 multiplication works for left-handed notation`` (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) + + [] + let ``Static Vector4 multiplication method is the same as component multiplication`` (a : Vector4, b : Vector4) = + + let v1 = Vector4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W) + let sum = Vector4.Multiply(a, b) + + Assert.ApproximatelyEqual(v1, sum) + + [] + let ``Static Vector4 multiplication method by reference is the same as component multiplication`` (a : Vector4, b : Vector4) = + + let v1 = Vector4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W) + let sum = Vector4.Multiply(ref a, ref b) + + Assert.ApproximatelyEqual(v1, sum) + + [ |])>] + module Division = + // + [] + let ``Vector4-float division is the same as component-float division`` (a : Vector4, f : float32) = + if not (approxEq f 0.0f) then // we don't support diving by zero. + let r = a / f + + Assert.ApproximatelyEqual(a.X / f, r.X) + Assert.ApproximatelyEqual(a.Y / f, r.Y) + Assert.ApproximatelyEqual(a.Z / f, r.Z) + Assert.ApproximatelyEqual(a.W / f, r.W) + + [] + let ``Static Vector4-Vector4 division method works`` (a : Vector4, b : Vector4) = + + let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W) + let sum = Vector4.Divide(a, b) + + Assert.ApproximatelyEqual(v1, sum) + + [] + let ``Static Vector4-Vector4 divison method works by reference`` (a : Vector4, b : Vector4) = + + let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W) + let sum = Vector4.Divide(ref a, ref b) + + Assert.ApproximatelyEqual(v1, sum) + + [] + let ``Static Vector4-scalar division method works`` (a : Vector4, b : float32) = + + let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b) + let sum = Vector4.Divide(a, b) + + Assert.ApproximatelyEqual(v1, sum) + + [] + let ``Static Vector4-scalar divison method works by reference`` (a : Vector4, b : float32) = + + let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b) + let sum = Vector4.Divide(ref a, b) + + Assert.ApproximatelyEqual(v1, sum) + + [ |])>] + module Negation = + // + [] + let ``Vector negation operator works`` (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) + + [ |])>] + module Equality = + // + [] + let ``Vector equality operator works`` (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) + + [] + let ``Vector inequality operator works`` (x, y, z, w) = + let v1 = Vector4(x, y, z, w) + let v2 = Vector4(x + (float32)1 , y + (float32)1, z + (float32)1, w + (float32)1) + let inequality = v1 <> v2 + + Assert.True(inequality) + + [] + let ``Vector equality method works`` (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) + + [ |])>] + module Swizzling = + // + [] + let ``Vector swizzling works 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) + + [] + let ``Vector swizzling works 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) + + [] + let ``Vector swizzling works 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) + + [] + let ``Vector swizzling works 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) + + [ |])>] + module Interpolation = + // + [] + let ``Linear interpolation works`` (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) + + [] + let ``Barycentric interpolation works`` (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) + + [ |])>] + module ``Vector products`` = + // + [] + let ``Dot product works`` (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) + + [ |])>] + module ``Component min and max`` = + // + [] + let ``Selecting the lesser of two vectors works`` (x, y, z, w, a, b, c, d) = + let v1 = Vector4(x, y, z, w) + let v2 = Vector4(a, b, c, d) + + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared + + let vMin = Vector4.Min(v1, v2) + + if vMin = v1 then + let v1ShorterThanv2 = l1 < l2 + Assert.True(v1ShorterThanv2) + else + let v2ShorterThanv1 = l2 < l1 + Assert.True(v2ShorterThanv1) + + [] + let ``Selecting the greater of two vectors works`` (x, y, z, w, a, b, c, d) = + let v1 = Vector4(x, y, z, w) + let v2 = Vector4(a, b, c, d) + + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared + + let vMin = Vector4.Max(v1, v2) + + if vMin = v1 then + let v1LongerThanOrEqualTov2 = l1 >= l2 + Assert.True(v1LongerThanOrEqualTov2) + else + let v2LongerThanv1 = l2 > l1 + Assert.True(v2LongerThanv1) + + [ |])>] + module Clamping = + // + [] + let ``Clamping one vector between two other vectors works`` (a : Vector4, b : Vector4, w : Vector4) = + let res = Vector4.Clamp(w, a, b) + + let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X + let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y + let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z + let expW = if w.W < a.W then a.W else if w.W > b.W then b.W else w.W + + Assert.Equal(expX, res.X) + Assert.Equal(expY, res.Y) + Assert.Equal(expZ, res.Z) + Assert.Equal(expW, res.W) + + [] + let ``Clamping one vector between two other vectors works by reference`` (a : Vector4, b : Vector4, w : Vector4) = + let res = Vector4.Clamp(ref w, ref a, ref b) + + let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X + let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y + let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z + let expW = if w.W < a.W then a.W else if w.W > b.W then b.W else w.W + + Assert.Equal(expX, res.X) + Assert.Equal(expY, res.Y) + Assert.Equal(expZ, res.Z) + Assert.Equal(expW, res.W) + + [ |])>] + module ``Unit vectors``= + // + [] + let ``Unit X is correct`` = + let unitX = Vector4((float32)1, (float32)0, (float32)0, (float32)0) + + Assert.Equal(Vector4.UnitX, unitX) + + [] + let ``Unit Y is correct`` = + let unitY = Vector4((float32)0, (float32)1, (float32)0, (float32)0) + + Assert.Equal(Vector4.UnitY, unitY) + + [] + let ``Unit Z is correct`` = + let unitZ = Vector4((float32)0, (float32)0, (float32)1, (float32)0) + + Assert.Equal(Vector4.UnitZ, unitZ) + + [] + let ``Unit W is correct`` = + let unitW = Vector4((float32)0, (float32)0, (float32)0, (float32)1) + + Assert.Equal(Vector4.UnitW, unitW) + + [] + let ``Unit zero is correct`` = + let unitZero = Vector4((float32)0, (float32)0, (float32)0, (float32)0) + + Assert.Equal(Vector4.Zero, unitZero) + + [] + let ``Unit one is correct`` = + let unitOne = Vector4((float32)1, (float32)1, (float32)1, (float32)1) + + Assert.Equal(Vector4.One, unitOne) + + [ |])>] + module Serialization = + // + [] + let ``The absolute size of a Vector4 is always the size of its components`` (v : Vector4) = + let expectedSize = sizeof * 4 + + Assert.Equal(expectedSize, Vector4.SizeInBytes) + Assert.Equal(expectedSize, Marshal.SizeOf(Vector4())) \ No newline at end of file