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

Vector64/128/256/512<T> and Vector<T> Consistency/Enhancements #76593

Closed
Tracked by #79005
tannergooding opened this issue Oct 4, 2022 · 2 comments · Fixed by #77562
Closed
Tracked by #79005

Vector64/128/256/512<T> and Vector<T> Consistency/Enhancements #76593

tannergooding opened this issue Oct 4, 2022 · 2 comments · Fixed by #77562
Labels
api-approved API was approved in API review, it can be implemented area-System.Runtime.Intrinsics
Milestone

Comments

@tannergooding
Copy link
Member

tannergooding commented Oct 4, 2022

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

namespace 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 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;

        // Shuffle is difficult to expose because the indices often should be "constant"

        // Has SquareRoot, not Sqrt

        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; }

        // 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   (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);
    }
}

Considerations

We expose == and != with the semantics of "All". Exposing <, <=, >, and >= with the same semantics likely makes sense. If we do this, then IComparable should likely also be implemented.

@tannergooding tannergooding added area-System.Runtime.Intrinsics api-ready-for-review API is ready for review, it is NOT ready for implementation labels Oct 4, 2022
@ghost
Copy link

ghost commented Oct 4, 2022

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

Issue Details

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

namespace 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);
    }
}

Considerations

We expose == and != with the semantics of "All". Exposing <, <=, >, and >= with the same semantics likely makes sense. If we do this, then IComparable should likely also be implemented.

Author: tannergooding
Assignees: -
Labels:

area-System.Runtime.Intrinsics, api-ready-for-review

Milestone: -

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Oct 4, 2022
@tannergooding tannergooding removed the untriaged New issue has not been triaged by the area owner label Oct 4, 2022
@dakersnar dakersnar added this to the 8.0.0 milestone Oct 10, 2022
@terrajobst
Copy link
Member

terrajobst commented Oct 25, 2022

Video

  • Looks good as proposed
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);
}

@terrajobst terrajobst added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review API is ready for review, it is NOT ready for implementation labels Oct 25, 2022
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Oct 27, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Nov 2, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Dec 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Runtime.Intrinsics
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants