Skip to content
Open
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 @@ -989,9 +989,13 @@ public static void Ieee754Remainder<T>(System.ReadOnlySpan<T> x, T y, System.Spa
public static void Ieee754Remainder<T>(T x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.IFloatingPointIeee754<T> { }
public static void ILogB<T>(System.ReadOnlySpan<T> x, System.Span<int> destination) where T : System.Numerics.IFloatingPointIeee754<T> { }
public static void Increment<T>(System.ReadOnlySpan<T> x, System.Span<T> destination) where T : System.Numerics.IIncrementOperators<T> { }
public static int IndexOfMaxMagnitudeNumber<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static int IndexOfMaxMagnitude<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static int IndexOfMaxNumber<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static int IndexOfMax<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static int IndexOfMinMagnitudeNumber<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static int IndexOfMinMagnitude<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static int IndexOfMinNumber<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static int IndexOfMin<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumber<T> { throw null; }
public static bool IsCanonicalAll<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
public static bool IsCanonicalAny<T>(System.ReadOnlySpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,12 @@
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Increment.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IndexOfMax.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IndexOfMaxMagnitude.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IndexOfMaxMagnitudeNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IndexOfMaxNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IndexOfMin.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IndexOfMinMagnitude.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IndexOfMinMagnitudeNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IndexOfMinNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IsCanonical.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IsComplexNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.IsEvenInteger.cs" />
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static int IndexOfMax<T>(ReadOnlySpan<T> x)
/// <summary>Returns the index of MathF.Max(x, y)</summary>
internal readonly struct IndexOfMaxOperator<T> : IIndexOfMinMaxOperator<T> where T : INumber<T>
{
public static bool ShouldEarlyExitOnNan => true;
public static T Aggregate(Vector128<T> x) => HorizontalAggregate<T, MaxOperator<T>>(x);
public static T Aggregate(Vector256<T> x) => HorizontalAggregate<T, MaxOperator<T>>(x);
public static T Aggregate(Vector512<T> x) => HorizontalAggregate<T, MaxOperator<T>>(x);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static int IndexOfMaxMagnitude<T>(ReadOnlySpan<T> x)

internal readonly struct IndexOfMaxMagnitudeOperator<T> : IIndexOfMinMaxOperator<T> where T : INumber<T>
{
public static bool ShouldEarlyExitOnNan => true;
public static T Aggregate(Vector128<T> x) => HorizontalAggregate<T, MaxMagnitudeOperator<T>>(x);
public static T Aggregate(Vector256<T> x) => HorizontalAggregate<T, MaxMagnitudeOperator<T>>(x);
public static T Aggregate(Vector512<T> x) => HorizontalAggregate<T, MaxMagnitudeOperator<T>>(x);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using static System.Numerics.Tensors.TensorOperation;

namespace System.Numerics.Tensors
{
public static partial class TensorPrimitives
{
/// <summary>Searches for the index of the non-NaN number with the largest magnitude in the specified tensor.</summary>
/// <param name="x">The tensor, represented as a span.</param>
/// <returns>The index of the element in <paramref name="x"/> with the largest magnitude (absolute value), or -1 if <paramref name="x"/> is empty or only contain NaN-values.</returns>
/// <remarks>
/// <para>
/// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitudeNumber` function. NaN-values are ignored.
/// 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 int IndexOfMaxMagnitudeNumber<T>(ReadOnlySpan<T> x)
where T : INumber<T> =>
IndexOfMinMaxCore<T, IndexOfMaxMagnitudeNumberOperator<T>>(x);

internal readonly struct IndexOfMaxMagnitudeNumberOperator<T> : IIndexOfMinMaxOperator<T> where T : INumber<T>
{
public static bool ShouldEarlyExitOnNan => false;
public static T Aggregate(Vector128<T> x) => HorizontalAggregate<T, MaxMagnitudeNumberOperator<T>>(x);
public static T Aggregate(Vector256<T> x) => HorizontalAggregate<T, MaxMagnitudeNumberOperator<T>>(x);
public static T Aggregate(Vector512<T> x) => HorizontalAggregate<T, MaxMagnitudeNumberOperator<T>>(x);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Compare(T x, T y)
{
if (T.IsNaN(x))
{
return false;
}
else if (T.IsNaN(y))
{
return true;
}

// Don't use T.Abs since it can throw OverflowException.
T result = T.MaxMagnitude(x, y);
if (result == x)
{
if (result == y)
{
// x and y are equal in magnitude
return T.IsPositive(x) && T.IsNegative(y);
}
else
{
// x == result && y != result means x has larger magnitude than y.
return true;
}
}
else
{
return false;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<T> Compare(Vector128<T> x, Vector128<T> y)
{
Vector128<T> xMag = Vector128.Abs(x), yMag = Vector128.Abs(y);
if (typeof(T) == typeof(double) || typeof(T) == typeof(float))
{
Vector128<T> equalResult = Vector128.IsPositive(x) & Vector128.IsNegative(y);
Vector128<T> notNanResult = Vector128.GreaterThan(xMag, yMag) | (Vector128.Equals(xMag, yMag) & equalResult);
return notNanResult | Vector128.IsNaN(y); // notNanResult will be false if x is NaN
}
else if (typeof(T) == typeof(sbyte)
|| typeof(T) == typeof(short)
|| typeof(T) == typeof(int)
|| typeof(T) == typeof(long)
|| typeof(T) == typeof(nint))
{
// Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude.
Vector128<T> equalResult = Vector128.IsPositive(x) & Vector128.IsNegative(y);
Vector128<T> nonOverflowResult = Vector128.GreaterThan(xMag, yMag) | (Vector128.Equals(xMag, yMag) & equalResult);
return Vector128.AndNot(nonOverflowResult | Vector128.IsNegative(xMag), Vector128.IsNegative(yMag));
}
else
{
return Vector128.GreaterThan(xMag, yMag);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<T> Compare(Vector256<T> x, Vector256<T> y)
{
Vector256<T> xMag = Vector256.Abs(x), yMag = Vector256.Abs(y);
if (typeof(T) == typeof(double) || typeof(T) == typeof(float))
{
Vector256<T> equalResult = Vector256.IsPositive(x) & Vector256.IsNegative(y);
Vector256<T> notNanResult = Vector256.GreaterThan(xMag, yMag) | (Vector256.Equals(xMag, yMag) & equalResult);
return notNanResult | Vector256.IsNaN(y); // notNanResult will be false if x is NaN
}
else if (typeof(T) == typeof(sbyte)
|| typeof(T) == typeof(short)
|| typeof(T) == typeof(int)
|| typeof(T) == typeof(long)
|| typeof(T) == typeof(nint))
{
// Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude.
Vector256<T> equalResult = Vector256.IsPositive(x) & Vector256.IsNegative(y);
Vector256<T> nonOverflowResult = Vector256.GreaterThan(xMag, yMag) | (Vector256.Equals(xMag, yMag) & equalResult);
return Vector256.AndNot(nonOverflowResult | Vector256.IsNegative(xMag), Vector256.IsNegative(yMag));
}
else
{
return Vector256.GreaterThan(xMag, yMag);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector512<T> Compare(Vector512<T> x, Vector512<T> y)
{
Vector512<T> xMag = Vector512.Abs(x), yMag = Vector512.Abs(y);
if (typeof(T) == typeof(double) || typeof(T) == typeof(float))
{
Vector512<T> equalResult = Vector512.IsPositive(x) & Vector512.IsNegative(y);
Vector512<T> notNanResult = Vector512.GreaterThan(xMag, yMag) | (Vector512.Equals(xMag, yMag) & equalResult);
return notNanResult | Vector512.IsNaN(y); // notNanResult will be false if x is NaN
}
else if (typeof(T) == typeof(sbyte)
|| typeof(T) == typeof(short)
|| typeof(T) == typeof(int)
|| typeof(T) == typeof(long)
|| typeof(T) == typeof(nint))
{
// Consider overflows (when IsNegative(Abs(x))) from Abs(MinValue) which implies maximum magnitude.
Vector512<T> equalResult = Vector512.IsPositive(x) & Vector512.IsNegative(y);
Vector512<T> nonOverflowResult = Vector512.GreaterThan(xMag, yMag) | (Vector512.Equals(xMag, yMag) & equalResult);
return Vector512.AndNot(nonOverflowResult | Vector512.IsNegative(xMag), Vector512.IsNegative(yMag));
}
else
{
return Vector512.GreaterThan(xMag, yMag);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace System.Numerics.Tensors
{
public static partial class TensorPrimitives
{
/// <summary>Searches for the index of the largest non-NaN number in the specified tensor.</summary>
/// <param name="x">The tensor, represented as a span.</param>
/// <returns>The index of the maximum element in <paramref name="x"/>, or -1 if <paramref name="x"/> is empty or only contain NaN-values.</returns>
/// <remarks>
/// <para>
/// The determination of the maximum element matches the IEEE 754:2019 `maximumNumber` function. NaN-values are ignored.
/// Positive 0 is considered greater than negative 0.
/// </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 int IndexOfMaxNumber<T>(ReadOnlySpan<T> x)
where T : INumber<T> =>
IndexOfMinMaxCore<T, IndexOfMaxNumberOperator<T>>(x);

internal readonly struct IndexOfMaxNumberOperator<T> : IIndexOfMinMaxOperator<T> where T : INumber<T>
{
public static bool ShouldEarlyExitOnNan => false;
public static T Aggregate(Vector128<T> x) => HorizontalAggregate<T, MaxNumberOperator<T>>(x);
public static T Aggregate(Vector256<T> x) => HorizontalAggregate<T, MaxNumberOperator<T>>(x);
public static T Aggregate(Vector512<T> x) => HorizontalAggregate<T, MaxNumberOperator<T>>(x);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Compare(T x, T y)
{
if (T.IsNaN(x))
{
return false;
}
else if (T.IsNaN(y))
{
return true;
}

if (x == y)
{
return T.IsPositive(x) && T.IsNegative(y);
}
else
{
return x > y;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<T> Compare(Vector128<T> x, Vector128<T> y)
{
if (typeof(T) == typeof(double) || typeof(T) == typeof(float))
{
Vector128<T> equalResult = Vector128.IsPositive(x) & Vector128.IsNegative(y);
Vector128<T> notNanResult = Vector128.GreaterThan(x, y) | (Vector128.Equals(x, y) & equalResult);
return notNanResult | Vector128.IsNaN(y); // notNanResult will be false if x is NaN
}
else
{
return Vector128.GreaterThan(x, y);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector256<T> Compare(Vector256<T> x, Vector256<T> y)
{
if (typeof(T) == typeof(double) || typeof(T) == typeof(float))
{
Vector256<T> equalResult = Vector256.IsPositive(x) & Vector256.IsNegative(y);
Vector256<T> notNanResult = Vector256.GreaterThan(x, y) | (Vector256.Equals(x, y) & equalResult);
return notNanResult | Vector256.IsNaN(y); // notNanResult will be false if x is NaN
}
else
{
return Vector256.GreaterThan(x, y);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector512<T> Compare(Vector512<T> x, Vector512<T> y)
{
if (typeof(T) == typeof(double) || typeof(T) == typeof(float))
{
Vector512<T> equalResult = Vector512.IsPositive(x) & Vector512.IsNegative(y);
Vector512<T> notNanResult = Vector512.GreaterThan(x, y) | (Vector512.Equals(x, y) & equalResult);
return notNanResult | Vector512.IsNaN(y); // notNanResult will be false if x is NaN
}
else
{
return Vector512.GreaterThan(x, y);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static int IndexOfMin<T>(ReadOnlySpan<T> x)
/// <summary>Returns the index of MathF.Min(x, y)</summary>
internal readonly struct IndexOfMinOperator<T> : IIndexOfMinMaxOperator<T> where T : INumber<T>
{
public static bool ShouldEarlyExitOnNan => true;
public static T Aggregate(Vector128<T> x) => HorizontalAggregate<T, MinOperator<T>>(x);
public static T Aggregate(Vector256<T> x) => HorizontalAggregate<T, MinOperator<T>>(x);
public static T Aggregate(Vector512<T> x) => HorizontalAggregate<T, MinOperator<T>>(x);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static int IndexOfMinMagnitude<T>(ReadOnlySpan<T> x)

internal readonly struct IndexOfMinMagnitudeOperator<T> : IIndexOfMinMaxOperator<T> where T : INumber<T>
{
public static bool ShouldEarlyExitOnNan => true;
public static T Aggregate(Vector128<T> x) => HorizontalAggregate<T, MinMagnitudeOperator<T>>(x);
public static T Aggregate(Vector256<T> x) => HorizontalAggregate<T, MinMagnitudeOperator<T>>(x);
public static T Aggregate(Vector512<T> x) => HorizontalAggregate<T, MinMagnitudeOperator<T>>(x);
Expand Down
Loading
Loading