Skip to content

Commit c6758df

Browse files
Optimize and cleanup ByteToNormalizedFloatReduce
1 parent 805c7c4 commit c6758df

File tree

15 files changed

+344
-425
lines changed

15 files changed

+344
-425
lines changed

src/ImageSharp/Common/Helpers/Numerics.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,4 +1069,24 @@ public static nuint Vector256Count<TVector>(this Span<float> span)
10691069
public static nuint Vector256Count<TVector>(int length)
10701070
where TVector : struct
10711071
=> (uint)length / (uint)Vector256<TVector>.Count;
1072+
1073+
/// <summary>
1074+
/// Gets the count of vectors that safely fit into the given span.
1075+
/// </summary>
1076+
/// <typeparam name="TVector">The type of the vector.</typeparam>
1077+
/// <param name="span">The given span.</param>
1078+
/// <returns>Count of vectors that safely fit into the span.</returns>
1079+
public static nuint Vector512Count<TVector>(this Span<float> span)
1080+
where TVector : struct
1081+
=> (uint)span.Length / (uint)Vector512<TVector>.Count;
1082+
1083+
/// <summary>
1084+
/// Gets the count of vectors that safely fit into length.
1085+
/// </summary>
1086+
/// <typeparam name="TVector">The type of the vector.</typeparam>
1087+
/// <param name="length">The given length.</param>
1088+
/// <returns>Count of vectors that safely fit into the length.</returns>
1089+
public static nuint Vector512Count<TVector>(int length)
1090+
where TVector : struct
1091+
=> (uint)length / (uint)Vector512<TVector>.Count;
10721092
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using System.Runtime.CompilerServices;
5+
using System.Runtime.InteropServices;
6+
7+
namespace SixLabors.ImageSharp;
8+
9+
internal static partial class SimdUtils
10+
{
11+
/// <summary>
12+
/// Converts all input <see cref="byte"/>-s to <see cref="float"/>-s normalized into [0..1].
13+
/// <paramref name="source"/> should be the of the same size as <paramref name="destination"/>,
14+
/// but there are no restrictions on the span's length.
15+
/// </summary>
16+
/// <param name="source">The source span of bytes</param>
17+
/// <param name="destination">The destination span of floats</param>
18+
[MethodImpl(InliningOptions.ShortMethod)]
19+
internal static void ByteToNormalizedFloat(ReadOnlySpan<byte> source, Span<float> destination)
20+
{
21+
DebugGuard.IsTrue(source.Length == destination.Length, nameof(source), "Input spans must be of same length!");
22+
23+
HwIntrinsics.ByteToNormalizedFloatReduce(ref source, ref destination);
24+
25+
if (source.Length > 0)
26+
{
27+
ConvertByteToNormalizedFloatRemainder(source, destination);
28+
}
29+
}
30+
31+
/// <summary>
32+
/// Convert all <see cref="float"/> values normalized into [0..1] from 'source' into 'destination' buffer of <see cref="byte"/>.
33+
/// The values are scaled up into [0-255] and rounded, overflows are clamped.
34+
/// <paramref name="source"/> should be the of the same size as <paramref name="destination"/>,
35+
/// but there are no restrictions on the span's length.
36+
/// </summary>
37+
/// <param name="source">The source span of floats</param>
38+
/// <param name="destination">The destination span of bytes</param>
39+
[MethodImpl(InliningOptions.ShortMethod)]
40+
internal static void NormalizedFloatToByteSaturate(ReadOnlySpan<float> source, Span<byte> destination)
41+
{
42+
DebugGuard.IsTrue(source.Length == destination.Length, nameof(source), "Input spans must be of same length!");
43+
44+
HwIntrinsics.NormalizedFloatToByteSaturateReduce(ref source, ref destination);
45+
46+
if (source.Length > 0)
47+
{
48+
ConvertNormalizedFloatToByteRemainder(source, destination);
49+
}
50+
}
51+
52+
[MethodImpl(MethodImplOptions.NoInlining)]
53+
private static void ConvertByteToNormalizedFloatRemainder(ReadOnlySpan<byte> source, Span<float> destination)
54+
{
55+
ref byte sBase = ref MemoryMarshal.GetReference(source);
56+
ref float dBase = ref MemoryMarshal.GetReference(destination);
57+
58+
for (int i = 0; i < source.Length; i++)
59+
{
60+
Unsafe.Add(ref dBase, i) = Unsafe.Add(ref sBase, i) / 255f;
61+
}
62+
}
63+
64+
[MethodImpl(MethodImplOptions.NoInlining)]
65+
private static void ConvertNormalizedFloatToByteRemainder(ReadOnlySpan<float> source, Span<byte> destination)
66+
{
67+
ref float sBase = ref MemoryMarshal.GetReference(source);
68+
ref byte dBase = ref MemoryMarshal.GetReference(destination);
69+
for (int i = 0; i < source.Length; i++)
70+
{
71+
Unsafe.Add(ref dBase, i) = ConvertToByte(Unsafe.Add(ref sBase, i));
72+
}
73+
}
74+
75+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
76+
private static byte ConvertToByte(float f) => (byte)Numerics.Clamp((f * 255F) + 0.5F, 0, 255F);
77+
}

src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs

Lines changed: 0 additions & 83 deletions
This file was deleted.

0 commit comments

Comments
 (0)