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