Skip to content

[API Proposal]: Vector128/256 AddSaturate/RemoveSaturate #82559

Closed

Description

@EgorBo

Background and motivation

I hit lack of these crossplatform helpers when I was doing "parse hex" work in #82521 - ended up with local functions. These APIs seem to present in SSE/AVX and AdvSimd and can be easily exposed as cross-platform helpers. Some places in BCL might benefit from this too, e.g.

if (AdvSimd.IsSupported)
{
charIsThreeByteUtf8Encoded = AdvSimd.AddSaturate(utf16Data, vector7800);
mask = GetNonAsciiBytes(AdvSimd.Or(charIsNonAscii, charIsThreeByteUtf8Encoded).AsByte(), bitMask128);
}
else
{
charIsThreeByteUtf8Encoded = Sse2.AddSaturate(utf16Data, vector7800);
mask = (uint)Sse2.MoveMask(Sse2.Or(charIsNonAscii, charIsThreeByteUtf8Encoded).AsByte());
}

API Proposal

namespace System.Numerics;

public static class Vector
{
+     public static Vector<T> AddSaturate<T>     (Vector<T> left, Vector<T> right) where T : struct;
+     public static Vector<T> SubtractSaturate<T>(Vector<T> left, Vector<T> right) where T : struct;
}

namespace System.Runtime.Intrinsics;

public static class Vector64
{
+     public static Vector64<T> AddSaturate<T>     (Vector64<T> left, Vector64<T> right) where T : struct;
+     public static Vector64<T> SubtractSaturate<T>(Vector64<T> left, Vector64<T> right) where T : struct;
}

public static class Vector128
{
+     public static Vector128<T> AddSaturate<T>     (Vector128<T> left, Vector128<T> right) where T : struct;
+     public static Vector128<T> SubtractSaturate<T>(Vector128<T> left, Vector128<T> right) where T : struct;
}

public static class Vector256
{
+     public static Vector256<T> AddSaturate<T>     (Vector256<T> left, Vector256<T> right) where T : struct;
+     public static Vector256<T> SubtractSaturate<T>(Vector256<T> left, Vector256<T> right) where T : struct;
}

public static class Vector512
{
+     public static Vector512<T> AddSaturate<T>     (Vector512<T> left, Vector512<T> right) where T : struct;
+     public static Vector512<T> SubtractSaturate<T>(Vector512<T> left, Vector512<T> right) where T : struct;
}

NOTE: SSE and AVX only accelerate byte, sbyte, short and ushort. AdvSimd supports more types.

Activity

  1. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on Feb 23, 2023
  2. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Feb 23, 2023
  3. EgorBo commented on Feb 23, 2023

    @EgorBo
    MemberAuthor
  4. added
    api-ready-for-reviewAPI is ready for review, it is NOT ready for implementation
    and removed
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    untriagedNew issue has not been triaged by the area owner
    on Feb 23, 2023
  5. added this to the 8.0.0 milestone on Feb 23, 2023
  6. bartonjs commented on Mar 23, 2023

    @bartonjs
    Member

    Video

    • The AddSaturate name is consistent with the intrinsics
    • We squared the circle to also include Vector, Vector64, and Vector512
    namespace System.Runtime.Intrinsics;
    
    public static partial class Vector
    {
          public static Vector<T>   AddSaturate(Vector<T>   left, Vector<T>   right);
          public static Vector<T>   SubtractSaturate(Vector<T>   left, Vector<T>   right);
    }
    
    public static partial class Vector64
    {
          public static Vector64<T>   AddSaturate(Vector64<T>   left, Vector64<T>   right);
          public static Vector64<T>   SubtractSaturate(Vector64<T>   left, Vector64<T>   right);
    }
    
    public static partial class Vector128
    {
          public static Vector128<T>   AddSaturate(Vector128<T>   left, Vector128<T>   right);
          public static Vector128<T>   SubtractSaturate(Vector128<T>   left, Vector128<T>   right);
    }
    
    public static partial class Vector256
    {
          public static Vector256<T>   AddSaturate(Vector256<T>   left, Vector256<T>   right);
          public static Vector256<T>   SubtractSaturate(Vector256<T>   left, Vector256<T>   right);
    }
    
    public static partial class Vector512
    {
          public static Vector512<T>   AddSaturate(Vector512<T>   left, Vector512<T>   right);
          public static Vector512<T>   SubtractSaturate(Vector512<T>   left, Vector512<T>   right);
    }
  7. added
    api-approvedAPI was approved in API review, it can be implemented
    and removed
    api-ready-for-reviewAPI is ready for review, it is NOT ready for implementation
    on Mar 23, 2023
  8. modified the milestones: 8.0.0, Future on Jul 24, 2023
  9. tannergooding commented on Jul 24, 2023

    @tannergooding
    Member

    Not going to land this for .NET 8; we can take a PR anytime after the repo opens for .NET 9 changes

  10. added
    help wanted[up-for-grabs] Good issue for external contributors
    on Aug 11, 2023
  11. lilinus commented on Aug 28, 2024

    @lilinus
    Contributor

    This had been open with "help wanted" tag for a while. I can work on a change for it, unless there is a reason it has been hanging?

  12. EgorBo commented on Aug 28, 2024

    @EgorBo
    MemberAuthor

    This had been open with "help wanted" tag for a while. I can work on a change for it, unless there is a reason it has been hanging?

    I don't think there are any, feel free to grab it

  13. tannergooding commented on May 24, 2025

    @tannergooding
    Member

    This was resolved with #115525 and will be in .NET 10 Preview 5

  14. locked and limited conversation to collaborators on Jun 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions