|
|
@ -2,6 +2,7 @@ |
|
|
// Licensed under the Six Labors Split License.
|
|
|
// Licensed under the Six Labors Split License.
|
|
|
|
|
|
|
|
|
using System.Numerics; |
|
|
using System.Numerics; |
|
|
|
|
|
using System.Numerics.Tensors; |
|
|
using System.Runtime.CompilerServices; |
|
|
using System.Runtime.CompilerServices; |
|
|
using System.Runtime.InteropServices; |
|
|
using System.Runtime.InteropServices; |
|
|
using System.Runtime.Intrinsics; |
|
|
using System.Runtime.Intrinsics; |
|
|
@ -14,6 +15,8 @@ namespace SixLabors.ImageSharp.Formats.Jxl.Processing; |
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
internal static partial class JxlSimdUtils |
|
|
internal static partial class JxlSimdUtils |
|
|
{ |
|
|
{ |
|
|
|
|
|
public static int MaxVectorSize => Vector<float>.Count * sizeof(float); |
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
public static Vector256<T> ConcatLowerLower<T>(Vector256<T> a, Vector256<T> b) |
|
|
public static Vector256<T> ConcatLowerLower<T>(Vector256<T> a, Vector256<T> b) |
|
|
where T : unmanaged => Vector256.Create(a.GetLower(), b.GetLower()); |
|
|
where T : unmanaged => Vector256.Create(a.GetLower(), b.GetLower()); |
|
|
@ -505,6 +508,39 @@ internal static partial class JxlSimdUtils |
|
|
Vector<float> exponent) |
|
|
Vector<float> exponent) |
|
|
=> FastPow2f(Vector.Log2(@base) * exponent); |
|
|
=> FastPow2f(Vector.Log2(@base) * exponent); |
|
|
|
|
|
|
|
|
|
|
|
public static uint MaxValue(Span<uint> data) |
|
|
|
|
|
{ |
|
|
|
|
|
int lanes = Vector<uint>.Count; |
|
|
|
|
|
int lastFull = lanes * (data.Length / lanes); |
|
|
|
|
|
|
|
|
|
|
|
Vector<uint> max = Vector<uint>.Zero; |
|
|
|
|
|
ref uint dataRef = ref MemoryMarshal.GetReference(data); |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < lastFull; i += lanes) |
|
|
|
|
|
{ |
|
|
|
|
|
max = Vector.Max(max, Vector.LoadUnsafe(ref Unsafe.Add(ref dataRef, i))); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (lastFull < data.Length) |
|
|
|
|
|
{ |
|
|
|
|
|
Vector<uint> stop = Vector.Create((uint)data.Length); |
|
|
|
|
|
Vector<uint> fence = Iota((uint)lastFull); |
|
|
|
|
|
Vector<uint> take = Vector.LessThan(fence, stop); |
|
|
|
|
|
max = Vector.Max( |
|
|
|
|
|
max, |
|
|
|
|
|
Vector.ConditionalSelect( |
|
|
|
|
|
take, |
|
|
|
|
|
Vector.LoadUnsafe(ref Unsafe.Add(ref dataRef, lastFull)), |
|
|
|
|
|
Vector<uint>.Zero)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// The following part is to find the largest number in
|
|
|
|
|
|
// the vector.
|
|
|
|
|
|
Span<uint> copy = stackalloc uint[Vector<uint>.Count]; |
|
|
|
|
|
max.CopyTo(copy); |
|
|
|
|
|
return TensorPrimitives.Max<uint>(copy); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Incrementing values to compute the Iota function.
|
|
|
/// Incrementing values to compute the Iota function.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
|