diff options
author | Eric Mellino <erme@microsoft.com> | 2017-07-06 00:54:18 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-06 00:54:18 +0300 |
commit | 04137f3ad7663a3e39beeda340a14d405a7c911c (patch) | |
tree | 1706028e15ee02d5a01fb9bb9e689695f717226d /src/System.Numerics.Vectors | |
parent | ab44d95526c4701782fc1fe36fdd883d3e2a739e (diff) | |
parent | 06602662a17120037e041e9a826d1cfabf486fca (diff) |
Merge pull request #21893 from mellinoe/vector-sqrt-test-precision
Add precision allowance and significantly better logging to Vector.SquareRoot tests.
Diffstat (limited to 'src/System.Numerics.Vectors')
5 files changed, 186 insertions, 73 deletions
diff --git a/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj b/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj index 437be1c4e8..2af29cb031 100644 --- a/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj +++ b/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj @@ -46,7 +46,9 @@ </ItemGroup> <!-- Carry a copy of MathF where not available --> <ItemGroup Condition="'$(IsPartialFacadeAssembly)' == 'true' OR $(TargetGroup.StartsWith('netstandard'))"> - <Compile Include="System\MathF.cs" /> + <Compile Include="..\..\Common\src\System\MathF.netstandard.cs"> + <Link>System\MathF.netstandard.cs</Link> + </Compile> </ItemGroup> <!-- Portable version only --> <ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'"> diff --git a/src/System.Numerics.Vectors/src/System/MathF.cs b/src/System.Numerics.Vectors/src/System/MathF.cs deleted file mode 100644 index d3eaa4b126..0000000000 --- a/src/System.Numerics.Vectors/src/System/MathF.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Runtime.CompilerServices; - -namespace System -{ - internal static class MathF - { - public const float PI = (float)Math.PI; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Abs(float x) - { - return Math.Abs(x); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Acos(float x) - { - return (float)Math.Acos(x); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Cos(float x) - { - return (float)Math.Cos(x); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float IEEERemainder(float x, float y) - { - return (float)Math.IEEERemainder(x, y); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sin(float x) - { - return (float)Math.Sin(x); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sqrt(float x) - { - return (float)Math.Sqrt(x); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Tan(float x) - { - return (float)Math.Tan(x); - } - } -} diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/System.Numerics.Vectors/tests/GenericVectorTests.cs index 88e11b93e4..e03022a216 100644 --- a/src/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.Linq; using System.Reflection; using Xunit; +using Xunit.Sdk; namespace System.Numerics.Tests { @@ -1880,26 +1881,26 @@ namespace System.Numerics.Tests } [Fact] - public void SquareRootByte() { TestSquareRoot<Byte>(); } + public void SquareRootByte() { TestSquareRoot<Byte>(-1); } [Fact] - public void SquareRootSByte() { TestSquareRoot<SByte>(); } + public void SquareRootSByte() { TestSquareRoot<SByte>(-1); } [Fact] - public void SquareRootUInt16() { TestSquareRoot<UInt16>(); } + public void SquareRootUInt16() { TestSquareRoot<UInt16>(-1); } [Fact] - public void SquareRootInt16() { TestSquareRoot<Int16>(); } + public void SquareRootInt16() { TestSquareRoot<Int16>(-1); } [Fact] - public void SquareRootUInt32() { TestSquareRoot<UInt32>(); } + public void SquareRootUInt32() { TestSquareRoot<UInt32>(-1); } [Fact] - public void SquareRootInt32() { TestSquareRoot<Int32>(); } + public void SquareRootInt32() { TestSquareRoot<Int32>(-1); } [Fact] - public void SquareRootUInt64() { TestSquareRoot<UInt64>(); } + public void SquareRootUInt64() { TestSquareRoot<UInt64>(-1); } [Fact] - public void SquareRootInt64() { TestSquareRoot<Int64>(); } + public void SquareRootInt64() { TestSquareRoot<Int64>(-1); } [Fact] - public void SquareRootSingle() { TestSquareRoot<Single>(); } + public void SquareRootSingle() { TestSquareRoot<Single>(6); } [Fact] - public void SquareRootDouble() { TestSquareRoot<Double>(); } - private void TestSquareRoot<T>() where T : struct + public void SquareRootDouble() { TestSquareRoot<Double>(15); } + private void TestSquareRoot<T>(int precision = -1) where T : struct, IEquatable<T> { T[] values = GenerateRandomValuesForVector<T>(); Vector<T> vector = new Vector<T>(values); @@ -1909,7 +1910,7 @@ namespace System.Numerics.Tests (index, val) => { T expected = Util.Sqrt(values[index]); - Assert.Equal(expected, val); + AssertEqual(expected, val, $"SquareRoot( {FullString(values[index])} )", precision); }); } @@ -2610,6 +2611,86 @@ namespace System.Numerics.Tests #endregion Narrow / Widen #region Helper Methods + private static void AssertEqual<T>(T expected, T actual, string operation, int precision = -1) where T : IEquatable<T> + { + if (typeof(T) == typeof(float)) + { + if (!IsDiffTolerable((float)(object)expected, (float)(object)actual, precision)) + { + throw new XunitException($"AssertEqual failed for operation {operation}. Expected: {expected,10:G9}, Actual: {actual,10:G9}."); + } + } + else if (typeof(T) == typeof(double)) + { + if (!IsDiffTolerable((double)(object)expected, (double)(object)actual, precision)) + { + throw new XunitException($"AssertEqual failed for operation {operation}. Expected: {expected,20:G17}, Actual: {actual,20:G17}."); + } + } + else + { + if (!expected.Equals(actual)) + { + throw new XunitException($"AssertEqual failed for operation {operation}. Expected: {expected}, Actual: {actual}."); + } + } + } + + private static bool IsDiffTolerable(double d1, double d2, int precision) + { + if (double.IsNaN(d1)) + { + return double.IsNaN(d2); + } + if (double.IsInfinity(d1) || double.IsInfinity(d2)) + { + return AreSameInfinity(d1, d2); + } + + double diffRatio = (d1 - d2) / d1; + diffRatio *= Math.Pow(10, precision); + return Math.Abs(diffRatio) < 1; + } + + private static bool IsDiffTolerable(float f1, float f2, int precision) + { + if (float.IsNaN(f1)) + { + return float.IsNaN(f2); + } + if (float.IsInfinity(f1) || float.IsInfinity(f2)) + { + return AreSameInfinity(f1, f2); + } + + float diffRatio = (f1 - f2) / f1; + diffRatio *= MathF.Pow(10, precision); + return Math.Abs(diffRatio) < 1; + } + + private static string FullString<T>(T value) + { + if (typeof(T) == typeof(float)) + { + return ((float)(object)value).ToString("G9"); + } + else if (typeof(T) == typeof(double)) + { + return ((double)(object)value).ToString("G17"); + } + else + { + return value.ToString(); + } + } + + private static bool AreSameInfinity(double d1, double d2) + { + return + double.IsNegativeInfinity(d1) == double.IsNegativeInfinity(d2) && + double.IsPositiveInfinity(d1) == double.IsPositiveInfinity(d2); + } + private static void ValidateVector<T>(Vector<T> vector, Action<int, T> indexValidationFunc) where T : struct { for (int g = 0; g < Vector<T>.Count; g++) @@ -2695,4 +2776,4 @@ namespace System.Numerics.Tests } #endregion } -} +}
\ No newline at end of file diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.tt b/src/System.Numerics.Vectors/tests/GenericVectorTests.tt index 1aa946d685..4790b1ac50 100644 --- a/src/System.Numerics.Vectors/tests/GenericVectorTests.tt +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.tt @@ -12,6 +12,7 @@ using System.Globalization; using System.Linq; using System.Reflection; using Xunit; +using Xunit.Sdk; namespace System.Numerics.Tests { @@ -216,7 +217,7 @@ namespace System.Numerics.Tests Assert.Throws<NullReferenceException>(() => vector.CopyTo(null, 0)); Assert.Throws<ArgumentOutOfRangeException>(() => vector.CopyTo(array, -1)); Assert.Throws<ArgumentOutOfRangeException>(() => vector.CopyTo(array, array.Length)); - Assert.Throws<ArgumentException>(() => vector.CopyTo(array, array.Length - 1)); + AssertExtensions.Throws<ArgumentException>(null, () => vector.CopyTo(array, array.Length - 1)); vector.CopyTo(array); for (int g = 0; g < array.Length; g++) @@ -1383,13 +1384,14 @@ namespace System.Numerics.Tests <# foreach (var type in supportedTypes) { + int precision = type == typeof(float) ? 6 : type == typeof(double) ? 15 : -1; #> [Fact] - public void SquareRoot<#=type.Name#>() { TestSquareRoot<<#=type.Name#>>(); } + public void SquareRoot<#=type.Name#>() { TestSquareRoot<<#=type.Name#>>(<#=precision#>); } <# } #> - private void TestSquareRoot<T>() where T : struct + private void TestSquareRoot<T>(int precision = -1) where T : struct, IEquatable<T> { T[] values = GenerateRandomValuesForVector<T>(); Vector<T> vector = new Vector<T>(values); @@ -1399,7 +1401,7 @@ namespace System.Numerics.Tests (index, val) => { T expected = Util.Sqrt(values[index]); - Assert.Equal(expected, val); + AssertEqual(expected, val, $"SquareRoot( {FullString(values[index])} )", precision); }); } @@ -1702,6 +1704,86 @@ namespace System.Numerics.Tests #endregion Narrow / Widen #region Helper Methods + private static void AssertEqual<T>(T expected, T actual, string operation, int precision = -1) where T : IEquatable<T> + { + if (typeof(T) == typeof(float)) + { + if (!IsDiffTolerable((float)(object)expected, (float)(object)actual, precision)) + { + throw new XunitException($"AssertEqual failed for operation {operation}. Expected: {expected,10:G9}, Actual: {actual,10:G9}."); + } + } + else if (typeof(T) == typeof(double)) + { + if (!IsDiffTolerable((double)(object)expected, (double)(object)actual, precision)) + { + throw new XunitException($"AssertEqual failed for operation {operation}. Expected: {expected,20:G17}, Actual: {actual,20:G17}."); + } + } + else + { + if (!expected.Equals(actual)) + { + throw new XunitException($"AssertEqual failed for operation {operation}. Expected: {expected}, Actual: {actual}."); + } + } + } + + private static bool IsDiffTolerable(double d1, double d2, int precision) + { + if (double.IsNaN(d1)) + { + return double.IsNaN(d2); + } + if (double.IsInfinity(d1) || double.IsInfinity(d2)) + { + return AreSameInfinity(d1, d2); + } + + double diffRatio = (d1 - d2) / d1; + diffRatio *= Math.Pow(10, precision); + return Math.Abs(diffRatio) < 1; + } + + private static bool IsDiffTolerable(float f1, float f2, int precision) + { + if (float.IsNaN(f1)) + { + return float.IsNaN(f2); + } + if (float.IsInfinity(f1) || float.IsInfinity(f2)) + { + return AreSameInfinity(f1, f2); + } + + float diffRatio = (f1 - f2) / f1; + diffRatio *= MathF.Pow(10, precision); + return Math.Abs(diffRatio) < 1; + } + + private static string FullString<T>(T value) + { + if (typeof(T) == typeof(float)) + { + return ((float)(object)value).ToString("G9"); + } + else if (typeof(T) == typeof(double)) + { + return ((double)(object)value).ToString("G17"); + } + else + { + return value.ToString(); + } + } + + private static bool AreSameInfinity(double d1, double d2) + { + return + double.IsNegativeInfinity(d1) == double.IsNegativeInfinity(d2) && + double.IsPositiveInfinity(d1) == double.IsPositiveInfinity(d2); + } + private static void ValidateVector<T>(Vector<T> vector, Action<int, T> indexValidationFunc) where T : struct { for (int g = 0; g < Vector<T>.Count; g++) diff --git a/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj b/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj index e623866e58..d952677904 100644 --- a/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj +++ b/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj @@ -35,6 +35,9 @@ <Compile Include="$(CommonTestPath)\System\PlatformDetection.cs"> <Link>Common\System\PlatformDetection.cs</Link> </Compile> + <Compile Condition="'$(TargetGroup)' == 'netfx'" Include="..\..\Common\src\System\MathF.netstandard.cs"> + <Link>System\MathF.netstandard.cs</Link> + </Compile> </ItemGroup> <ItemGroup> <None Include="..\src\System\Numerics\ConstantHelper.tt"> |