diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs
index 273947272..7f10f3182 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs
@@ -38,7 +38,7 @@ internal static partial class SimdUtils
///
/// The vector
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static Vector FastRound(this Vector v)
+ internal static Vector RoundToNearestInteger(this Vector v)
{
if (Avx512F.IsSupported && Vector.Count == Vector512.Count)
{
@@ -59,13 +59,11 @@ internal static partial class SimdUtils
}
// https://github.com/g-truc/glm/blob/master/glm/simd/common.h#L11
- Vector magic0 = new(int.MinValue); // 0x80000000
- Vector sgn0 = Vector.AsVectorSingle(magic0);
- Vector and0 = Vector.BitwiseAnd(sgn0, v);
- Vector or0 = Vector.BitwiseOr(and0, new Vector(8388608.0f));
- Vector add0 = Vector.Add(v, or0);
+ Vector sign = v & new Vector(-0F);
+ Vector val_2p23_f32 = sign | new Vector(8388608F);
- return Vector.Subtract(add0, or0);
+ val_2p23_f32 = (v + val_2p23_f32) - val_2p23_f32;
+ return val_2p23_f32 | sign;
}
[Conditional("DEBUG")]
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
index 018df5f9f..aa9249be5 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
@@ -588,6 +588,6 @@ internal partial struct Block8x8F : IEquatable
row += off;
row = Vector.Max(row, Vector.Zero);
row = Vector.Min(row, max);
- return row.FastRound();
+ return row.RoundToNearestInteger();
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs
index 2591ae310..e3700b2ca 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs
@@ -55,9 +55,9 @@ internal abstract partial class JpegColorConverterBase
Vector g = y + (cb * gCbMult) + (cr * gCrMult);
Vector b = y + (cb * bCbMult);
- r = r.FastRound();
- g = g.FastRound();
- b = b.FastRound();
+ r = r.RoundToNearestInteger();
+ g = g.RoundToNearestInteger();
+ b = b.RoundToNearestInteger();
r *= scale;
g *= scale;
b *= scale;
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKVector.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKVector.cs
index 570a401ad..535e5f125 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKVector.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKVector.cs
@@ -59,9 +59,9 @@ internal abstract partial class JpegColorConverterBase
Vector g = y + (cb * gCbMult) + (cr * gCrMult);
Vector b = y + (cb * bCbMult);
- r = (max - r.FastRound()) * scaledK;
- g = (max - g.FastRound()) * scaledK;
- b = (max - b.FastRound()) * scaledK;
+ r = (max - r.RoundToNearestInteger()) * scaledK;
+ g = (max - g.RoundToNearestInteger()) * scaledK;
+ b = (max - b.RoundToNearestInteger()) * scaledK;
c0 = r;
c1 = g;
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Round.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Round.cs
index 1d8385168..92faa50d2 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Round.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Round.cs
@@ -67,21 +67,21 @@ public unsafe class Block8x8F_Round
ref Block8x8F b = ref this.block;
ref Vector row0 = ref Unsafe.As>(ref b.V0L);
- row0 = row0.FastRound();
+ row0 = row0.RoundToNearestInteger();
ref Vector row1 = ref Unsafe.As>(ref b.V1L);
- row1 = row1.FastRound();
+ row1 = row1.RoundToNearestInteger();
ref Vector row2 = ref Unsafe.As>(ref b.V2L);
- row2 = row2.FastRound();
+ row2 = row2.RoundToNearestInteger();
ref Vector row3 = ref Unsafe.As>(ref b.V3L);
- row3 = row3.FastRound();
+ row3 = row3.RoundToNearestInteger();
ref Vector row4 = ref Unsafe.As>(ref b.V4L);
- row4 = row4.FastRound();
+ row4 = row4.RoundToNearestInteger();
ref Vector row5 = ref Unsafe.As>(ref b.V5L);
- row5 = row5.FastRound();
+ row5 = row5.RoundToNearestInteger();
ref Vector row6 = ref Unsafe.As>(ref b.V6L);
- row6 = row6.FastRound();
+ row6 = row6.RoundToNearestInteger();
ref Vector row7 = ref Unsafe.As>(ref b.V7L);
- row7 = row7.FastRound();
+ row7 = row7.RoundToNearestInteger();
}
[Benchmark]
@@ -90,21 +90,21 @@ public unsafe class Block8x8F_Round
ref Block8x8F b = ref Unsafe.AsRef(this.alignedPtr);
ref Vector row0 = ref Unsafe.As>(ref b.V0L);
- row0 = row0.FastRound();
+ row0 = row0.RoundToNearestInteger();
ref Vector row1 = ref Unsafe.As>(ref b.V1L);
- row1 = row1.FastRound();
+ row1 = row1.RoundToNearestInteger();
ref Vector row2 = ref Unsafe.As>(ref b.V2L);
- row2 = row2.FastRound();
+ row2 = row2.RoundToNearestInteger();
ref Vector row3 = ref Unsafe.As>(ref b.V3L);
- row3 = row3.FastRound();
+ row3 = row3.RoundToNearestInteger();
ref Vector row4 = ref Unsafe.As>(ref b.V4L);
- row4 = row4.FastRound();
+ row4 = row4.RoundToNearestInteger();
ref Vector row5 = ref Unsafe.As>(ref b.V5L);
- row5 = row5.FastRound();
+ row5 = row5.RoundToNearestInteger();
ref Vector row6 = ref Unsafe.As>(ref b.V6L);
- row6 = row6.FastRound();
+ row6 = row6.RoundToNearestInteger();
ref Vector row7 = ref Unsafe.As>(ref b.V7L);
- row7 = row7.FastRound();
+ row7 = row7.RoundToNearestInteger();
}
[Benchmark]
@@ -117,20 +117,20 @@ public unsafe class Block8x8F_Round
ref Vector row2 = ref Unsafe.As>(ref b.V2L);
ref Vector row3 = ref Unsafe.As>(ref b.V3L);
- row0 = row0.FastRound();
- row1 = row1.FastRound();
- row2 = row2.FastRound();
- row3 = row3.FastRound();
+ row0 = row0.RoundToNearestInteger();
+ row1 = row1.RoundToNearestInteger();
+ row2 = row2.RoundToNearestInteger();
+ row3 = row3.RoundToNearestInteger();
row0 = ref Unsafe.As>(ref b.V4L);
row1 = ref Unsafe.As>(ref b.V5L);
row2 = ref Unsafe.As>(ref b.V6L);
row3 = ref Unsafe.As>(ref b.V7L);
- row0 = row0.FastRound();
- row1 = row1.FastRound();
- row2 = row2.FastRound();
- row3 = row3.FastRound();
+ row0 = row0.RoundToNearestInteger();
+ row1 = row1.RoundToNearestInteger();
+ row2 = row2.RoundToNearestInteger();
+ row3 = row3.RoundToNearestInteger();
}
[Benchmark]
diff --git a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
index 36b301264..77c9889ae 100644
--- a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
+++ b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
@@ -73,7 +73,7 @@ public partial class SimdUtilsTests
public void FastRound()
{
Vector v = CreateExactTestVector1();
- Vector r = v.FastRound();
+ Vector r = v.RoundToNearestInteger();
this.Output.WriteLine(r.ToString());
@@ -90,7 +90,7 @@ public partial class SimdUtilsTests
public void FastRound_RandomValues(int seed, float scale)
{
Vector v = CreateRandomTestVector(seed, -scale * 0.5f, scale * 0.5f);
- Vector r = v.FastRound();
+ Vector r = v.RoundToNearestInteger();
this.Output.WriteLine(v.ToString());
this.Output.WriteLine(r.ToString());