mirror of https://github.com/SixLabors/ImageSharp
2 changed files with 142 additions and 45 deletions
@ -0,0 +1,99 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Diagnostics; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.Intrinsics; |
|||
using System.Runtime.Intrinsics.Arm; |
|||
using System.Runtime.Intrinsics.X86; |
|||
|
|||
namespace SixLabors.ImageSharp.Common.Helpers; |
|||
|
|||
/// <summary>
|
|||
/// Defines utility methods for <see cref="Vector128{T}"/> that have not yet been normalized in the runtime.
|
|||
/// Should only be used if the intrinsics are available.
|
|||
/// </summary>
|
|||
internal static class Vector128Utilities |
|||
{ |
|||
/// <summary>
|
|||
/// Gets a value indicating whether right shift operations are supported.
|
|||
/// </summary>
|
|||
public static bool SupportsRightShift |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => Ssse3.IsSupported || AdvSimd.IsSupported; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Shifts a 128-bit value right by a specified number of bytes while shifting in zeros.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to shift.</param>
|
|||
/// <param name="numBytes">The number of bytes to shift by.</param>
|
|||
/// <returns>The <see cref="Vector128{Byte}"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector128<byte> ShiftRightBytesInVector(Vector128<byte> value, [ConstantExpected(Max = (byte)15)] byte numBytes) |
|||
{ |
|||
if (Sse2.IsSupported) |
|||
{ |
|||
return Sse2.ShiftRightLogical128BitLane(value, numBytes); |
|||
} |
|||
|
|||
if (AdvSimd.IsSupported) |
|||
{ |
|||
return AdvSimd.ExtractVector128(value, Vector128<byte>.Zero, numBytes); |
|||
} |
|||
|
|||
ThrowUnreachableException(); |
|||
return default; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Shifts a 128-bit value left by a specified number of bytes while shifting in zeros.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to shift.</param>
|
|||
/// <param name="numBytes">The number of bytes to shift by.</param>
|
|||
/// <returns>The <see cref="Vector128{Byte}"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector128<byte> ShiftLeftBytesInVector(Vector128<byte> value, [ConstantExpected(Max = (byte)15)] byte numBytes) |
|||
{ |
|||
if (Sse2.IsSupported) |
|||
{ |
|||
return Sse2.ShiftLeftLogical128BitLane(value, numBytes); |
|||
} |
|||
|
|||
if (AdvSimd.IsSupported) |
|||
{ |
|||
return AdvSimd.ExtractVector128(Vector128<byte>.Zero, value, numBytes); |
|||
} |
|||
|
|||
ThrowUnreachableException(); |
|||
return default; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Right aligns elements of two source 128-bit values depending on bits in a mask.
|
|||
/// </summary>
|
|||
/// <param name="left">The left hand source vector.</param>
|
|||
/// <param name="right">The right hand source vector.</param>
|
|||
/// <param name="mask">An 8-bit mask used for the operation.</param>
|
|||
/// <returns>The <see cref="Vector128{Byte}"/>.</returns>
|
|||
public static Vector128<byte> AlignRight(Vector128<byte> left, Vector128<byte> right, [ConstantExpected(Max = (byte)15)] byte mask) |
|||
{ |
|||
if (Sse3.IsSupported) |
|||
{ |
|||
return Ssse3.AlignRight(left, right, mask); |
|||
} |
|||
|
|||
if (AdvSimd.IsSupported) |
|||
{ |
|||
return AdvSimd.ExtractVector128(right, left, mask); |
|||
} |
|||
|
|||
ThrowUnreachableException(); |
|||
return default; |
|||
} |
|||
|
|||
[DoesNotReturn] |
|||
private static void ThrowUnreachableException() => throw new UnreachableException(); |
|||
} |
|||
Loading…
Reference in new issue