mirror of https://github.com/SixLabors/ImageSharp
6 changed files with 140 additions and 127 deletions
@ -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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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…
Reference in new issue