Browse Source

Added DivideCeil

pull/1694/head
Dmitry Pentin 5 years ago
parent
commit
13c3a45a98
  1. 8
      src/ImageSharp/Common/Helpers/Numerics.cs
  2. 4
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs
  3. 34
      tests/ImageSharp.Tests/Common/NumericsTests.cs

8
src/ImageSharp/Common/Helpers/Numerics.cs

@ -879,5 +879,13 @@ namespace SixLabors.ImageSharp
(IntPtr)(int)((value * 0x07C4ACDDu) >> 27)); // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here
}
#endif
/// <summary>
/// Fast division with ceiling for <see cref="uint"/> numbers.
/// </summary>
/// <param name="value">Divident value.</param>
/// <param name="divisor">Divisor value.</param>
/// <returns>Ceiled division result.</returns>
public static uint DivideCeil(uint value, uint divisor) => (value + divisor - 1) / divisor;
}
}

4
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs

@ -103,8 +103,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// </summary>
public void InitComponents()
{
this.McusPerLine = (int)MathF.Ceiling(this.PixelWidth / 8F / this.MaxHorizontalFactor);
this.McusPerColumn = (int)MathF.Ceiling(this.PixelHeight / 8F / this.MaxVerticalFactor);
this.McusPerLine = (int)Numerics.DivideCeil((uint)this.PixelWidth, (uint)this.MaxHorizontalFactor * 8);
this.McusPerColumn = (int)Numerics.DivideCeil((uint)this.PixelHeight, (uint)this.MaxVerticalFactor * 8);
for (int i = 0; i < this.ComponentCount; i++)
{

34
tests/ImageSharp.Tests/Common/NumericsTests.cs

@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Tests.Common
int expected = 0;
int actual = Numerics.Log2(value);
Assert.True(expected == actual, $"Expected: {expected}, Actual: {actual}");
Assert.Equal(expected, actual);
}
[Fact]
@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests.Common
int expected = i;
int actual = Numerics.Log2(value);
Assert.True(expected == actual, $"Expected: {expected}, Actual: {actual}");
Assert.Equal(expected, actual);
}
}
@ -66,7 +66,35 @@ namespace SixLabors.ImageSharp.Tests.Common
int expected = Log2_ReferenceImplementation(value);
int actual = Numerics.Log2(value);
Assert.True(expected == actual, $"Expected: {expected}, Actual: {actual}");
Assert.Equal(expected, actual);
}
}
private static uint DivideCeil_ReferenceImplementation(uint value, uint divisor) => (uint)MathF.Ceiling((float)value / divisor);
[Fact]
public void DivideCeil_DivideZero()
{
uint expected = 0;
uint actual = Numerics.DivideCeil(0, 100);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(1, 100)]
public void DivideCeil_RandomValues(int seed, int count)
{
var rng = new Random(seed);
for (int i = 0; i < count; i++)
{
uint value = (uint)rng.Next();
uint divisor = (uint)rng.Next();
uint expected = DivideCeil_ReferenceImplementation(value, divisor);
uint actual = Numerics.DivideCeil(value, divisor);
Assert.True(expected == actual, $"Expected: {expected}\nActual: {actual}\n{value} / {divisor} = {expected}");
}
}
}

Loading…
Cancel
Save