From 6a5ca7ed614432fcea346ab7786ad8d6d9401103 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 30 Apr 2024 17:57:11 -0400 Subject: [PATCH] Fix some TensorPrimitives tests failing for me locally with checked builds This is just: - Adding tolerance checks for NFloat that are the same as for float/double - Adding tolerance for MultiplyAddEstimate that matches our other tolerances for "Estimate" functions This addresses everything failing for me locally, but it doesn't match the failure spike recently highlighted in CI. --- .../System.Numerics.Tensors/tests/Helpers.cs | 13 ++- .../tests/TensorPrimitives.Generic.cs | 105 +++++++++++------- 2 files changed, 78 insertions(+), 40 deletions(-) diff --git a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs index 1cc399d0a5a52..e2621ec3af32a 100644 --- a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs +++ b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; namespace System.Numerics.Tensors.Tests { @@ -72,8 +73,18 @@ public static bool IsEqualWithTolerance(float expected, float actual, float? tol { return (T?)(object)halfTolerance; } + else if (typeof(T) == typeof(NFloat)) + { + if (IntPtr.Size == 8 && doubleTolerance != null) + { + return (T?)(object)(NFloat)doubleTolerance; + } + else if (IntPtr.Size == 4 && floatTolerance != null) + { + return (T?)(object)(NFloat)doubleTolerance; + } + } #endif - return null; } } diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs index 0ad762f9401ed..1875b6059b7fa 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs @@ -480,8 +480,11 @@ public void SpanDestinationFunctions_ValueRange(SpanDestinationDelegate tensorPr #pragma warning disable xUnit1026 // Theory methods should use all of their parameters [Theory] [MemberData(nameof(SpanDestinationFunctionsToTest))] - public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinationDelegate tensorPrimitivesMethod, Func _, T? __ = null) + public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -493,8 +496,11 @@ public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinatio [Theory] [MemberData(nameof(SpanDestinationFunctionsToTest))] - public void SpanDestinationFunctions_ThrowsForOverlapppingInputsWithOutputs(SpanDestinationDelegate tensorPrimitivesMethod, Func _, T? __ = null) + public void SpanDestinationFunctions_ThrowsForOverlapppingInputsWithOutputs(SpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(2, 2))); @@ -946,15 +952,15 @@ public static IEnumerable SpanSpanSpanDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) - => new object[] { tensorPrimitivesMethod, expectedMethod }; + static object[] Create(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) + => new object[] { tensorPrimitivesMethod, expectedMethod, tolerance }; } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -966,14 +972,14 @@ public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate t tensorPrimitivesMethod(x, y, z, destination); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -984,14 +990,14 @@ public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tens for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], xOrig[i]), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], xOrig[i]), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1005,7 +1011,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, x); @@ -1014,7 +1020,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, y); @@ -1023,7 +1029,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, z); }); @@ -1031,8 +1037,11 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1051,8 +1060,11 @@ public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDesti [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1066,8 +1078,11 @@ public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDes [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(5, 2), array.AsSpan(7, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(5, 2), array.AsSpan(7, 2), array.AsSpan(2, 2))); @@ -1082,15 +1097,15 @@ public static IEnumerable SpanSpanScalarDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) - => new object[] { tensorPrimitivesMethod, expectedMethod }; + static object[] Create(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) + => new object[] { tensorPrimitivesMethod, expectedMethod, tolerance }; } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1103,14 +1118,14 @@ public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelega for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1122,14 +1137,14 @@ public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], z), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], z), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1143,7 +1158,7 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel tensorPrimitivesMethod(x.Span, y.Span, z, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }, x); @@ -1152,7 +1167,7 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel tensorPrimitivesMethod(x.Span, y.Span, z, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }, y); }); @@ -1160,8 +1175,11 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1175,8 +1193,11 @@ public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScala [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanScalarDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(4, 2), default, array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(4, 2), default, array.AsSpan(2, 2))); @@ -1190,15 +1211,15 @@ public static IEnumerable SpanScalarSpanDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + static object[] Create(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) => new object[] { tensorPrimitivesMethod, expectedMethod }; } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1211,14 +1232,14 @@ public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelega for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1230,14 +1251,14 @@ public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], y, xOrig[i]), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], y, xOrig[i]), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1251,7 +1272,7 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel tensorPrimitivesMethod(x.Span, y, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }, x); @@ -1260,7 +1281,7 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel tensorPrimitivesMethod(x.Span, y, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }, z); }); @@ -1268,8 +1289,11 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1283,8 +1307,11 @@ public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpa [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanScalarSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), default, array.AsSpan(4, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), default, array.AsSpan(4, 2), array.AsSpan(2, 2)));