-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Vector64/128/256/512<T> and Vector<T> Consistency/Enhancements #76593
Comments
Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics Issue DetailsSummaryWe've exposed several APIs on Vector64/128/256 and recently approved Vector512. However, there are notably a few missing APIs that make it feel "incomplete". Such APIs were likely simply missed as part of previous review. API Proposalnamespace System.Numerics
{
public static partial class Vector
{
// Has AsVectorByte and friends, not AsByte and friends
public static Vector<T> Divide(Vector<T> left, T right);
public static T GetElement<T>(this Vector<T> vector, int index) where T : struct;
public static T Load<T>(T* source) where T : unmanaged;
public static T LoadAligned<T>(T* source) where T : unmanaged;
public static T LoadAlignedNonTemporal<T>(T* source) where T : unmanaged;
public static T LoadUnsafe<T>(ref T source) where T : struct;
public static T LoadUnsafe<T>(ref T source, nuint index) where T : struct;
// Shuffle is difficult to expose because the indices often should be "constant"
// Has SquareRoot, not Sqrt
public static T ToScalar<T>(this Vector<T> vector) where T : struct;
public static Vector<T> WithElement<T> (this Vector<T> vector, int index, T value) where T : struct;
}
public partial struct Vector<T>
{
public static Vector<T> AllBitsSet { get; }
// Has constructors, not Vector.Create()
// Has explicit cast operators
public static Vector<T> operator /(Vector<T> left, T right);
public static Vector<T> operator +(Vector<T> value);
}
}
namespace System.Runtime.Intrinsics.X86
{
public static partial class Vector64
{
public static Vector64<T> CreateScalar<T>(T value) where T : struct;
public static Vector64<T> CreateScalarUnsafe<T>(T value) where T : struct;
public static Vector64<long> CreateScalarUnsafe (long value);
public static Vector64<ulong> CreateScalarUnsafe (ulong value);
public static Vector64<T> Divide(Vector64<T> left, T right);
public static Vector64<ushort> WidenLower(Vector64<byte> value);
public static Vector64<int> WidenLower(Vector64<short> value);
public static Vector64<long> WidenLower(Vector64<int> value);
public static Vector64<short> WidenLower(Vector64<sbyte> value);
public static Vector64<double> WidenLower(Vector64<float> value);
public static Vector64<uint> WidenLower(Vector64<ushort> value);
public static Vector64<ulong> WidenLower(Vector64<uint> value);
public static Vector64<ushort> WidenUpper(Vector64<byte> value);
public static Vector64<int> WidenUpper(Vector64<short> value);
public static Vector64<long> WidenUpper(Vector64<int> value);
public static Vector64<short> WidenUpper(Vector64<sbyte> value);
public static Vector64<double> WidenUpper(Vector64<float> value);
public static Vector64<uint> WidenUpper(Vector64<ushort> value);
public static Vector64<ulong> WidenUpper(Vector64<uint> value);
}
public partial struct Vector64<T>
{
public static Vector64<T> One { get; }
public static Vector64<T> operator /(Vector64<T> left, T right);
public static Vector64<T> operator <<(Vector64<T> left, int shiftAmount);
public static Vector64<T> operator >>(Vector64<T> left, int shiftAmount);
public static Vector64<T> operator >>>(Vector64<T> left, int shiftAmount);
}
public static partial class Vector128
{
public static Vector128<T> Create<T>(Vector64<T> lower, Vector64<T> upper) where T : struct;
public static Vector128<nint> Create (Vector64<nint> lower, Vector64<nint> upper);
public static Vector128<nuint> Create (Vector64<nuint> lower, Vector64<nuint> upper);
public static Vector128<T> CreateScalar<T>(T value) where T : struct;
public static Vector128<T> CreateScalarUnsafe<T>(T value) where T : struct;
public static Vector128<T> Divide(Vector128<T> left, T right);
public static Vector128<ushort> WidenLower(Vector128<byte> value);
public static Vector128<int> WidenLower(Vector128<short> value);
public static Vector128<long> WidenLower(Vector128<int> value);
public static Vector128<short> WidenLower(Vector128<sbyte> value);
public static Vector128<double> WidenLower(Vector128<float> value);
public static Vector128<uint> WidenLower(Vector128<ushort> value);
public static Vector128<ulong> WidenLower(Vector128<uint> value);
public static Vector128<ushort> WidenUpper(Vector128<byte> value);
public static Vector128<int> WidenUpper(Vector128<short> value);
public static Vector128<long> WidenUpper(Vector128<int> value);
public static Vector128<short> WidenUpper(Vector128<sbyte> value);
public static Vector128<double> WidenUpper(Vector128<float> value);
public static Vector128<uint> WidenUpper(Vector128<ushort> value);
public static Vector128<ulong> WidenUpper(Vector128<uint> value);
}
public partial struct Vector128<T>
{
public static Vector128<T> One { get; }
public static Vector128<T> operator /(Vector128<T> left, T right);
public static Vector128<T> operator <<(Vector128<T> left, int shiftAmount);
public static Vector128<T> operator >>(Vector128<T> left, int shiftAmount);
public static Vector128<T> operator >>>(Vector128<T> left, int shiftAmount);
}
public static partial class Vector256
{
public static Vector256<T> Create<T>(Vector128<T> lower, Vector128<T> upper) where T : struct;
public static Vector256<nint> Create (Vector128<nint> lower, Vector128<nint> upper);
public static Vector256<nuint> Create (Vector128<nuint> lower, Vector128<nuint> upper);
public static Vector256<T> CreateScalar<T>(T value) where T : struct;
public static Vector256<T> CreateScalarUnsafe<T>(T value) where T : struct;
public static Vector256<T> Divide(Vector256<T> left, T right);
public static Vector256<ushort> WidenLower(Vector256<byte> value);
public static Vector256<int> WidenLower(Vector256<short> value);
public static Vector256<long> WidenLower(Vector256<int> value);
public static Vector256<short> WidenLower(Vector256<sbyte> value);
public static Vector256<double> WidenLower(Vector256<float> value);
public static Vector256<uint> WidenLower(Vector256<ushort> value);
public static Vector256<ulong> WidenLower(Vector256<uint> value);
public static Vector256<ushort> WidenUpper(Vector256<byte> value);
public static Vector256<int> WidenUpper(Vector256<short> value);
public static Vector256<long> WidenUpper(Vector256<int> value);
public static Vector256<short> WidenUpper(Vector256<sbyte> value);
public static Vector256<double> WidenUpper(Vector256<float> value);
public static Vector256<uint> WidenUpper(Vector256<ushort> value);
public static Vector256<ulong> WidenUpper(Vector256<uint> value);
}
public partial struct Vector256<T>
{
public static Vector256<T> One { get; }
public static Vector256<T> operator /(Vector256<T> left, T right);
public static Vector256<T> operator <<(Vector256<T> left, int shiftAmount);
public static Vector256<T> operator >>(Vector256<T> left, int shiftAmount);
public static Vector256<T> operator >>>(Vector256<T> left, int shiftAmount);
}
} ConsiderationsWe expose
|
namespace System.Numerics;
public static partial class Vector
{
public static Vector<T> Divide(Vector<T> left, T right);
public static T GetElement<T>(this Vector<T> vector, int index) where T : struct;
public static Vector<T> Load<T>(T* source) where T : unmanaged;
public static Vector<T> LoadAligned<T>(T* source) where T : unmanaged;
public static Vector<T> LoadAlignedNonTemporal<T>(T* source) where T : unmanaged;
public static Vector<T> LoadUnsafe<T>(ref T source) where T : struct;
public static Vector<T> LoadUnsafe<T>(ref T source, nuint index) where T : struct;
public static unsafe void Store<T>(this Vector<T> source, T* destination) where T : unmanaged;
public static unsafe void StoreAligned<T>(this Vector<T> source, T* destination) where T : unmanaged;
public static unsafe void StoreAlignedNonTemporal<T>(this Vector<T> source, T* destination) where T : unmanaged;
public static unsafe void StoreUnsafe<T>(this Vector<T> source, ref T destination) where T : struct;
public static unsafe void StoreUnsafe<T>(this Vector<T> source, ref T destination, nuint index) where T : struct;
public static T ToScalar<T>(this Vector<T> vector) where T : struct;
public static Vector<T> WithElement<T> (this Vector<T> vector, int index, T value) where T : struct;
}
public partial struct Vector<T>
{
public static Vector<T> AllBitsSet { get; }
public static Vector<T> operator /(Vector<T> left, T right);
public static Vector<T> operator +(Vector<T> value);
} namespace System.Runtime.Intrinsics.X86;
public static partial class Vector64
{
public static Vector64<T> CreateScalar<T>(T value) where T : struct;
public static Vector64<T> CreateScalarUnsafe<T>(T value) where T : struct;
public static Vector64<long> CreateScalarUnsafe (double value);
public static Vector64<long> CreateScalarUnsafe (long value);
public static Vector64<ulong> CreateScalarUnsafe (ulong value);
public static Vector64<T> Divide(Vector64<T> left, T right);
public static Vector64<ushort> WidenLower(Vector64<byte> value);
public static Vector64<int> WidenLower(Vector64<short> value);
public static Vector64<long> WidenLower(Vector64<int> value);
public static Vector64<short> WidenLower(Vector64<sbyte> value);
public static Vector64<double> WidenLower(Vector64<float> value);
public static Vector64<uint> WidenLower(Vector64<ushort> value);
public static Vector64<ulong> WidenLower(Vector64<uint> value);
public static Vector64<ushort> WidenUpper(Vector64<byte> value);
public static Vector64<int> WidenUpper(Vector64<short> value);
public static Vector64<long> WidenUpper(Vector64<int> value);
public static Vector64<short> WidenUpper(Vector64<sbyte> value);
public static Vector64<double> WidenUpper(Vector64<float> value);
public static Vector64<uint> WidenUpper(Vector64<ushort> value);
public static Vector64<ulong> WidenUpper(Vector64<uint> value);
}
public partial struct Vector64<T>
{
public static Vector64<T> One { get; }
public static Vector64<T> operator /(Vector64<T> left, T right);
public static Vector64<T> operator <<(Vector64<T> left, int shiftAmount);
public static Vector64<T> operator >>(Vector64<T> left, int shiftAmount);
public static Vector64<T> operator >>>(Vector64<T> left, int shiftAmount);
}
public static partial class Vector128
{
public static Vector128<T> Create<T>(Vector64<T> lower, Vector64<T> upper) where T : struct;
public static Vector128<nint> Create (Vector64<nint> lower, Vector64<nint> upper);
public static Vector128<nuint> Create (Vector64<nuint> lower, Vector64<nuint> upper);
public static Vector128<T> CreateScalar<T>(T value) where T : struct;
public static Vector128<T> CreateScalarUnsafe<T>(T value) where T : struct;
public static Vector128<T> Divide(Vector128<T> left, T right);
public static Vector128<ushort> WidenLower(Vector128<byte> value);
public static Vector128<int> WidenLower(Vector128<short> value);
public static Vector128<long> WidenLower(Vector128<int> value);
public static Vector128<short> WidenLower(Vector128<sbyte> value);
public static Vector128<double> WidenLower(Vector128<float> value);
public static Vector128<uint> WidenLower(Vector128<ushort> value);
public static Vector128<ulong> WidenLower(Vector128<uint> value);
public static Vector128<ushort> WidenUpper(Vector128<byte> value);
public static Vector128<int> WidenUpper(Vector128<short> value);
public static Vector128<long> WidenUpper(Vector128<int> value);
public static Vector128<short> WidenUpper(Vector128<sbyte> value);
public static Vector128<double> WidenUpper(Vector128<float> value);
public static Vector128<uint> WidenUpper(Vector128<ushort> value);
public static Vector128<ulong> WidenUpper(Vector128<uint> value);
}
public partial struct Vector128<T>
{
public static Vector128<T> One { get; }
public static Vector128<T> operator /(Vector128<T> left, T right);
public static Vector128<T> operator <<(Vector128<T> left, int shiftAmount);
public static Vector128<T> operator >>(Vector128<T> left, int shiftAmount);
public static Vector128<T> operator >>>(Vector128<T> left, int shiftAmount);
}
public static partial class Vector256
{
public static Vector256<T> Create<T>(Vector128<T> lower, Vector128<T> upper) where T : struct;
public static Vector256<nint> Create (Vector128<nint> lower, Vector128<nint> upper);
public static Vector256<nuint> Create (Vector128<nuint> lower, Vector128<nuint> upper);
public static Vector256<T> CreateScalar<T>(T value) where T : struct;
public static Vector256<T> CreateScalarUnsafe<T>(T value) where T : struct;
public static Vector256<T> Divide(Vector256<T> left, T right);
public static Vector256<ushort> WidenLower(Vector256<byte> value);
public static Vector256<int> WidenLower(Vector256<short> value);
public static Vector256<long> WidenLower(Vector256<int> value);
public static Vector256<short> WidenLower(Vector256<sbyte> value);
public static Vector256<double> WidenLower(Vector256<float> value);
public static Vector256<uint> WidenLower(Vector256<ushort> value);
public static Vector256<ulong> WidenLower(Vector256<uint> value);
public static Vector256<ushort> WidenUpper(Vector256<byte> value);
public static Vector256<int> WidenUpper(Vector256<short> value);
public static Vector256<long> WidenUpper(Vector256<int> value);
public static Vector256<short> WidenUpper(Vector256<sbyte> value);
public static Vector256<double> WidenUpper(Vector256<float> value);
public static Vector256<uint> WidenUpper(Vector256<ushort> value);
public static Vector256<ulong> WidenUpper(Vector256<uint> value);
}
public partial struct Vector256<T>
{
public static Vector256<T> One { get; }
public static Vector256<T> operator /(Vector256<T> left, T right);
public static Vector256<T> operator <<(Vector256<T> left, int shiftAmount);
public static Vector256<T> operator >>(Vector256<T> left, int shiftAmount);
public static Vector256<T> operator >>>(Vector256<T> left, int shiftAmount);
} |
Summary
We've exposed several APIs on Vector64/128/256 and recently approved Vector512. However, there are notably a few missing APIs that make it feel "incomplete". Such APIs were likely simply missed as part of previous review.
API Proposal
Considerations
We expose
==
and!=
with the semantics of "All". Exposing<
,<=
,>
, and>=
with the same semantics likely makes sense. If we do this, thenIComparable
should likely also be implemented.The text was updated successfully, but these errors were encountered: