Skip to content

Vector{<T>|64|128|256|512}.Narrow with saturation #75724

Closed
@gfoidl

Description

@gfoidl

Summary

For SSE2 there's Sse2.PackSignedSaturate which packs the two vectors with saturation.
Such functionality is missing for the xplat-vectors -- i.e. Vector128.Narrow packs the two vectors, but cuts / masks off the values outside of the target range, e.g. for short -> sbyte bits above 0xFF is cut off resulting in (for me) unexpected values.

Maybe it's a bit astonishing that Narrow doesn't pack with saturation. This just bit me, and as it seems #73064 (comment) was similar.

There should be something like NarrowWithSaturation in order to don't need to fallback to Sse2 / AdvSimd.

API Proposal

namespace System.Runtime.Intrinsics;

public static class Vector64
{
    // Existing methods left out for brevity

    [CLSCompliant(false)]
    public static Vector64<sbyte> NarrowWithSaturation(Vector64<short> lower, Vector64<short> upper);

    public static Vector64<short> NarrowWithSaturation(Vector64<int> lower, Vector64<int> upper);

    public static Vector64<int> NarrowWithSaturation(Vector64<long> lower, Vector64<long> upper);

    [CLSCompliant(false)]
    public static Vector64<byte> NarrowWithSaturation(Vector64<ushort> lower, Vector64<ushort> upper);

    [CLSCompliant(false)]
    public static Vector64<ushort> NarrowWithSaturation(Vector64<uint> lower, Vector64<uint> upper);

    public static Vector64<uint> NarrowWithSaturation(Vector64<ulong> lower, Vector64<ulong> upper);

    public static Vector64<float> NarrowWithSaturation(Vector64<double> lower, Vector64<double> upper);
}

public static class Vector128
{
    // Existing methods left out for brevity

    [CLSCompliant(false)]
    public static Vector128<sbyte> NarrowWithSaturation(Vector128<short> lower, Vector128<short> upper);

    public static Vector128<short> NarrowWithSaturation(Vector128<int> lower, Vector128<int> upper);

    public static Vector128<int> NarrowWithSaturation(Vector128<long> lower, Vector128<long> upper);

    [CLSCompliant(false)]
    public static Vector128<byte> NarrowWithSaturation(Vector128<ushort> lower, Vector128<ushort> upper);

    [CLSCompliant(false)]
    public static Vector128<ushort> NarrowWithSaturation(Vector128<uint> lower, Vector128<uint> upper);

    public static Vector128<uint> NarrowWithSaturation(Vector128<ulong> lower, Vector128<ulong> upper);

    public static Vector128<float> NarrowWithSaturation(Vector128<double> lower, Vector128<double> upper);
}

public static class Vector256
{
    // Existing methods left out for brevity

    [CLSCompliant(false)]
    public static Vector256<sbyte> NarrowWithSaturation(Vector256<short> lower, Vector256<short> upper);

    public static Vector256<short> NarrowWithSaturation(Vector256<int> lower, Vector256<int> upper);

    public static Vector256<int> NarrowWithSaturation(Vector256<long> lower, Vector256<long> upper);

    [CLSCompliant(false)]
    public static Vector256<byte> NarrowWithSaturation(Vector256<ushort> lower, Vector256<ushort> upper);

    [CLSCompliant(false)]
    public static Vector256<ushort> NarrowWithSaturation(Vector256<uint> lower, Vector256<uint> upper);

    public static Vector256<uint> NarrowWithSaturation(Vector256<ulong> lower, Vector256<ulong> upper);

    public static Vector256<float> NarrowWithSaturation(Vector256<double> lower, Vector256<double> upper);
}

public static class Vector512
{
    // Existing methods left out for brevity

    [CLSCompliant(false)]
    public static Vector512<sbyte> NarrowWithSaturation(Vector512<short> lower, Vector512<short> upper);

    public static Vector512<short> NarrowWithSaturation(Vector512<int> lower, Vector512<int> upper);

    public static Vector512<int> NarrowWithSaturation(Vector512<long> lower, Vector512<long> upper);

    [CLSCompliant(false)]
    public static Vector512<byte> NarrowWithSaturation(Vector512<ushort> lower, Vector512<ushort> upper);

    [CLSCompliant(false)]
    public static Vector512<ushort> NarrowWithSaturation(Vector512<uint> lower, Vector512<uint> upper);

    public static Vector512<uint> NarrowWithSaturation(Vector512<ulong> lower, Vector512<ulong> upper);

    public static Vector512<float> NarrowWithSaturation(Vector512<double> lower, Vector512<double> upper);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions