mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-15 07:43:13 +00:00
have sort_with_indices allocate. Add a couple convenience procs for using the indices result to sort other slices.
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user