From 2b156119247b43514a4f115556b07f638b7f20b7 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 9 Jul 2024 21:59:35 -0400 Subject: [PATCH] Add TensorPrimitives.{Max/Min}MagnitudeNumber --- .../ref/System.Numerics.Tensors.netcore.cs | 6 ++ .../TensorPrimitives.MaxMagnitudeNumber.cs | 69 +++++++++++++++++++ .../TensorPrimitives.MinMagnitudeNumber.cs | 69 +++++++++++++++++++ .../tests/TensorPrimitives.Generic.cs | 18 +++-- 4 files changed, 158 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs index 5e1d77a45a5c1..7bb347b333d85 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs @@ -476,6 +476,9 @@ public static void Log10(System.ReadOnlySpan x, System.Span destination public static T MaxMagnitude(System.ReadOnlySpan x) where T : System.Numerics.INumberBase { throw null; } public static void MaxMagnitude(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumberBase { } public static void MaxMagnitude(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumberBase { } + public static T MaxMagnitudeNumber(System.ReadOnlySpan x) where T : System.Numerics.INumberBase { throw null; } + public static void MaxMagnitudeNumber(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumberBase { } + public static void MaxMagnitudeNumber(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumberBase { } public static T Max(System.ReadOnlySpan x) where T : System.Numerics.INumber { throw null; } public static void Max(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumber { } public static void Max(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumber { } @@ -485,6 +488,9 @@ public static void MaxNumber(System.ReadOnlySpan x, T y, System.Span de public static T MinMagnitude(System.ReadOnlySpan x) where T : System.Numerics.INumberBase { throw null; } public static void MinMagnitude(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumberBase { } public static void MinMagnitude(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumberBase { } + public static T MinMagnitudeNumber(System.ReadOnlySpan x) where T : System.Numerics.INumberBase { throw null; } + public static void MinMagnitudeNumber(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumberBase { } + public static void MinMagnitudeNumber(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumberBase { } public static T Min(System.ReadOnlySpan x) where T : System.Numerics.INumber { throw null; } public static void Min(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumber { } public static void Min(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumber { } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs index 53eb31e5dc2a2..01dbcb471d973 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs @@ -9,6 +9,75 @@ namespace System.Numerics.Tensors { public static partial class TensorPrimitives { + /// Searches for the number with the largest magnitude in the specified tensor. + /// The tensor, represented as a span. + /// The element in with the largest magnitude (absolute value). + /// Length of must be greater than zero. + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitudeNumber` function. + /// If two values have the same magnitude and one is positive and the other is negative, + /// the positive value is considered to have the larger magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static T MaxMagnitudeNumber(ReadOnlySpan x) + where T : INumberBase => + MinMaxCore>(x); + + /// Computes the element-wise number with the largest magnitude in the specified tensors. + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of must be same as length of . + /// Destination is too short. + /// and reference overlapping memory locations and do not begin at the same location. + /// and reference overlapping memory locations and do not begin at the same location. + /// + /// + /// This method effectively computes [i] = .MaxMagnitudeNumber([i], [i]). + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitudeNumber` function. + /// If the two values have the same magnitude and one is positive and the other is negative, + /// the positive value is considered to have the larger magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static void MaxMagnitudeNumber(ReadOnlySpan x, ReadOnlySpan y, Span destination) + where T : INumberBase => + InvokeSpanSpanIntoSpan>(x, y, destination); + + /// Computes the element-wise number with the largest magnitude in the specified tensors. + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// and reference overlapping memory locations and do not begin at the same location. + /// + /// + /// This method effectively computes [i] = .MaxMagnitudeNumber([i], ). + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitudeNumber` function. + /// If the two values have the same magnitude and one is positive and the other is negative, + /// the positive value is considered to have the larger magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static void MaxMagnitudeNumber(ReadOnlySpan x, T y, Span destination) + where T : INumberBase => + InvokeSpanScalarIntoSpan>(x, y, destination); + /// Operator to get x or y based on which has the larger MathF.Abs internal readonly struct MaxMagnitudeNumberOperator : IAggregationOperator where T : INumberBase diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs index b714b8e7d0a64..f02cbc7caf1b1 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs @@ -9,6 +9,75 @@ namespace System.Numerics.Tensors { public static partial class TensorPrimitives { + /// Searches for the number with the smallest magnitude in the specified tensor. + /// The tensor, represented as a span. + /// The element in with the smallest magnitude (absolute value). + /// Length of must be greater than zero. + /// + /// + /// The determination of the minimum magnitude matches the IEEE 754:2019 `minimumMagnitudeNumber` function. + /// If two values have the same magnitude and one is positive and the other is negative, + /// the negative value is considered to have the smaller magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static T MinMagnitudeNumber(ReadOnlySpan x) + where T : INumberBase => + MinMaxCore>(x); + + /// Computes the element-wise number with the smallest magnitude in the specified tensors. + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of must be same as length of . + /// Destination is too short. + /// and reference overlapping memory locations and do not begin at the same location. + /// and reference overlapping memory locations and do not begin at the same location. + /// + /// + /// This method effectively computes [i] = .MinMagnitudeNumber([i], [i]). + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `minimumMagnitudeNumber` function. + /// If the two values have the same magnitude and one is positive and the other is negative, + /// the negative value is considered to have the smaller magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static void MinMagnitudeNumber(ReadOnlySpan x, ReadOnlySpan y, Span destination) + where T : INumberBase => + InvokeSpanSpanIntoSpan>(x, y, destination); + + /// Computes the element-wise number with the smallest magnitude in the specified tensors. + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// and reference overlapping memory locations and do not begin at the same location. + /// + /// + /// This method effectively computes [i] = .MinMagnitudeNumber([i], ). + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `minimumMagnitudeNumber` function. + /// If the two values have the same magnitude and one is positive and the other is negative, + /// the negative value is considered to have the smaller magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static void MinMagnitudeNumber(ReadOnlySpan x, T y, Span destination) + where T : INumberBase => + InvokeSpanScalarIntoSpan>(x, y, destination); + /// Operator to get x or y based on which has the smaller MathF.Abs internal readonly struct MinMagnitudeNumberOperator : IAggregationOperator where T : INumberBase diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs index cfe4fd9896977..94bbfb8fcebe9 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs @@ -522,8 +522,14 @@ public static IEnumerable SpanSpanDestinationFunctionsToTest() yield return Create(TensorPrimitives.Hypot, T.Hypot); yield return Create(TensorPrimitives.Ieee754Remainder, T.Ieee754Remainder); yield return Create(TensorPrimitives.Log, T.Log); + yield return Create(TensorPrimitives.Max, T.Max); yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber); + yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude); + yield return Create(TensorPrimitives.MaxMagnitudeNumber, T.MaxMagnitudeNumber); + yield return Create(TensorPrimitives.Min, T.Min); yield return Create(TensorPrimitives.MinNumber, T.MinNumber); + yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude); + yield return Create(TensorPrimitives.MinMagnitudeNumber, T.MinMagnitudeNumber); yield return Create(TensorPrimitives.Pow, T.Pow, Helpers.DetermineTolerance(doubleTolerance: 1e-13, floatTolerance: 1e-5f)); static object[] Create(SpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) @@ -656,11 +662,13 @@ public static IEnumerable SpanScalarDestinationFunctionsToTest() yield return Create(TensorPrimitives.Pow, T.Pow, Helpers.DetermineTolerance(doubleTolerance: 1e-13, floatTolerance: 1e-5f)); yield return Create(TensorPrimitives.Log, T.Log); yield return Create(TensorPrimitives.Max, T.Max); - yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude); yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber); + yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude); + yield return Create(TensorPrimitives.MaxMagnitudeNumber, T.MaxMagnitudeNumber); yield return Create(TensorPrimitives.Min, T.Min); - yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude); yield return Create(TensorPrimitives.MinNumber, T.MinNumber); + yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude); + yield return Create(TensorPrimitives.MinMagnitudeNumber, T.MinMagnitudeNumber); static object[] Create(SpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) => new object[] { tensorPrimitivesMethod, expectedMethod, tolerance }; @@ -1841,11 +1849,13 @@ public static IEnumerable SpanScalarDestinationFunctionsToTest() yield return Create(TensorPrimitives.BitwiseAnd, (x, y) => x & y); yield return Create(TensorPrimitives.BitwiseOr, (x, y) => x | y); yield return Create(TensorPrimitives.Max, T.Max); - yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude); yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber); + yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude); + yield return Create(TensorPrimitives.MaxMagnitudeNumber, T.MaxMagnitudeNumber); yield return Create(TensorPrimitives.Min, T.Min); - yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude); yield return Create(TensorPrimitives.MinNumber, T.MinNumber); + yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude); + yield return Create(TensorPrimitives.MinMagnitudeNumber, T.MinMagnitudeNumber); yield return Create(TensorPrimitives.Xor, (x, y) => x ^ y); static object[] Create(SpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod)