Skip to content

Commit 9b7e41f

Browse files
committed
Optimized division by constants
1 parent 1faf5a5 commit 9b7e41f

36 files changed

+106
-94
lines changed

src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Six Labors.
1+
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

44
using System.Runtime.CompilerServices;
@@ -42,9 +42,11 @@ public CieLab Convert(in CieXyz input)
4242

4343
float xr = input.X / wx, yr = input.Y / wy, zr = input.Z / wz;
4444

45-
float fx = xr > CieConstants.Epsilon ? MathF.Pow(xr, 0.3333333F) : ((CieConstants.Kappa * xr) + 16F) / 116F;
46-
float fy = yr > CieConstants.Epsilon ? MathF.Pow(yr, 0.3333333F) : ((CieConstants.Kappa * yr) + 16F) / 116F;
47-
float fz = zr > CieConstants.Epsilon ? MathF.Pow(zr, 0.3333333F) : ((CieConstants.Kappa * zr) + 16F) / 116F;
45+
const float inv116 = 1 / 116F;
46+
47+
float fx = xr > CieConstants.Epsilon ? MathF.Pow(xr, 0.3333333F) : ((CieConstants.Kappa * xr) + 16F) * inv116;
48+
float fy = yr > CieConstants.Epsilon ? MathF.Pow(yr, 0.3333333F) : ((CieConstants.Kappa * yr) + 16F) * inv116;
49+
float fz = zr > CieConstants.Epsilon ? MathF.Pow(zr, 0.3333333F) : ((CieConstants.Kappa * zr) + 16F) * inv116;
4850

4951
float l = (116F * fy) - 16F;
5052
float a = 500F * (fx - fy);

src/ImageSharp/Common/Helpers/HexConverter.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,19 @@ internal static class HexConverter
1616
/// <returns>The number of bytes written to <paramref name="bytes"/>.</returns>
1717
public static int HexStringToBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
1818
{
19-
if ((chars.Length % 2) != 0)
19+
if ((chars.Length & 1) != 0) // bit-hack for % 2
2020
{
2121
throw new ArgumentException("Input string length must be a multiple of 2", nameof(chars));
2222
}
2323

24-
if ((bytes.Length * 2) < chars.Length)
24+
if ((bytes.Length << 1) < chars.Length) // bit-hack for * 2
2525
{
2626
throw new ArgumentException("Output span must be at least half the length of the input string");
2727
}
28-
else
29-
{
30-
// Slightly better performance in the loop below, allows us to skip a bounds check
31-
// while still supporting output buffers that are larger than necessary
32-
bytes = bytes[..(chars.Length / 2)];
33-
}
28+
29+
// Slightly better performance in the loop below, allows us to skip a bounds check
30+
// while still supporting output buffers that are larger than necessary
31+
bytes = bytes[..(chars.Length >> 1)]; // bit-hack for / 2
3432

3533
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3634
static int FromChar(int c)

src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
8484
{
8585
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
8686
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
87-
int n = source.Length / 4;
87+
int n = (int)((uint)source.Length / 4);
8888

8989
for (nint i = 0; i < (uint)n; i++)
9090
{
@@ -108,7 +108,7 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
108108
{
109109
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
110110
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
111-
int n = source.Length / 4;
111+
int n = (int)((uint)source.Length / 4);
112112

113113
for (nint i = 0; i < (uint)n; i++)
114114
{
@@ -132,7 +132,7 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
132132
{
133133
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
134134
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
135-
int n = source.Length / 4;
135+
int n = (int)((uint)source.Length / 4);
136136

137137
for (nint i = 0; i < (uint)n; i++)
138138
{
@@ -156,7 +156,7 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
156156
{
157157
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
158158
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
159-
int n = source.Length / 4;
159+
int n = (int)((uint)source.Length / 4);
160160

161161
for (nint i = 0; i < (uint)n; i++)
162162
{
@@ -187,7 +187,7 @@ public void RunFallbackShuffle(ReadOnlySpan<byte> source, Span<byte> dest)
187187
{
188188
ref uint sBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(source));
189189
ref uint dBase = ref Unsafe.As<byte, uint>(ref MemoryMarshal.GetReference(dest));
190-
int n = source.Length / 4;
190+
int n = (int)((uint)source.Length / 4);
191191

192192
for (nint i = 0; i < (uint)n; i++)
193193
{

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ internal static void ByteToNormalizedFloat(ReadOnlySpan<byte> source, Span<float
7171
{
7272
VerifySpanInput(source, dest, 4);
7373

74-
int count = dest.Length / 4;
74+
int count = (int)((uint)dest.Length / 4);
7575
if (count == 0)
7676
{
7777
return;
@@ -105,7 +105,7 @@ internal static void NormalizedFloatToByteSaturate(
105105
{
106106
VerifySpanInput(source, dest, 4);
107107

108-
int count = source.Length / 4;
108+
int count = (int)((uint)source.Length / 4);
109109
if (count == 0)
110110
{
111111
return;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public static void Pad3Shuffle4Reduce(
159159
int remainder = source.Length % (Vector128<byte>.Count * 3);
160160

161161
int sourceCount = source.Length - remainder;
162-
int destCount = sourceCount * 4 / 3;
162+
int destCount = (int)((uint)sourceCount * 4 / 3);
163163

164164
if (sourceCount > 0)
165165
{
@@ -192,7 +192,7 @@ public static void Shuffle4Slice3Reduce(
192192
int remainder = source.Length % (Vector128<byte>.Count * 4);
193193

194194
int sourceCount = source.Length - remainder;
195-
int destCount = sourceCount * 3 / 4;
195+
int destCount = (int)((uint)sourceCount * 3 / 4);
196196

197197
if (sourceCount > 0)
198198
{

src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ public void CompressBlock()
206206
int lc = Lcode(litlen);
207207
this.literalTree.WriteSymbol(pendingBuffer, lc);
208208

209-
int bits = (lc - 261) / 4;
210-
if (bits > 0 && bits <= 5)
209+
int bits = (int)(((uint)lc - 261) / 4);
210+
if (bits is > 0 and <= 5)
211211
{
212212
this.Pending.WriteBits(litlen & ((1 << bits) - 1), bits);
213213
}
@@ -364,7 +364,7 @@ public bool TallyDist(int distance, int length)
364364
this.literalTree.Frequencies[lc]++;
365365
if (lc >= 265 && lc < 285)
366366
{
367-
this.extraBits += (lc - 261) / 4;
367+
this.extraBits += (int)(((uint)lc - 261) / 4);
368368
}
369369

370370
int dc = Dcode(distance - 1);

src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ private void UncompressRle4(BufferedReadStream stream, int w, Span<byte> buffer,
489489
// If the second byte > 2, we are in 'absolute mode'.
490490
// The second byte contains the number of color indexes that follow.
491491
int max = cmd[1];
492-
int bytesToRead = (max + 1) / 2;
492+
int bytesToRead = (int)(((uint)max + 1) / 2);
493493

494494
byte[] run = new byte[bytesToRead];
495495

src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
124124
this.bitsPerPixel ??= bmpMetadata.BitsPerPixel;
125125

126126
short bpp = (short)this.bitsPerPixel;
127-
int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32);
127+
int bytesPerLine = (int)(4 * ((((uint)image.Width * (ushort)bpp) + 31) / 32));
128128
this.padding = bytesPerLine - (int)(image.Width * (bpp / 8F));
129129

130130
int colorPaletteSize = this.bitsPerPixel switch

src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public void NormalizeColorsInPlace(float maximum)
1616
{
1717
var CMin4 = new Vector4(0F);
1818
var CMax4 = new Vector4(maximum);
19-
var COff4 = new Vector4(MathF.Ceiling(maximum / 2));
19+
var COff4 = new Vector4(MathF.Ceiling(maximum * 0.5F)); // /2
2020

2121
this.V0L = Numerics.Clamp(this.V0L + COff4, CMin4, CMax4);
2222
this.V0R = Numerics.Clamp(this.V0R + COff4, CMin4, CMax4);
@@ -42,7 +42,7 @@ public void NormalizeColorsInPlace(float maximum)
4242
[MethodImpl(InliningOptions.ShortMethod)]
4343
public void NormalizeColorsAndRoundInPlaceVector8(float maximum)
4444
{
45-
var off = new Vector<float>(MathF.Ceiling(maximum / 2));
45+
var off = new Vector<float>(MathF.Ceiling(maximum * 0.5F)); // /2
4646
var max = new Vector<float>(maximum);
4747

4848
ref Vector<float> row0 = ref Unsafe.As<Vector4, Vector<float>>(ref this.V0L);

src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal partial struct Block8x8F
2929
{
3030
var CMin4 = new Vector4(0F);
3131
var CMax4 = new Vector4(maximum);
32-
var COff4 = new Vector4(MathF.Ceiling(maximum / 2));
32+
var COff4 = new Vector4(MathF.Ceiling(maximum * 0.5F)); // /2
3333

3434
<#
3535

@@ -53,7 +53,7 @@ internal partial struct Block8x8F
5353
[MethodImpl(InliningOptions.ShortMethod)]
5454
public void NormalizeColorsAndRoundInPlaceVector8(float maximum)
5555
{
56-
var off = new Vector<float>(MathF.Ceiling(maximum / 2));
56+
var off = new Vector<float>(MathF.Ceiling(maximum * 0.5F)); // /2
5757
var max = new Vector<float>(maximum);
5858
<#
5959

0 commit comments

Comments
 (0)