diff --git a/core/slice/sort.odin b/core/slice/sort.odin index 779ba37fd..5319fbaaa 100644 --- a/core/slice/sort.odin +++ b/core/slice/sort.odin @@ -38,18 +38,39 @@ sort :: proc(data: $T/[]$E) where ORD(E) { } } -// sort sorts a slice + +sort_by_indices :: proc(data: $T/[]$E, indices: []int, allocator := context.allocator) -> (sorted: T) { + assert(len(data) == len(indices)) + sorted = make([]int, len(data), allocator) + for v, i in indices { + sorted[i] = data[v] + } +} + +sort_by_indices_overwrite :: proc(data: $T/[]$E, indices: []int) { + assert(len(data) == len(indices)) + temp := make([]int, len(data), context.temp_allocator) + defer delete(temp) + for v, i in indices { + temp[i] = data[v] + } + swap_with_slice(data, temp) +} + +// sort sorts a slice and returns a slice of the original indices // This sort is not guaranteed to be stable -sort_with_indices :: proc(data: $T/[]$E, indices: []int) where ORD(E) { +sort_with_indices :: proc(data: $T/[]$E, allocator := context.allocator) -> (indices: []int) where ORD(E) { when size_of(E) != 0 { if n := len(data); n > 1 { - assert(len(data) == len(indices)) + indices = make([]int, len(data), allocator) for _, idx in indices { indices[idx] = idx } _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), struct{}{}, .Ordered) + return indices } } + return nil } // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j" @@ -64,16 +85,18 @@ sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j" // This sort is not guaranteed to be stable -sort_by_with_indices :: proc(data: $T/[]$E, indices: []int, less: proc(i, j: E) -> bool) { +sort_by_with_indices :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool, allocator := context.allocator) -> (indices : []int) { when size_of(E) != 0 { if n := len(data); n > 1 { - assert(len(data) == len(indices)) + indices = make([]int, len(data), allocator) for _, idx in indices { indices[idx] = idx } _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), less, .Less) + return indices } } + return nil } sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { diff --git a/tests/core/slice/test_core_slice.odin b/tests/core/slice/test_core_slice.odin index 12577ab20..8caf911e8 100644 --- a/tests/core/slice/test_core_slice.odin +++ b/tests/core/slice/test_core_slice.odin @@ -51,23 +51,17 @@ test_sort_with_indices :: proc(t: ^testing.T) { r := rand.create(seed) vals := make([]u64, test_size) - f_idx := make([]int, test_size) // Forward index, will be sorted + defer delete(vals) r_idx := make([]int, test_size) // Reverse index - defer { - delete(vals) - delete(f_idx) - delete(r_idx) - } - // Set up test values for _, i in vals { vals[i] = rand.uint64(&r) - f_idx[i] = i } // Sort - slice.sort_with_indices(vals, f_idx) + f_idx := slice.sort_with_indices(vals) + defer delete(f_idx) // Verify sorted test values rand.init(&r, seed) @@ -94,4 +88,4 @@ test_sort_with_indices :: proc(t: ^testing.T) { last = v } } -} \ No newline at end of file +}