Skip to content

Commit

Permalink
Ensure that TensorPrimitives uses the in-box vector operations on .NE…
Browse files Browse the repository at this point in the history
…T 9+
  • Loading branch information
tannergooding committed Jun 21, 2024
1 parent 0816d54 commit 8e211ce
Show file tree
Hide file tree
Showing 19 changed files with 979 additions and 632 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.LogP1.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Max.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.MaxMagnitude.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.MaxMagnitudeNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.MaxNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Min.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.MinMagnitude.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.MinMagnitudeNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.MinNumber.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Multiply.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.MultiplyAdd.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ public static float Max(ReadOnlySpan<float> x) =>
/// </para>
/// </remarks>
public static void Max(ReadOnlySpan<float> x, ReadOnlySpan<float> y, Span<float> destination) =>
InvokeSpanSpanIntoSpan<MaxPropagateNaNOperator_Single>(x, y, destination);
InvokeSpanSpanIntoSpan<MaxOperator>(x, y, destination);

/// <summary>Searches for the single-precision floating-point number with the largest magnitude in the specified tensor.</summary>
/// <param name="x">The tensor, represented as a span.</param>
Expand Down Expand Up @@ -476,7 +476,7 @@ public static float MaxMagnitude(ReadOnlySpan<float> x) =>
/// </para>
/// </remarks>
public static void MaxMagnitude(ReadOnlySpan<float> x, ReadOnlySpan<float> y, Span<float> destination) =>
InvokeSpanSpanIntoSpan<MaxMagnitudePropagateNaNOperator_Single>(x, y, destination);
InvokeSpanSpanIntoSpan<MaxMagnitudeOperator>(x, y, destination);

/// <summary>Searches for the smallest single-precision floating-point number in the specified tensor.</summary>
/// <param name="x">The tensor, represented as a span.</param>
Expand Down Expand Up @@ -517,7 +517,7 @@ public static float Min(ReadOnlySpan<float> x) =>
/// </para>
/// </remarks>
public static void Min(ReadOnlySpan<float> x, ReadOnlySpan<float> y, Span<float> destination) =>
InvokeSpanSpanIntoSpan<MinPropagateNaNOperator_Single>(x, y, destination);
InvokeSpanSpanIntoSpan<MinOperator>(x, y, destination);

/// <summary>Searches for the single-precision floating-point number with the smallest magnitude in the specified tensor.</summary>
/// <param name="x">The tensor, represented as a span.</param>
Expand Down Expand Up @@ -558,7 +558,7 @@ public static float MinMagnitude(ReadOnlySpan<float> x) =>
/// </para>
/// </remarks>
public static void MinMagnitude(ReadOnlySpan<float> x, ReadOnlySpan<float> y, Span<float> destination) =>
InvokeSpanSpanIntoSpan<MinMagnitudePropagateNaNOperator_Single>(x, y, destination);
InvokeSpanSpanIntoSpan<MinMagnitudeOperator>(x, y, destination);

/// <summary>Computes the element-wise product of single-precision floating-point numbers in the specified tensors.</summary>
/// <param name="x">The first tensor, represented as a span.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public static void CopySign<T>(ReadOnlySpan<T> x, T sign, Span<T> destination)

public static Vector128<T> Invoke(Vector128<T> x, Vector128<T> y)
{
#if NET9_0_OR_GREATER
return Vector128.CopySign(x, y);
#else
if (typeof(T) == typeof(float))
{
return Vector128.ConditionalSelect(Vector128.Create(-0.0f).As<float, T>(), y, x);
Expand All @@ -71,10 +74,14 @@ public static Vector128<T> Invoke(Vector128<T> x, Vector128<T> y)
}

return x;
#endif
}

public static Vector256<T> Invoke(Vector256<T> x, Vector256<T> y)
{
#if NET9_0_OR_GREATER
return Vector256.CopySign(x, y);
#else
if (typeof(T) == typeof(float))
{
return Vector256.ConditionalSelect(Vector256.Create(-0.0f).As<float, T>(), y, x);
Expand All @@ -99,10 +106,14 @@ public static Vector256<T> Invoke(Vector256<T> x, Vector256<T> y)
}

return x;
#endif
}

public static Vector512<T> Invoke(Vector512<T> x, Vector512<T> y)
{
#if NET9_0_OR_GREATER
return Vector512.CopySign(x, y);
#else
if (typeof(T) == typeof(float))
{
return Vector512.ConditionalSelect(Vector512.Create(-0.0f).As<float, T>(), y, x);
Expand All @@ -127,6 +138,7 @@ public static Vector512<T> Invoke(Vector512<T> x, Vector512<T> y)
}

return x;
#endif
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Intrinsics;

namespace System.Numerics.Tensors
Expand All @@ -25,10 +26,59 @@ public static void DegreesToRadians<T>(ReadOnlySpan<T> x, Span<T> destination)
private readonly struct DegreesToRadiansOperator<T> : IUnaryOperator<T, T> where T : ITrigonometricFunctions<T>
{
public static bool Vectorizable => true;

public static T Invoke(T x) => T.DegreesToRadians(x);
public static Vector128<T> Invoke(Vector128<T> x) => (x * T.Pi) / T.CreateChecked(180);
public static Vector256<T> Invoke(Vector256<T> x) => (x * T.Pi) / T.CreateChecked(180);
public static Vector512<T> Invoke(Vector512<T> x) => (x * T.Pi) / T.CreateChecked(180);

public static Vector128<T> Invoke(Vector128<T> x)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector128.DegreesToRadians(x.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector128.DegreesToRadians(x.AsSingle()).As<float, T>();
}
#else
return (x * T.Pi) / T.CreateChecked(180);
#endif
}

public static Vector256<T> Invoke(Vector256<T> x)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector256.DegreesToRadians(x.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector256.DegreesToRadians(x.AsSingle()).As<float, T>();
}
#else
return (x * T.Pi) / T.CreateChecked(180);
#endif
}

public static Vector512<T> Invoke(Vector512<T> x)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector512.DegreesToRadians(x.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector512.DegreesToRadians(x.AsSingle()).As<float, T>();
}
#else
return (x * T.Pi) / T.CreateChecked(180);
#endif
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Intrinsics;

namespace System.Numerics.Tensors
Expand Down Expand Up @@ -29,10 +30,59 @@ public static void Hypot<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destin
where T : IRootFunctions<T>
{
public static bool Vectorizable => true;

public static T Invoke(T x, T y) => T.Hypot(x, y);
public static Vector128<T> Invoke(Vector128<T> x, Vector128<T> y) => Vector128.Sqrt((x * x) + (y * y));
public static Vector256<T> Invoke(Vector256<T> x, Vector256<T> y) => Vector256.Sqrt((x * x) + (y * y));
public static Vector512<T> Invoke(Vector512<T> x, Vector512<T> y) => Vector512.Sqrt((x * x) + (y * y));

public static Vector128<T> Invoke(Vector128<T> x, Vector128<T> y)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector128.Hypot(x.AsDouble(), y.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector128.Hypot(x.AsSingle(), y.AsSingle()).As<float, T>();
}
#else
return Vector128.Sqrt((x * x) + (y * y));
#endif
}

public static Vector256<T> Invoke(Vector256<T> x, Vector256<T> y)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector256.Hypot(x.AsDouble(), y.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector256.Hypot(x.AsSingle(), y.AsSingle()).As<float, T>();
}
#else
return Vector256.Sqrt((x * x) + (y * y));
#endif
}

public static Vector512<T> Invoke(Vector512<T> x, Vector512<T> y)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector512.Hypot(x.AsDouble(), y.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector512.Hypot(x.AsSingle(), y.AsSingle()).As<float, T>();
}
#else
return Vector512.Sqrt((x * x) + (y * y));
#endif
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Intrinsics;

namespace System.Numerics.Tensors
Expand Down Expand Up @@ -75,9 +76,57 @@ public static void Lerp<T>(ReadOnlySpan<T> x, T y, ReadOnlySpan<T> amount, Span<
private readonly struct LerpOperator<T> : ITernaryOperator<T> where T : IFloatingPointIeee754<T>
{
public static T Invoke(T x, T y, T amount) => T.Lerp(x, y, amount);
public static Vector128<T> Invoke(Vector128<T> x, Vector128<T> y, Vector128<T> amount) => (x * (Vector128<T>.One - amount)) + (y * amount);
public static Vector256<T> Invoke(Vector256<T> x, Vector256<T> y, Vector256<T> amount) => (x * (Vector256<T>.One - amount)) + (y * amount);
public static Vector512<T> Invoke(Vector512<T> x, Vector512<T> y, Vector512<T> amount) => (x * (Vector512<T>.One - amount)) + (y * amount);

public static Vector128<T> Invoke(Vector128<T> x, Vector128<T> y, Vector128<T> amount)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector128.Lerp(x.AsDouble(), y.AsDouble(), amount.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector128.Lerp(x.AsSingle(), y.AsSingle(), amount.AsSingle()).As<float, T>();
}
#else
return (x * (Vector128<T>.One - amount)) + (y * amount);
#endif
}

public static Vector256<T> Invoke(Vector256<T> x, Vector256<T> y, Vector256<T> amount)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector256.Lerp(x.AsDouble(), y.AsDouble(), amount.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector256.Lerp(x.AsSingle(), y.AsSingle(), amount.AsSingle()).As<float, T>();
}
#else
return (x * (Vector256<T>.One - amount)) + (y * amount);
#endif
}

public static Vector512<T> Invoke(Vector512<T> x, Vector512<T> y, Vector512<T> amount)
{
#if NET9_0_OR_GREATER
if (typeof(T) == typeof(double))
{
return Vector512.Lerp(x.AsDouble(), y.AsDouble(), amount.AsDouble()).As<double, T>();
}
else
{
Debug.Assert(typeof(T) == typeof(float));
return Vector512.Lerp(x.AsSingle(), y.AsSingle(), amount.AsSingle()).As<float, T>();
}
#else
return (x * (Vector512<T>.One - amount)) + (y * amount);
#endif
}
}
}
}
Loading

0 comments on commit 8e211ce

Please sign in to comment.