From 26edc70bcaaaf9da1ddb802aafa7d79b0b29ebbf Mon Sep 17 00:00:00 2001 From: Eric Henry Date: Sat, 3 Apr 2021 12:28:06 -0400 Subject: [PATCH] quicksort broken --- compiler/builtins/bitcode/src/list.zig | 52 ++++++++++++++++++++++++- compiler/builtins/bitcode/src/utils.zig | 6 +++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/compiler/builtins/bitcode/src/list.zig b/compiler/builtins/bitcode/src/list.zig index 380f0f7902..1aa4acbd72 100644 --- a/compiler/builtins/bitcode/src/list.zig +++ b/compiler/builtins/bitcode/src/list.zig @@ -690,6 +690,56 @@ fn listRangeHelp(allocator: *Allocator, comptime T: type, low: T, high: T) RocLi } } -pub fn listSortWith(list: RocList, transform: Opaque, wrapper: CompareFn, alignment: usize, element_width: usize) callconv(.C) RocList { +fn swap(source_ptr: [*]u8, element_width: usize, index_1: usize, index_2: usize) void { + const temp: [*]u8 = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, element_width) catch unreachable); + + const element_at_i = source_ptr + (index_1 * element_width); + const element_at_j = source_ptr + (index_2 * element_width); + // Store I Element in temp + @memcpy(temp, element_at_i, element_width); + + // Swap I Element with J Element + @memcpy(element_at_i, element_at_j, element_width); + + // Swap J Element with temp + @memcpy(element_at_j, temp, element_width); + + std.heap.c_allocator.free(temp[0..element_width]); +} + +fn partition(source_ptr: [*]u8, transform: Opaque, wrapper: CompareFn, element_width: usize, low: usize, high: usize) usize { + const pivot = source_ptr + (high * element_width); + var i = (low - 1); // Index of smaller element and indicates the right position of pivot found so far + var j = low; + + while (j <= high - 1) : (j += 1) { + const current_elem = source_ptr + (j * element_width); + const ordering = wrapper(transform, current_elem, pivot); + const order = @intToEnum(utils.Ordering, ordering); + // If current element is smaller than the pivot + if (order == utils.Ordering.LT) { + i += 1; // increment index of smaller element + swap(source_ptr, element_width, i, j); + } + } + swap(source_ptr, element_width, (i + 1), high); + return (i + 1); +} + +fn quicksort(list: RocList, transform: Opaque, wrapper: CompareFn, element_width: usize, low: usize, high: usize) RocList { + if (list.bytes) |source_ptr| { + if (low < high) { + const pi = partition(source_ptr, transform, wrapper, element_width, low, high); + + const _unused1 = quicksort(list, transform, wrapper, element_width, low, pi - 1); // before pi + const _unused2 = quicksort(list, transform, wrapper, element_width, pi + 1, high); // after pi + } + } return list; } + +pub fn listSortWith(list: RocList, transform: Opaque, wrapper: CompareFn, alignment: usize, element_width: usize) callconv(.C) RocList { + const low = 0; + const high = list.len() - 1; + return quicksort(list, transform, wrapper, element_width, low, high); +} diff --git a/compiler/builtins/bitcode/src/utils.zig b/compiler/builtins/bitcode/src/utils.zig index 6628c46ba6..b4bbabc690 100644 --- a/compiler/builtins/bitcode/src/utils.zig +++ b/compiler/builtins/bitcode/src/utils.zig @@ -157,3 +157,9 @@ pub const RocResult = extern struct { return !self.isOk(); } }; + +pub const Ordering = enum(u8) { + EQ, + GT, + LT, +};