github.com/primecitizens/pcz/std@v0.2.1/algo/sort/sort.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2022 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 package sort 9 10 import ( 11 "github.com/primecitizens/pcz/std/core/bits" 12 "github.com/primecitizens/pcz/std/core/cmp" 13 "github.com/primecitizens/pcz/std/core/iter" 14 "github.com/primecitizens/pcz/std/core/mark" 15 ) 16 17 // An implementation of Interface can be sorted by the routines in this package. 18 // The methods refer to elements of the underlying collection by integer index. 19 type Interface interface { 20 // A sortable collection must have finite elements. 21 iter.Finite 22 23 // Less reports whether the element with index i 24 // must sort before the element with index j. 25 // 26 // If both Less(i, j) and Less(j, i) are false, 27 // then the elements at index i and j are considered equal. 28 // Ascend may place equal elements in any order in the final result, 29 // while Stable preserves the original input order of equal elements. 30 // 31 // Less must describe a transitive ordering: 32 // - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well. 33 // - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well. 34 // 35 // Note that floating-point comparison (the < operator on float32 or float64 values) 36 // is not a transitive ordering when not-a-number (NaN) values are involved. 37 // See Float64Slice.Less for a correct implementation for floating-point values. 38 Less(i, j int) bool 39 40 // Swap swaps the elements with indexes i and j. 41 Swap(i, j int) 42 } 43 44 // Ascend sorts data in ascending order as determined by the Less method. 45 // 46 // It makes one call to data.Len to determine n and O(n*log(n)) calls to 47 // data.Less and data.Swap. The sort is not guaranteed to be stable. 48 func Ascend[T Interface](data T) { 49 n := data.Len() 50 if n <= 1 { 51 return 52 } 53 54 pdqsort(data, 0, n, bits.Len(uint(n))) 55 } 56 57 // StableAscend sorts data in ascending order as determined by the Less method, 58 // while keeping the original order of equal elements. 59 // 60 // It makes one call to data.Len to determine n, O(n*log(n)) calls to 61 // data.Less and O(n*log(n)*log(n)) calls to data.Swap. 62 func StableAscend[T Interface](data T) { 63 stable(data, data.Len()) 64 } 65 66 // IsAscend reports whether data is sorted in ascending order. 67 func IsAscend[T Interface](data T) bool { 68 n := data.Len() 69 for i := n - 1; i > 0; i-- { 70 if data.Less(i, i-1) { 71 return false 72 } 73 } 74 return true 75 } 76 77 func SliceAscend[T any](data []T, cmp func(data []T, i, j int) bool) { 78 x := SliceSorter[T]{ 79 Data: data, 80 LessFunc: cmp, 81 } 82 83 Ascend(mark.NoEscape(&x)) 84 } 85 86 func SliceStableAscend[T any](data []T, cmp func(data []T, i, j int) bool) { 87 x := SliceSorter[T]{ 88 Data: data, 89 LessFunc: cmp, 90 } 91 92 stable(mark.NoEscape(&x), len(data)) 93 } 94 95 func SliceIsAscend[T any](data []T, cmp func(data []T, i, j int) bool) bool { 96 x := SliceSorter[T]{ 97 Data: data, 98 LessFunc: cmp, 99 } 100 101 return IsAscend(mark.NoEscape(&x)) 102 } 103 104 func BuiltinAscend[T cmp.FOrdered](data []T) { 105 SliceAscend(data, BuiltinLessFunc[T]) 106 } 107 108 func BuiltinIsAscend[T cmp.FOrdered](data []T) bool { 109 return SliceIsAscend(data, BuiltinLessFunc[T]) 110 }