package sort import ( "fmt" "testing" "codeberg.org/snonux/algorithms/ds" ) // Store here so that Go isn't optimizing the benchmark away. var benchResult interface{} const minLength int = 1 const maxLength int = 1000000 const factor int = 100 const maxSlowLength int = 100000 var arrayListCache map[string]ds.ArrayList[int] type sortAlgorithm[V ds.Number] func(ds.ArrayList[V]) ds.ArrayList[V] type sortAlgorithmInt func([]int) []int func TestSleepSort(t *testing.T) { a := ds.NewRandomArrayList[int](10, 10) a = Sleep(a) if !a.Sorted() { t.Errorf("Array not sorted: %v", a) } } func TestSelectionSort(t *testing.T) { for i := minLength; i <= maxSlowLength; i *= factor { test(Selection[int], i, t) } } func TestInsertionSort(t *testing.T) { for i := minLength; i <= maxSlowLength; i *= factor { test(Insertion[int], i, t) } } func TestShellSort(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test(Shell[int], i, t) } } func TestMergeSort(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test(Merge[int], i, t) } } func TestBottomUpMergeSort(t *testing.T) { t.Log("Parallel merge sort") for i := minLength; i <= maxLength; i *= factor { test(BottomUpMerge[int], i, t) } test(BottomUpMerge[int], maxLength*2, t) } func TestParallelMergeSort(t *testing.T) { t.Log("Bottom-up merge sort") for i := minLength; i <= maxLength; i *= factor { test(ParallelMerge[int], i, t) } } func TestQuickSort(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test(Quick[int], i, t) } } func TestParallelQuickSort(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test(ParallelQuick[int], i, t) } } func TestQuick3WaySort(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test(Quick3Way[int], i, t) } } func TestShuffleSort(t *testing.T) { for i := 10; i <= maxLength; i *= factor { testShuffleSort(Shuffle[int], i, t) } } func BenchmarkInsertionSort(b *testing.B) { for i := minLength; i <= maxSlowLength; i *= factor { benchmark(Insertion[int], i, b) } } func BenchmarkSelectionSort(b *testing.B) { for i := minLength; i <= maxSlowLength; i *= factor { benchmark(Selection[int], i, b) } } func BenchmarkShellSort(b *testing.B) { for i := minLength; i <= maxLength; i *= factor { benchmark(Shell[int], i, b) } } func BenchmarkMergeSort(b *testing.B) { for i := minLength; i <= maxLength; i *= factor { benchmark(Merge[int], i, b) } } func BenchmarkBottomUpMergeSort(b *testing.B) { for i := minLength; i <= maxLength; i *= factor { benchmark(BottomUpMerge[int], i, b) } } func BenchmarkParallelMergeSort(b *testing.B) { for i := minLength; i <= maxLength; i *= factor { benchmark(ParallelMerge[int], i, b) } } func BenchmarkQuickSort(b *testing.B) { for i := minLength; i <= maxLength; i *= factor { benchmark(Quick[int], i, b) } } func BenchmarkParallelQuickSort(b *testing.B) { for i := minLength; i <= maxLength; i *= factor { benchmark(ParallelQuick[int], i, b) } } func BenchmarkQuick3WaySort(b *testing.B) { for i := minLength; i <= maxLength; i *= factor { benchmark(Quick3Way[int], i, b) } } /* func BenchmarkShuffleSort(b *testing.B) { for i := minLength; i <= maxLength; i *= factor { benchmark(Shuffle[int], i, b) } } */ func test[V ds.Number](sort sortAlgorithm[V], l int, t *testing.T) { cb := func(t *testing.T) { t.Parallel() a := ds.NewRandomArrayList[V](l, -1) a = sort(a) if !a.Sorted() { t.Errorf("Array not sorted: %v", a) } } t.Run(fmt.Sprintf("%d", l), cb) } func testShuffleSort[V ds.Number](sort sortAlgorithm[V], l int, t *testing.T) { cb := func(t *testing.T) { t.Parallel() a := sort(ds.NewAscendingArrayList[V](l)) if a.Sorted() { t.Errorf("Array sorted: %v", a.FirstN(10)) } } t.Run(fmt.Sprintf("%d", l), cb) } func benchmark[V ds.Number](sort sortAlgorithm[V], l int, b *testing.B) { a := ds.NewRandomArrayList[V](l, -1) aux := ds.NewArrayList[V](l) b.Run(fmt.Sprintf("random(%d)", l), func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { copy(aux, a) benchResult = sort(aux) } }) a = ds.NewAscendingArrayList[V](l) b.Run(fmt.Sprintf("ascending(%d)", l), func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { copy(aux, a) benchResult = sort(aux) } }) a = ds.NewDescendingArrayList[V](l) b.Run(fmt.Sprintf("descending(%d)", l), func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { copy(aux, a) benchResult = sort(aux) } }) }