Fix Vector2/4 Lerp methods (#37764)
authorJohn Kelly <johnkellyoxford@gmail.com>
Sat, 13 Jun 2020 01:25:51 +0000 (02:25 +0100)
committerGitHub <noreply@github.com>
Sat, 13 Jun 2020 01:25:51 +0000 (18:25 -0700)
* Fix LERP and add appropriate tests

* Fix syntax error

All tests passed :white_check_mark:

src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs
src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs
src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs

index b3ed6e2..731e001 100644 (file)
@@ -435,6 +435,37 @@ namespace System.Numerics.Tests
             Assert.True(MathHelper.Equal(expected, actual), "Vector2f.Lerp did not return the expected value.");
         }
 
+        // A test for Lerp (Vector2f, Vector2f, float)
+        // Lerp test with values known to be innacurate with the old lerp impl
+        [Fact]
+        public void Vector2LerpTest7()
+        {
+            Vector2 a = new Vector2(0.44728136f);
+            Vector2 b = new Vector2(0.46345946f);
+
+            float t = 0.26402435f;
+
+            Vector2 expected = new Vector2(0.45155275f);
+            Vector2 actual = Vector2.Lerp(a, b, t);
+            Assert.True(MathHelper.Equal(expected, actual), "Vector2f.Lerp did not return the expected value.");
+        }
+
+        // A test for Lerp (Vector2f, Vector2f, float)
+        // Lerp test with values known to be innacurate with the old lerp impl
+        // (Old code incorrectly gets 0.33333588)
+        [Fact]
+        public void Vector2LerpTest8()
+        {
+            Vector2 a = new Vector2(-100);
+            Vector2 b = new Vector2(0.33333334f);
+
+            float t = 1f;
+
+            Vector2 expected = new Vector2(0.33333334f);
+            Vector2 actual = Vector2.Lerp(a, b, t);
+            Assert.True(MathHelper.Equal(expected, actual), "Vector2f.Lerp did not return the expected value.");
+        }
+
         // A test for Transform(Vector2f, Matrix4x4)
         [Fact]
         public void Vector2TransformTest()
index ec93079..e49fe5c 100644 (file)
@@ -364,10 +364,24 @@ namespace System.Numerics.Tests
         }
 
         // A test for Lerp (Vector3f, Vector3f, float)
-        // Lerp test from the same point
+        // Lerp test with special float value
         [Fact]
         public void Vector3LerpTest5()
         {
+            Vector3 a = new Vector3(45.67f, 90.0f, 0f);
+            Vector3 b = new Vector3(float.PositiveInfinity, float.NegativeInfinity, 0);
+
+            float t = 0.408f;
+            Vector3 actual = Vector3.Lerp(a, b, t);
+            Assert.True(float.IsPositiveInfinity(actual.X), "Vector3f.Lerp did not return the expected value.");
+            Assert.True(float.IsNegativeInfinity(actual.Y), "Vector3f.Lerp did not return the expected value.");
+        }
+
+        // A test for Lerp (Vector3f, Vector3f, float)
+        // Lerp test from the same point
+        [Fact]
+        public void Vector3LerpTest6()
+        {
             Vector3 a = new Vector3(1.68f, 2.34f, 5.43f);
             Vector3 b = a;
 
@@ -377,6 +391,37 @@ namespace System.Numerics.Tests
             Assert.True(MathHelper.Equal(expected, actual), "Vector3f.Lerp did not return the expected value.");
         }
 
+        // A test for Lerp (Vector3f, Vector3f, float)
+        // Lerp test with values known to be innacurate with the old lerp impl
+        [Fact]
+        public void Vector3LerpTest7()
+        {
+            Vector3 a = new Vector3(0.44728136f);
+            Vector3 b = new Vector3(0.46345946f);
+
+            float t = 0.26402435f;
+
+            Vector3 expected = new Vector3(0.45155275f);
+            Vector3 actual = Vector3.Lerp(a, b, t);
+            Assert.True(MathHelper.Equal(expected, actual), "Vector3f.Lerp did not return the expected value.");
+        }
+
+        // A test for Lerp (Vector3f, Vector3f, float)
+        // Lerp test with values known to be innacurate with the old lerp impl
+        // (Old code incorrectly gets 0.33333588)
+        [Fact]
+        public void Vector3LerpTest8()
+        {
+            Vector3 a = new Vector3(-100);
+            Vector3 b = new Vector3(0.33333334f);
+
+            float t = 1f;
+
+            Vector3 expected = new Vector3(0.33333334f);
+            Vector3 actual = Vector3.Lerp(a, b, t);
+            Assert.True(MathHelper.Equal(expected, actual), "Vector3f.Lerp did not return the expected value.");
+        }
+
         // A test for Reflect (Vector3f, Vector3f)
         [Fact]
         public void Vector3ReflectTest()
index 3643f20..8db6079 100644 (file)
@@ -397,10 +397,24 @@ namespace System.Numerics.Tests
         }
 
         // A test for Lerp (Vector4f, Vector4f, float)
-        // Lerp test from the same point
+        // Lerp test with special float value
         [Fact]
         public void Vector4LerpTest5()
         {
+            Vector4 a = new Vector4(45.67f, 90.0f, 0, 0);
+            Vector4 b = new Vector4(float.PositiveInfinity, float.NegativeInfinity, 0, 0);
+
+            float t = 0.408f;
+            Vector4 actual = Vector4.Lerp(a, b, t);
+            Assert.True(float.IsPositiveInfinity(actual.X), "Vector4f.Lerp did not return the expected value.");
+            Assert.True(float.IsNegativeInfinity(actual.Y), "Vector4f.Lerp did not return the expected value.");
+        }
+
+        // A test for Lerp (Vector4f, Vector4f, float)
+        // Lerp test from the same point
+        [Fact]
+        public void Vector4LerpTest6()
+        {
             Vector4 a = new Vector4(4.0f, 5.0f, 6.0f, 7.0f);
             Vector4 b = new Vector4(4.0f, 5.0f, 6.0f, 7.0f);
 
@@ -410,6 +424,37 @@ namespace System.Numerics.Tests
             Assert.True(MathHelper.Equal(expected, actual), "Vector4f.Lerp did not return the expected value.");
         }
 
+        // A test for Lerp (Vector4f, Vector4f, float)
+        // Lerp test with values known to be innacurate with the old lerp impl
+        [Fact]
+        public void Vector4LerpTest7()
+        {
+            Vector4 a = new Vector4(0.44728136f);
+            Vector4 b = new Vector4(0.46345946f);
+
+            float t = 0.26402435f;
+
+            Vector4 expected = new Vector4(0.45155275f);
+            Vector4 actual = Vector4.Lerp(a, b, t);
+            Assert.True(MathHelper.Equal(expected, actual), "Vector4f.Lerp did not return the expected value.");
+        }
+
+        // A test for Lerp (Vector4f, Vector4f, float)
+        // Lerp test with values known to be innacurate with the old lerp impl
+        // (Old code incorrectly gets 0.33333588)
+        [Fact]
+        public void Vector4LerpTest8()
+        {
+            Vector4 a = new Vector4(-100);
+            Vector4 b = new Vector4(0.33333334f);
+
+            float t = 1f;
+
+            Vector4 expected = new Vector4(0.33333334f);
+            Vector4 actual = Vector4.Lerp(a, b, t);
+            Assert.True(MathHelper.Equal(expected, actual), "Vector4f.Lerp did not return the expected value.");
+        }
+
         // A test for Transform (Vector2f, Matrix4x4)
         [Fact]
         public void Vector4TransformTest1()
index cee4a0e..81402c8 100644 (file)
@@ -205,7 +205,7 @@ namespace System.Numerics
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount)
         {
-            return value1 + (value2 - value1) * amount;
+            return (value1 * (1.0f - amount)) + (value2 * amount);
         }
 
         /// <summary>
index c6dc6a8..54f16a1 100644 (file)
@@ -207,7 +207,7 @@ namespace System.Numerics
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount)
         {
-            return value1 + (value2 - value1) * amount;
+            return (value1 * (1.0f - amount)) + (value2 * amount);
         }
 
         /// <summary>