Skip to content

Commit d40ac7c

Browse files
authored
Add TensorPrimitives.{Max/Min}MagnitudeNumber (#104651)
1 parent 029007d commit d40ac7c

File tree

4 files changed

+158
-4
lines changed

4 files changed

+158
-4
lines changed

src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ public static void Log10<T>(System.ReadOnlySpan<T> x, System.Span<T> destination
476476
public static T MaxMagnitude<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
477477
public static void MaxMagnitude<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
478478
public static void MaxMagnitude<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
479+
public static T MaxMagnitudeNumber<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
480+
public static void MaxMagnitudeNumber<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
481+
public static void MaxMagnitudeNumber<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
479482
public static T Max<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
480483
public static void Max<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumber<T> { }
481484
public static void Max<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumber<T> { }
@@ -485,6 +488,9 @@ public static void MaxNumber<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> de
485488
public static T MinMagnitude<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
486489
public static void MinMagnitude<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
487490
public static void MinMagnitude<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
491+
public static T MinMagnitudeNumber<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
492+
public static void MinMagnitudeNumber<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
493+
public static void MinMagnitudeNumber<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
488494
public static T Min<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
489495
public static void Min<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumber<T> { }
490496
public static void Min<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumber<T> { }

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxMagnitudeNumber.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,75 @@ namespace System.Numerics.Tensors
99
{
1010
public static partial class TensorPrimitives
1111
{
12+
/// <summary>Searches for the number with the largest magnitude in the specified tensor.</summary>
13+
/// <param name="x">The tensor, represented as a span.</param>
14+
/// <returns>The element in <paramref name="x"/> with the largest magnitude (absolute value).</returns>
15+
/// <exception cref="ArgumentException">Length of <paramref name="x" /> must be greater than zero.</exception>
16+
/// <remarks>
17+
/// <para>
18+
/// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitudeNumber` function.
19+
/// If two values have the same magnitude and one is positive and the other is negative,
20+
/// the positive value is considered to have the larger magnitude.
21+
/// </para>
22+
/// <para>
23+
/// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different
24+
/// operating systems or architectures.
25+
/// </para>
26+
/// </remarks>
27+
public static T MaxMagnitudeNumber<T>(ReadOnlySpan<T> x)
28+
where T : INumberBase<T> =>
29+
MinMaxCore<T, MaxMagnitudeNumberOperator<T>>(x);
30+
31+
/// <summary>Computes the element-wise number with the largest magnitude in the specified tensors.</summary>
32+
/// <param name="x">The first tensor, represented as a span.</param>
33+
/// <param name="y">The second tensor, represented as a span.</param>
34+
/// <param name="destination">The destination tensor, represented as a span.</param>
35+
/// <exception cref="ArgumentException">Length of <paramref name="x" /> must be same as length of <paramref name="y" />.</exception>
36+
/// <exception cref="ArgumentException">Destination is too short.</exception>
37+
/// <exception cref="ArgumentException"><paramref name="x"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
38+
/// <exception cref="ArgumentException"><paramref name="y"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
39+
/// <remarks>
40+
/// <para>
41+
/// This method effectively computes <c><paramref name="destination" />[i] = <typeparamref name="T"/>.MaxMagnitudeNumber(<paramref name="x" />[i], <paramref name="y" />[i])</c>.
42+
/// </para>
43+
/// <para>
44+
/// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitudeNumber` function.
45+
/// If the two values have the same magnitude and one is positive and the other is negative,
46+
/// the positive value is considered to have the larger magnitude.
47+
/// </para>
48+
/// <para>
49+
/// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different
50+
/// operating systems or architectures.
51+
/// </para>
52+
/// </remarks>
53+
public static void MaxMagnitudeNumber<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
54+
where T : INumberBase<T> =>
55+
InvokeSpanSpanIntoSpan<T, MaxMagnitudeNumberOperator<T>>(x, y, destination);
56+
57+
/// <summary>Computes the element-wise number with the largest magnitude in the specified tensors.</summary>
58+
/// <param name="x">The first tensor, represented as a span.</param>
59+
/// <param name="y">The second tensor, represented as a scalar.</param>
60+
/// <param name="destination">The destination tensor, represented as a span.</param>
61+
/// <exception cref="ArgumentException">Destination is too short.</exception>
62+
/// <exception cref="ArgumentException"><paramref name="x"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
63+
/// <remarks>
64+
/// <para>
65+
/// This method effectively computes <c><paramref name="destination" />[i] = <typeparamref name="T"/>.MaxMagnitudeNumber(<paramref name="x" />[i], <paramref name="y" />)</c>.
66+
/// </para>
67+
/// <para>
68+
/// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitudeNumber` function.
69+
/// If the two values have the same magnitude and one is positive and the other is negative,
70+
/// the positive value is considered to have the larger magnitude.
71+
/// </para>
72+
/// <para>
73+
/// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different
74+
/// operating systems or architectures.
75+
/// </para>
76+
/// </remarks>
77+
public static void MaxMagnitudeNumber<T>(ReadOnlySpan<T> x, T y, Span<T> destination)
78+
where T : INumberBase<T> =>
79+
InvokeSpanScalarIntoSpan<T, MaxMagnitudeNumberOperator<T>>(x, y, destination);
80+
1281
/// <summary>Operator to get x or y based on which has the larger MathF.Abs</summary>
1382
internal readonly struct MaxMagnitudeNumberOperator<T> : IAggregationOperator<T>
1483
where T : INumberBase<T>

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinMagnitudeNumber.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,75 @@ namespace System.Numerics.Tensors
99
{
1010
public static partial class TensorPrimitives
1111
{
12+
/// <summary>Searches for the number with the smallest magnitude in the specified tensor.</summary>
13+
/// <param name="x">The tensor, represented as a span.</param>
14+
/// <returns>The element in <paramref name="x"/> with the smallest magnitude (absolute value).</returns>
15+
/// <exception cref="ArgumentException">Length of <paramref name="x" /> must be greater than zero.</exception>
16+
/// <remarks>
17+
/// <para>
18+
/// The determination of the minimum magnitude matches the IEEE 754:2019 `minimumMagnitudeNumber` function.
19+
/// If two values have the same magnitude and one is positive and the other is negative,
20+
/// the negative value is considered to have the smaller magnitude.
21+
/// </para>
22+
/// <para>
23+
/// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different
24+
/// operating systems or architectures.
25+
/// </para>
26+
/// </remarks>
27+
public static T MinMagnitudeNumber<T>(ReadOnlySpan<T> x)
28+
where T : INumberBase<T> =>
29+
MinMaxCore<T, MinMagnitudeNumberOperator<T>>(x);
30+
31+
/// <summary>Computes the element-wise number with the smallest magnitude in the specified tensors.</summary>
32+
/// <param name="x">The first tensor, represented as a span.</param>
33+
/// <param name="y">The second tensor, represented as a span.</param>
34+
/// <param name="destination">The destination tensor, represented as a span.</param>
35+
/// <exception cref="ArgumentException">Length of <paramref name="x" /> must be same as length of <paramref name="y" />.</exception>
36+
/// <exception cref="ArgumentException">Destination is too short.</exception>
37+
/// <exception cref="ArgumentException"><paramref name="x"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
38+
/// <exception cref="ArgumentException"><paramref name="y"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
39+
/// <remarks>
40+
/// <para>
41+
/// This method effectively computes <c><paramref name="destination" />[i] = <typeparamref name="T"/>.MinMagnitudeNumber(<paramref name="x" />[i], <paramref name="y" />[i])</c>.
42+
/// </para>
43+
/// <para>
44+
/// The determination of the maximum magnitude matches the IEEE 754:2019 `minimumMagnitudeNumber` function.
45+
/// If the two values have the same magnitude and one is positive and the other is negative,
46+
/// the negative value is considered to have the smaller magnitude.
47+
/// </para>
48+
/// <para>
49+
/// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different
50+
/// operating systems or architectures.
51+
/// </para>
52+
/// </remarks>
53+
public static void MinMagnitudeNumber<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
54+
where T : INumberBase<T> =>
55+
InvokeSpanSpanIntoSpan<T, MinMagnitudeNumberOperator<T>>(x, y, destination);
56+
57+
/// <summary>Computes the element-wise number with the smallest magnitude in the specified tensors.</summary>
58+
/// <param name="x">The first tensor, represented as a span.</param>
59+
/// <param name="y">The second tensor, represented as a scalar.</param>
60+
/// <param name="destination">The destination tensor, represented as a span.</param>
61+
/// <exception cref="ArgumentException">Destination is too short.</exception>
62+
/// <exception cref="ArgumentException"><paramref name="x"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
63+
/// <remarks>
64+
/// <para>
65+
/// This method effectively computes <c><paramref name="destination" />[i] = <typeparamref name="T"/>.MinMagnitudeNumber(<paramref name="x" />[i], <paramref name="y" />)</c>.
66+
/// </para>
67+
/// <para>
68+
/// The determination of the maximum magnitude matches the IEEE 754:2019 `minimumMagnitudeNumber` function.
69+
/// If the two values have the same magnitude and one is positive and the other is negative,
70+
/// the negative value is considered to have the smaller magnitude.
71+
/// </para>
72+
/// <para>
73+
/// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different
74+
/// operating systems or architectures.
75+
/// </para>
76+
/// </remarks>
77+
public static void MinMagnitudeNumber<T>(ReadOnlySpan<T> x, T y, Span<T> destination)
78+
where T : INumberBase<T> =>
79+
InvokeSpanScalarIntoSpan<T, MinMagnitudeNumberOperator<T>>(x, y, destination);
80+
1281
/// <summary>Operator to get x or y based on which has the smaller MathF.Abs</summary>
1382
internal readonly struct MinMagnitudeNumberOperator<T> : IAggregationOperator<T>
1483
where T : INumberBase<T>

src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,14 @@ public static IEnumerable<object[]> SpanSpanDestinationFunctionsToTest()
522522
yield return Create(TensorPrimitives.Hypot, T.Hypot);
523523
yield return Create(TensorPrimitives.Ieee754Remainder, T.Ieee754Remainder);
524524
yield return Create(TensorPrimitives.Log, T.Log);
525+
yield return Create(TensorPrimitives.Max, T.Max);
525526
yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber);
527+
yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude);
528+
yield return Create(TensorPrimitives.MaxMagnitudeNumber, T.MaxMagnitudeNumber);
529+
yield return Create(TensorPrimitives.Min, T.Min);
526530
yield return Create(TensorPrimitives.MinNumber, T.MinNumber);
531+
yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude);
532+
yield return Create(TensorPrimitives.MinMagnitudeNumber, T.MinMagnitudeNumber);
527533
yield return Create(TensorPrimitives.Pow, T.Pow, Helpers.DetermineTolerance<T>(doubleTolerance: 1e-13, floatTolerance: 1e-5f));
528534

529535
static object[] Create(SpanSpanDestinationDelegate tensorPrimitivesMethod, Func<T, T, T> expectedMethod, T? tolerance = null)
@@ -656,11 +662,13 @@ public static IEnumerable<object[]> SpanScalarDestinationFunctionsToTest()
656662
yield return Create(TensorPrimitives.Pow, T.Pow, Helpers.DetermineTolerance<T>(doubleTolerance: 1e-13, floatTolerance: 1e-5f));
657663
yield return Create(TensorPrimitives.Log, T.Log);
658664
yield return Create(TensorPrimitives.Max, T.Max);
659-
yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude);
660665
yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber);
666+
yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude);
667+
yield return Create(TensorPrimitives.MaxMagnitudeNumber, T.MaxMagnitudeNumber);
661668
yield return Create(TensorPrimitives.Min, T.Min);
662-
yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude);
663669
yield return Create(TensorPrimitives.MinNumber, T.MinNumber);
670+
yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude);
671+
yield return Create(TensorPrimitives.MinMagnitudeNumber, T.MinMagnitudeNumber);
664672

665673
static object[] Create(SpanScalarDestinationDelegate<T, T, T> tensorPrimitivesMethod, Func<T, T, T> expectedMethod, T? tolerance = null)
666674
=> new object[] { tensorPrimitivesMethod, expectedMethod, tolerance };
@@ -1841,11 +1849,13 @@ public static IEnumerable<object[]> SpanScalarDestinationFunctionsToTest()
18411849
yield return Create(TensorPrimitives.BitwiseAnd, (x, y) => x & y);
18421850
yield return Create(TensorPrimitives.BitwiseOr, (x, y) => x | y);
18431851
yield return Create(TensorPrimitives.Max, T.Max);
1844-
yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude);
18451852
yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber);
1853+
yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude);
1854+
yield return Create(TensorPrimitives.MaxMagnitudeNumber, T.MaxMagnitudeNumber);
18461855
yield return Create(TensorPrimitives.Min, T.Min);
1847-
yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude);
18481856
yield return Create(TensorPrimitives.MinNumber, T.MinNumber);
1857+
yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude);
1858+
yield return Create(TensorPrimitives.MinMagnitudeNumber, T.MinMagnitudeNumber);
18491859
yield return Create(TensorPrimitives.Xor, (x, y) => x ^ y);
18501860

18511861
static object[] Create(SpanScalarDestinationDelegate<T, T, T> tensorPrimitivesMethod, Func<T, T, T> expectedMethod)

0 commit comments

Comments
 (0)