Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TensorPrimitives.{Max/Min}MagnitudeNumber #104651

Merged
merged 1 commit into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,9 @@ public static void Log10<T>(System.ReadOnlySpan<T> x, System.Span<T> destination
public static T MaxMagnitude<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
public static void MaxMagnitude<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
public static void MaxMagnitude<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
public static T MaxMagnitudeNumber<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
public static void MaxMagnitudeNumber<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
public static void MaxMagnitudeNumber<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
public static T Max<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static void Max<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumber<T> { }
public static void Max<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumber<T> { }
Expand All @@ -485,6 +488,9 @@ public static void MaxNumber<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> de
public static T MinMagnitude<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
public static void MinMagnitude<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
public static void MinMagnitude<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
public static T MinMagnitudeNumber<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
public static void MinMagnitudeNumber<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
public static void MinMagnitudeNumber<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumberBase<T> { }
public static T Min<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static void Min<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.INumber<T> { }
public static void Min<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.INumber<T> { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,75 @@ namespace System.Numerics.Tensors
{
public static partial class TensorPrimitives
{
/// <summary>Searches for the number with the largest magnitude in the specified tensor.</summary>
/// <param name="x">The tensor, represented as a span.</param>
/// <returns>The element in <paramref name="x"/> with the largest magnitude (absolute value).</returns>
/// <exception cref="ArgumentException">Length of <paramref name="x" /> must be greater than zero.</exception>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
public static T MaxMagnitudeNumber<T>(ReadOnlySpan<T> x)
where T : INumberBase<T> =>
MinMaxCore<T, MaxMagnitudeNumberOperator<T>>(x);

/// <summary>Computes the element-wise number with the largest magnitude in the specified tensors.</summary>
/// <param name="x">The first tensor, represented as a span.</param>
/// <param name="y">The second tensor, represented as a span.</param>
/// <param name="destination">The destination tensor, represented as a span.</param>
/// <exception cref="ArgumentException">Length of <paramref name="x" /> must be same as length of <paramref name="y" />.</exception>
/// <exception cref="ArgumentException">Destination is too short.</exception>
/// <exception cref="ArgumentException"><paramref name="x"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
/// <exception cref="ArgumentException"><paramref name="y"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
/// <remarks>
/// <para>
/// This method effectively computes <c><paramref name="destination" />[i] = <typeparamref name="T"/>.MaxMagnitudeNumber(<paramref name="x" />[i], <paramref name="y" />[i])</c>.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
public static void MaxMagnitudeNumber<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
where T : INumberBase<T> =>
InvokeSpanSpanIntoSpan<T, MaxMagnitudeNumberOperator<T>>(x, y, destination);

/// <summary>Computes the element-wise number with the largest magnitude in the specified tensors.</summary>
/// <param name="x">The first tensor, represented as a span.</param>
/// <param name="y">The second tensor, represented as a scalar.</param>
/// <param name="destination">The destination tensor, represented as a span.</param>
/// <exception cref="ArgumentException">Destination is too short.</exception>
/// <exception cref="ArgumentException"><paramref name="x"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
/// <remarks>
/// <para>
/// This method effectively computes <c><paramref name="destination" />[i] = <typeparamref name="T"/>.MaxMagnitudeNumber(<paramref name="x" />[i], <paramref name="y" />)</c>.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
public static void MaxMagnitudeNumber<T>(ReadOnlySpan<T> x, T y, Span<T> destination)
where T : INumberBase<T> =>
InvokeSpanScalarIntoSpan<T, MaxMagnitudeNumberOperator<T>>(x, y, destination);

/// <summary>Operator to get x or y based on which has the larger MathF.Abs</summary>
internal readonly struct MaxMagnitudeNumberOperator<T> : IAggregationOperator<T>
where T : INumberBase<T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,75 @@ namespace System.Numerics.Tensors
{
public static partial class TensorPrimitives
{
/// <summary>Searches for the number with the smallest magnitude in the specified tensor.</summary>
/// <param name="x">The tensor, represented as a span.</param>
/// <returns>The element in <paramref name="x"/> with the smallest magnitude (absolute value).</returns>
/// <exception cref="ArgumentException">Length of <paramref name="x" /> must be greater than zero.</exception>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
public static T MinMagnitudeNumber<T>(ReadOnlySpan<T> x)
where T : INumberBase<T> =>
MinMaxCore<T, MinMagnitudeNumberOperator<T>>(x);

/// <summary>Computes the element-wise number with the smallest magnitude in the specified tensors.</summary>
/// <param name="x">The first tensor, represented as a span.</param>
/// <param name="y">The second tensor, represented as a span.</param>
/// <param name="destination">The destination tensor, represented as a span.</param>
/// <exception cref="ArgumentException">Length of <paramref name="x" /> must be same as length of <paramref name="y" />.</exception>
/// <exception cref="ArgumentException">Destination is too short.</exception>
/// <exception cref="ArgumentException"><paramref name="x"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
/// <exception cref="ArgumentException"><paramref name="y"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
/// <remarks>
/// <para>
/// This method effectively computes <c><paramref name="destination" />[i] = <typeparamref name="T"/>.MinMagnitudeNumber(<paramref name="x" />[i], <paramref name="y" />[i])</c>.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
public static void MinMagnitudeNumber<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
where T : INumberBase<T> =>
InvokeSpanSpanIntoSpan<T, MinMagnitudeNumberOperator<T>>(x, y, destination);

/// <summary>Computes the element-wise number with the smallest magnitude in the specified tensors.</summary>
/// <param name="x">The first tensor, represented as a span.</param>
/// <param name="y">The second tensor, represented as a scalar.</param>
/// <param name="destination">The destination tensor, represented as a span.</param>
/// <exception cref="ArgumentException">Destination is too short.</exception>
/// <exception cref="ArgumentException"><paramref name="x"/> and <paramref name="destination"/> reference overlapping memory locations and do not begin at the same location.</exception>
/// <remarks>
/// <para>
/// This method effectively computes <c><paramref name="destination" />[i] = <typeparamref name="T"/>.MinMagnitudeNumber(<paramref name="x" />[i], <paramref name="y" />)</c>.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
public static void MinMagnitudeNumber<T>(ReadOnlySpan<T> x, T y, Span<T> destination)
where T : INumberBase<T> =>
InvokeSpanScalarIntoSpan<T, MinMagnitudeNumberOperator<T>>(x, y, destination);

/// <summary>Operator to get x or y based on which has the smaller MathF.Abs</summary>
internal readonly struct MinMagnitudeNumberOperator<T> : IAggregationOperator<T>
where T : INumberBase<T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,14 @@ public static IEnumerable<object[]> 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<T>(doubleTolerance: 1e-13, floatTolerance: 1e-5f));

static object[] Create(SpanSpanDestinationDelegate tensorPrimitivesMethod, Func<T, T, T> expectedMethod, T? tolerance = null)
Expand Down Expand Up @@ -656,11 +662,13 @@ public static IEnumerable<object[]> SpanScalarDestinationFunctionsToTest()
yield return Create(TensorPrimitives.Pow, T.Pow, Helpers.DetermineTolerance<T>(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<T, T, T> tensorPrimitivesMethod, Func<T, T, T> expectedMethod, T? tolerance = null)
=> new object[] { tensorPrimitivesMethod, expectedMethod, tolerance };
Expand Down Expand Up @@ -1841,11 +1849,13 @@ public static IEnumerable<object[]> 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<T, T, T> tensorPrimitivesMethod, Func<T, T, T> expectedMethod)
Expand Down
Loading