Skip to content

Commit a3d5261

Browse files
Adding vectorized implementations of Log2 to Vector64/128/256/512 (#96455)
* Adding vectorized implementations of Log2 to Vector64/128/256/512 * Accelerate TensorPrimitives.Log2<double>() * Undo a sln file change * Use the built-in Log2 implementation from Vector64/128/256/512 on .NET 9+ * Ensure the helpers are checking the correct types * Relocate the Vector64/128/256/512 assert extensions to avoid Mono LLVM trimming issues * Keep xunit happy
1 parent 33446fb commit a3d5261

File tree

19 files changed

+1193
-22
lines changed

19 files changed

+1193
-22
lines changed

src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
using System.Linq;
66
using System.Runtime.CompilerServices;
77
using System.Runtime.InteropServices;
8+
#if NET6_0_OR_GREATER
9+
using System.Runtime.Intrinsics;
10+
#endif
811
using System.Threading;
912
using System.Threading.Tasks;
1013
using Xunit;

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

Lines changed: 398 additions & 17 deletions
Large diffs are not rendered by default.

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,6 @@
602602
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector4.cs" />
603603
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector4.Extensions.cs" />
604604
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\VectorDebugView_1.cs" />
605-
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\VectorMath.cs" />
606605
<Compile Include="$(MSBuildThisFileDirectory)System\Object.cs" />
607606
<Compile Include="$(MSBuildThisFileDirectory)System\ObjectDisposedException.cs" />
608607
<Compile Include="$(MSBuildThisFileDirectory)System\ObsoleteAttribute.cs" />
@@ -1040,6 +1039,7 @@
10401039
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector64.cs" />
10411040
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector64_1.cs" />
10421041
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector64DebugView_1.cs" />
1042+
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\VectorMath.cs" />
10431043
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Enums.cs" />
10441044
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\JitInfo.cs" />
10451045
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Loader\AssemblyLoadContext.cs" />

src/libraries/System.Private.CoreLib/src/System/Double.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ public readonly struct Double
105105
internal const int TrailingSignificandLength = 52;
106106
internal const int SignificandLength = TrailingSignificandLength + 1;
107107

108+
internal const long PositiveInfinityBits = 0x7FF00000_00000000;
109+
internal const long SmallestNormalBits = 0x00100000_00000000;
110+
108111
internal ushort BiasedExponent
109112
{
110113
get

src/libraries/System.Private.CoreLib/src/System/Math.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,9 @@ public static double BitIncrement(double x)
292292
[MethodImpl(MethodImplOptions.AggressiveInlining)]
293293
public static double CopySign(double x, double y)
294294
{
295-
if (Sse2.IsSupported || AdvSimd.IsSupported)
295+
if (Vector128.IsHardwareAccelerated)
296296
{
297-
return VectorMath.ConditionalSelectBitwise(Vector128.CreateScalarUnsafe(-0.0), Vector128.CreateScalarUnsafe(y), Vector128.CreateScalarUnsafe(x)).ToScalar();
297+
return Vector128.ConditionalSelect(Vector128.CreateScalarUnsafe(-0.0), Vector128.CreateScalarUnsafe(y), Vector128.CreateScalarUnsafe(x)).ToScalar();
298298
}
299299
else
300300
{

src/libraries/System.Private.CoreLib/src/System/MathF.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ public static float BitIncrement(float x)
105105
[MethodImpl(MethodImplOptions.AggressiveInlining)]
106106
public static float CopySign(float x, float y)
107107
{
108-
if (Sse.IsSupported || AdvSimd.IsSupported)
108+
if (Vector128.IsHardwareAccelerated)
109109
{
110-
return VectorMath.ConditionalSelectBitwise(Vector128.CreateScalarUnsafe(-0.0f), Vector128.CreateScalarUnsafe(y), Vector128.CreateScalarUnsafe(x)).ToScalar();
110+
return Vector128.ConditionalSelect(Vector128.CreateScalarUnsafe(-0.0f), Vector128.CreateScalarUnsafe(y), Vector128.CreateScalarUnsafe(x)).ToScalar();
111111
}
112112
else
113113
{

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,38 @@ internal static Vector128<ushort> LoadUnsafe(ref char source) =>
17811781
internal static Vector128<ushort> LoadUnsafe(ref char source, nuint elementOffset) =>
17821782
LoadUnsafe(ref Unsafe.As<char, ushort>(ref source), elementOffset);
17831783

1784+
/// <inheritdoc cref="Vector64.Log2(Vector64{double})" />
1785+
public static Vector128<double> Log2(Vector128<double> vector)
1786+
{
1787+
if (IsHardwareAccelerated)
1788+
{
1789+
return VectorMath.Log2Double<Vector128<double>, Vector128<long>, Vector128<ulong>>(vector);
1790+
}
1791+
else
1792+
{
1793+
return Create(
1794+
Vector64.Log2(vector._lower),
1795+
Vector64.Log2(vector._upper)
1796+
);
1797+
}
1798+
}
1799+
1800+
/// <inheritdoc cref="Vector64.Log2(Vector64{float})" />
1801+
public static Vector128<float> Log2(Vector128<float> vector)
1802+
{
1803+
if (IsHardwareAccelerated)
1804+
{
1805+
return VectorMath.Log2Single<Vector128<float>, Vector128<int>, Vector128<uint>>(vector);
1806+
}
1807+
else
1808+
{
1809+
return Create(
1810+
Vector64.Log2(vector._lower),
1811+
Vector64.Log2(vector._upper)
1812+
);
1813+
}
1814+
}
1815+
17841816
/// <summary>Computes the maximum of two vectors on a per-element basis.</summary>
17851817
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
17861818
/// <param name="left">The vector to compare with <paramref name="right" />.</param>

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,38 @@ internal static Vector256<ushort> LoadUnsafe(ref char source) =>
17551755
internal static Vector256<ushort> LoadUnsafe(ref char source, nuint elementOffset) =>
17561756
LoadUnsafe(ref Unsafe.As<char, ushort>(ref source), elementOffset);
17571757

1758+
/// <inheritdoc cref="Vector128.Log2(Vector128{double})" />
1759+
public static Vector256<double> Log2(Vector256<double> vector)
1760+
{
1761+
if (IsHardwareAccelerated)
1762+
{
1763+
return VectorMath.Log2Double<Vector256<double>, Vector256<long>, Vector256<ulong>>(vector);
1764+
}
1765+
else
1766+
{
1767+
return Create(
1768+
Vector128.Log2(vector._lower),
1769+
Vector128.Log2(vector._upper)
1770+
);
1771+
}
1772+
}
1773+
1774+
/// <inheritdoc cref="Vector128.Log2(Vector128{float})" />
1775+
public static Vector256<float> Log2(Vector256<float> vector)
1776+
{
1777+
if (IsHardwareAccelerated)
1778+
{
1779+
return VectorMath.Log2Single<Vector256<float>, Vector256<int>, Vector256<uint>>(vector);
1780+
}
1781+
else
1782+
{
1783+
return Create(
1784+
Vector128.Log2(vector._lower),
1785+
Vector128.Log2(vector._upper)
1786+
);
1787+
}
1788+
}
1789+
17581790
/// <summary>Computes the maximum of two vectors on a per-element basis.</summary>
17591791
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
17601792
/// <param name="left">The vector to compare with <paramref name="right" />.</param>

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,38 @@ internal static Vector512<ushort> LoadUnsafe(ref char source) =>
18061806
internal static Vector512<ushort> LoadUnsafe(ref char source, nuint elementOffset) =>
18071807
LoadUnsafe(ref Unsafe.As<char, ushort>(ref source), elementOffset);
18081808

1809+
/// <inheritdoc cref="Vector256.Log2(Vector256{double})" />
1810+
public static Vector512<double> Log2(Vector512<double> vector)
1811+
{
1812+
if (IsHardwareAccelerated)
1813+
{
1814+
return VectorMath.Log2Double<Vector512<double>, Vector512<long>, Vector512<ulong>>(vector);
1815+
}
1816+
else
1817+
{
1818+
return Create(
1819+
Vector256.Log2(vector._lower),
1820+
Vector256.Log2(vector._upper)
1821+
);
1822+
}
1823+
}
1824+
1825+
/// <inheritdoc cref="Vector256.Log2(Vector256{float})" />
1826+
public static Vector512<float> Log2(Vector512<float> vector)
1827+
{
1828+
if (IsHardwareAccelerated)
1829+
{
1830+
return VectorMath.Log2Single<Vector512<float>, Vector512<int>, Vector512<uint>>(vector);
1831+
}
1832+
else
1833+
{
1834+
return Create(
1835+
Vector256.Log2(vector._lower),
1836+
Vector256.Log2(vector._upper)
1837+
);
1838+
}
1839+
}
1840+
18091841
/// <summary>Computes the maximum of two vectors on a per-element basis.</summary>
18101842
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
18111843
/// <param name="left">The vector to compare with <paramref name="right" />.</param>

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,50 @@ public static Vector64<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffs
15711571
return Unsafe.ReadUnaligned<Vector64<T>>(in address);
15721572
}
15731573

1574+
internal static Vector64<T> Log2<T>(Vector64<T> vector)
1575+
where T : ILogarithmicFunctions<T>
1576+
{
1577+
Unsafe.SkipInit(out Vector64<T> result);
1578+
1579+
for (int index = 0; index < Vector64<T>.Count; index++)
1580+
{
1581+
T value = T.Log2(vector.GetElement(index));
1582+
result.SetElementUnsafe(index, value);
1583+
}
1584+
1585+
return result;
1586+
}
1587+
1588+
/// <summary>Computes the log2 of each element in a vector.</summary>
1589+
/// <param name="vector">The vector that will have its log2 computed.</param>
1590+
/// <returns>A vector whose elements are the log2 of the elements in <paramref name="vector" />.</returns>
1591+
public static Vector64<double> Log2(Vector64<double> vector)
1592+
{
1593+
if (IsHardwareAccelerated)
1594+
{
1595+
return VectorMath.Log2Double<Vector64<double>, Vector64<long>, Vector64<ulong>>(vector);
1596+
}
1597+
else
1598+
{
1599+
return Log2<double>(vector);
1600+
}
1601+
}
1602+
1603+
/// <summary>Computes the log2 of each element in a vector.</summary>
1604+
/// <param name="vector">The vector that will have its log2 computed.</param>
1605+
/// <returns>A vector whose elements are the log2 of the elements in <paramref name="vector" />.</returns>
1606+
public static Vector64<float> Log2(Vector64<float> vector)
1607+
{
1608+
if (IsHardwareAccelerated)
1609+
{
1610+
return VectorMath.Log2Single<Vector64<float>, Vector64<int>, Vector64<uint>>(vector);
1611+
}
1612+
else
1613+
{
1614+
return Log2<float>(vector);
1615+
}
1616+
}
1617+
15741618
/// <summary>Computes the maximum of two vectors on a per-element basis.</summary>
15751619
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
15761620
/// <param name="left">The vector to compare with <paramref name="right" />.</param>

0 commit comments

Comments
 (0)