From cbb9b5d9f04509260b8cea935a0441f63f33bc32 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 6 Oct 2023 23:58:53 -0700 Subject: [PATCH] std: add unstable sorting to array hash maps closes #17426 --- lib/std/array_hash_map.zig | 33 ++++++++++++++++++++++++++++++--- lib/std/multi_array_list.zig | 2 +- lib/std/sort.zig | 2 ++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/std/array_hash_map.zig b/lib/std/array_hash_map.zig index 1bb85a255d..75a86f63f6 100644 --- a/lib/std/array_hash_map.zig +++ b/lib/std/array_hash_map.zig @@ -1229,14 +1229,41 @@ pub fn ArrayHashMapUnmanaged( /// Sorts the entries and then rebuilds the index. /// `sort_ctx` must have this method: /// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool` + /// Uses a stable sorting algorithm. pub inline fn sort(self: *Self, sort_ctx: anytype) void { if (@sizeOf(ByIndexContext) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call sortContext instead."); - return self.sortContext(sort_ctx, undefined); + return sortContextInternal(self, .stable, sort_ctx, undefined); } - pub fn sortContext(self: *Self, sort_ctx: anytype, ctx: Context) void { - self.entries.sort(sort_ctx); + /// Sorts the entries and then rebuilds the index. + /// `sort_ctx` must have this method: + /// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool` + /// Uses an unstable sorting algorithm. + pub inline fn sortUnstable(self: *Self, sort_ctx: anytype) void { + if (@sizeOf(ByIndexContext) != 0) + @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call sortUnstableContext instead."); + return self.sortContextInternal(.unstable, sort_ctx, undefined); + } + + pub inline fn sortContext(self: *Self, sort_ctx: anytype, ctx: Context) void { + return sortContextInternal(self, .stable, sort_ctx, ctx); + } + + pub inline fn sortUnstableContext(self: *Self, sort_ctx: anytype, ctx: Context) void { + return sortContextInternal(self, .unstable, sort_ctx, ctx); + } + + fn sortContextInternal( + self: *Self, + comptime mode: std.sort.Mode, + sort_ctx: anytype, + ctx: Context, + ) void { + switch (mode) { + .stable => self.entries.sort(sort_ctx), + .unstable => self.entries.sortUnstable(sort_ctx), + } const header = self.index_header orelse return; header.reset(); self.insertAllEntriesIntoNewHeader(if (store_hash) {} else ctx, header); diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index c18d2c2a5a..11dec78036 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -467,7 +467,7 @@ pub fn MultiArrayList(comptime T: type) type { /// `ctx` has the following method: /// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool` - fn sortInternal(self: Self, a: usize, b: usize, ctx: anytype, comptime mode: enum { stable, unstable }) void { + fn sortInternal(self: Self, a: usize, b: usize, ctx: anytype, comptime mode: std.sort.Mode) void { const sort_context: struct { sub_ctx: @TypeOf(ctx), slice: Slice, diff --git a/lib/std/sort.zig b/lib/std/sort.zig index abeae29247..e110a8beb8 100644 --- a/lib/std/sort.zig +++ b/lib/std/sort.zig @@ -4,6 +4,8 @@ const testing = std.testing; const mem = std.mem; const math = std.math; +pub const Mode = enum { stable, unstable }; + pub const block = @import("sort/block.zig").block; pub const pdq = @import("sort/pdq.zig").pdq; pub const pdqContext = @import("sort/pdq.zig").pdqContext;