Browse Source

refactor QuickSort to a common utility class

af/merge-core
Anton Firszov 8 years ago
parent
commit
ecf160e5bb
  1. 69
      src/ImageSharp.Drawing/Processing/Drawing/Processors/FillRegionProcessor.cs
  2. 2
      src/ImageSharp.Drawing/Processing/Text/DrawTextExtensions.cs
  3. 58
      src/ImageSharp.Drawing/Processing/Text/Processors/DrawTextProcessor.cs
  4. 84
      src/ImageSharp.Drawing/Utils/QuickSort.cs
  5. 3
      tests/ImageSharp.Tests/Drawing/BeziersTests.cs
  6. 51
      tests/ImageSharp.Tests/Drawing/Utils/QuickSortTests.cs

69
src/ImageSharp.Drawing/Processing/Drawing/Processors/FillRegionProcessor.cs

@ -2,11 +2,11 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing.Drawing.Brushes;
using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.ImageSharp.Utils;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Processors
continue;
}
QuickSort(buffer.Slice(0, pointsFound));
QuickSort.Sort(buffer.Slice(0, pointsFound));
for (int point = 0; point < pointsFound; point += 2)
{
@ -186,70 +186,5 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Processors
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Swap(ref float left, ref float right)
{
float tmp = left;
left = right;
right = tmp;
}
private static void QuickSort(Span<float> data)
{
if (data.Length < 2)
{
return;
}
else if (data.Length == 2)
{
if (data[0] > data[1])
{
Swap(ref data[0], ref data[1]);
}
return;
}
QuickSort(ref data[0], 0, data.Length - 1);
}
private static void QuickSort(ref float data0, int lo, int hi)
{
if (lo < hi)
{
int p = Partition(ref data0, lo, hi);
QuickSort(ref data0, lo, p);
QuickSort(ref data0, p + 1, hi);
}
}
private static int Partition(ref float data0, int lo, int hi)
{
float pivot = Unsafe.Add(ref data0, lo);
int i = lo - 1;
int j = hi + 1;
while (true)
{
do
{
i = i + 1;
}
while (Unsafe.Add(ref data0, i) < pivot && i < hi);
do
{
j = j - 1;
}
while (Unsafe.Add(ref data0, j) > pivot && j > lo);
if (i >= j)
{
return j;
}
Swap(ref Unsafe.Add(ref data0, i), ref Unsafe.Add(ref data0, j));
}
}
}
}

2
src/ImageSharp.Drawing/Processing/Text/DrawTextExtensions.cs

@ -3,12 +3,10 @@
using SixLabors.Fonts;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Drawing;
using SixLabors.ImageSharp.Processing.Drawing.Brushes;
using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.ImageSharp.Processing.Text.Processors;
using SixLabors.Primitives;
using SixLabors.Shapes;
namespace SixLabors.ImageSharp.Processing.Text
{

58
src/ImageSharp.Drawing/Processing/Text/Processors/DrawTextProcessor.cs

@ -3,16 +3,13 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.Fonts;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing.Drawing.Brushes;
using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.ImageSharp.Processing.Drawing.Processors;
using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.ImageSharp.Utils;
using SixLabors.Memory;
using SixLabors.Primitives;
using SixLabors.Shapes;
@ -377,7 +374,7 @@ namespace SixLabors.ImageSharp.Processing.Text.Processors
buffer[i] = intersectionSpan[i].X;
}
QuickSort(buffer.Slice(0, pointsFound));
QuickSort.Sort(buffer.Slice(0, pointsFound));
for (int point = 0; point < pointsFound; point += 2)
{
@ -439,57 +436,6 @@ namespace SixLabors.ImageSharp.Processing.Text.Processors
return fullBuffer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Swap(Span<float> data, int left, int right)
{
float tmp = data[left];
data[left] = data[right];
data[right] = tmp;
}
private static void QuickSort(Span<float> data)
{
QuickSort(data, 0, data.Length - 1);
}
private static void QuickSort(Span<float> data, int lo, int hi)
{
if (lo < hi)
{
int p = Partition(data, lo, hi);
QuickSort(data, lo, p);
QuickSort(data, p + 1, hi);
}
}
private static int Partition(Span<float> data, int lo, int hi)
{
float pivot = data[lo];
int i = lo - 1;
int j = hi + 1;
while (true)
{
do
{
i = i + 1;
}
while (data[i] < pivot && i < hi);
do
{
j = j - 1;
}
while (data[j] > pivot && j > lo);
if (i >= j)
{
return j;
}
Swap(data, i, j);
}
}
public void EndText()
{
}

84
src/ImageSharp.Drawing/Utils/QuickSort.cs

@ -0,0 +1,84 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Utils
{
/// <summary>
/// Optimized quick sort implementation for Span{float} input
/// </summary>
internal class QuickSort
{
/// <summary>
/// Sorts the elements of <paramref name="data"/> in ascending order
/// </summary>
/// <param name="data">The items to sort</param>
public static void Sort(Span<float> data)
{
if (data.Length < 2)
{
return;
}
if (data.Length == 2)
{
if (data[0] > data[1])
{
Swap(ref data[0], ref data[1]);
}
return;
}
Sort(ref data[0], 0, data.Length - 1);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Swap(ref float left, ref float right)
{
float tmp = left;
left = right;
right = tmp;
}
private static void Sort(ref float data0, int lo, int hi)
{
if (lo < hi)
{
int p = Partition(ref data0, lo, hi);
Sort(ref data0, lo, p);
Sort(ref data0, p + 1, hi);
}
}
private static int Partition(ref float data0, int lo, int hi)
{
float pivot = Unsafe.Add(ref data0, lo);
int i = lo - 1;
int j = hi + 1;
while (true)
{
do
{
i = i + 1;
}
while (Unsafe.Add(ref data0, i) < pivot && i < hi);
do
{
j = j - 1;
}
while (Unsafe.Add(ref data0, j) > pivot && j > lo);
if (i >= j)
{
return j;
}
Swap(ref Unsafe.Add(ref data0, i), ref Unsafe.Add(ref data0, j));
}
}
}
}

3
tests/ImageSharp.Tests/Drawing/BeziersTests.cs

@ -7,12 +7,11 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Drawing;
using SixLabors.ImageSharp.Processing.Overlays;
using SixLabors.Memory;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing
{
using SixLabors.Memory;
public class Beziers : FileTestBase
{
[Fact]

51
tests/ImageSharp.Tests/Drawing/Utils/QuickSortTests.cs

@ -0,0 +1,51 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Tests.Drawing.Utils
{
using System;
using System.Linq;
using SixLabors.ImageSharp.Utils;
using Xunit;
public class QuickSortTests
{
public static readonly TheoryData<float[]> Data = new TheoryData<float[]>()
{
new float[]{ 3, 2, 1 },
new float[0],
new float[] { 42},
new float[] { 1, 2},
new float[] { 2, 1},
new float[] { 5, 1, 2, 3, 0}
};
[Theory]
[MemberData(nameof(Data))]
public void Sort(float[] data)
{
float[] expected = data.ToArray();
Array.Sort(expected);
QuickSort.Sort(data);
Assert.Equal(expected, data);
}
[Fact]
public void SortSlice()
{
float[] data = { 3, 2, 1, 0, -1 };
Span<float> slice = data.AsSpan(1, 3);
QuickSort.Sort(slice);
float[] actual = slice.ToArray();
float[] expected = { 0, 1, 2 };
Assert.Equal(actual, expected);
}
}
}
Loading…
Cancel
Save