std.sort: add pdqsort and heapsort

This commit is contained in:
Ali Chraghi 2023-05-23 15:33:12 +03:30 committed by Andrew Kelley
parent bfe02ff61a
commit 3db3cf7790
37 changed files with 1797 additions and 1386 deletions

View file

@ -93,7 +93,7 @@ pub const HuffmanEncoder = struct {
return; return;
} }
self.lfs = list; self.lfs = list;
sort.sort(LiteralNode, self.lfs, {}, byFreq); mem.sort(LiteralNode, self.lfs, {}, byFreq);
// Get the number of literals for each bit count // Get the number of literals for each bit count
var bit_count = self.bitCounts(list, max_bits); var bit_count = self.bitCounts(list, max_bits);
@ -270,7 +270,7 @@ pub const HuffmanEncoder = struct {
var chunk = list[list.len - @intCast(u32, bits) ..]; var chunk = list[list.len - @intCast(u32, bits) ..];
self.lns = chunk; self.lns = chunk;
sort.sort(LiteralNode, self.lns, {}, byLiteral); mem.sort(LiteralNode, self.lns, {}, byLiteral);
for (chunk) |node| { for (chunk) |node| {
self.codes[node.literal] = HuffCode{ self.codes[node.literal] = HuffCode{

View file

@ -107,7 +107,7 @@ fn buildFseTable(values: []const u16, entries: []Table.Fse) !void {
position &= entries.len - 1; position &= entries.len - 1;
} }
} }
std.sort.sort(u16, temp_states[0..probability], {}, std.sort.asc(u16)); std.mem.sort(u16, temp_states[0..probability], {}, std.sort.asc(u16));
for (0..probability) |i| { for (0..probability) |i| {
entries[temp_states[i]] = if (i < double_state_count) Table.Fse{ entries[temp_states[i]] = if (i < double_state_count) Table.Fse{
.symbol = @intCast(u8, symbol), .symbol = @intCast(u8, symbol),

View file

@ -124,7 +124,7 @@ fn assignSymbols(weight_sorted_prefixed_symbols: []LiteralsSection.HuffmanTree.P
}; };
} }
std.sort.sort( std.mem.sort(
LiteralsSection.HuffmanTree.PrefixedSymbol, LiteralsSection.HuffmanTree.PrefixedSymbol,
weight_sorted_prefixed_symbols, weight_sorted_prefixed_symbols,
weights, weights,

View file

@ -28,7 +28,7 @@ pub fn ComptimeStringMap(comptime V: type, comptime kvs_list: anytype) type {
sorted_kvs[i] = .{ .key = kv.@"0", .value = {} }; sorted_kvs[i] = .{ .key = kv.@"0", .value = {} };
} }
} }
std.sort.sort(KV, &sorted_kvs, {}, lenAsc); mem.sort(KV, &sorted_kvs, {}, lenAsc);
const min_len = sorted_kvs[0].key.len; const min_len = sorted_kvs[0].key.len;
const max_len = sorted_kvs[sorted_kvs.len - 1].key.len; const max_len = sorted_kvs[sorted_kvs.len - 1].key.len;
var len_indexes: [max_len + 1]usize = undefined; var len_indexes: [max_len + 1]usize = undefined;

View file

@ -1211,7 +1211,7 @@ fn readMachODebugInfo(allocator: mem.Allocator, macho_file: File) !ModuleDebugIn
// Even though lld emits symbols in ascending order, this debug code // Even though lld emits symbols in ascending order, this debug code
// should work for programs linked in any valid way. // should work for programs linked in any valid way.
// This sort is so that we can binary search later. // This sort is so that we can binary search later.
std.sort.sort(MachoSymbol, symbols, {}, MachoSymbol.addressLessThan); mem.sort(MachoSymbol, symbols, {}, MachoSymbol.addressLessThan);
return ModuleDebugInfo{ return ModuleDebugInfo{
.base_address = undefined, .base_address = undefined,

View file

@ -1314,7 +1314,7 @@ pub fn EnumIndexer(comptime E: type) type {
} }
}; };
} }
std.sort.sort(EnumField, &fields, {}, ascByValue); std.mem.sort(EnumField, &fields, {}, ascByValue);
const min = fields[0].value; const min = fields[0].value;
const max = fields[fields.len - 1].value; const max = fields[fields.len - 1].value;
const fields_len = fields.len; const fields_len = fields.len;

View file

@ -191,7 +191,7 @@ pub const Headers = struct {
/// Sorts the headers in lexicographical order. /// Sorts the headers in lexicographical order.
pub fn sort(headers: *Headers) void { pub fn sort(headers: *Headers) void {
std.sort.sort(Field, headers.list.items, {}, Field.lessThan); std.mem.sort(Field, headers.list.items, {}, Field.lessThan);
headers.rebuildIndex(); headers.rebuildIndex();
} }

View file

@ -566,6 +566,34 @@ test "zeroInit" {
}, nested_baz); }, nested_baz);
} }
pub fn sort(
comptime T: type,
items: []T,
context: anytype,
comptime lessThanFn: fn (@TypeOf(context), lhs: T, rhs: T) bool,
) void {
std.sort.block(T, items, context, lessThanFn);
}
pub fn sortUnstable(
comptime T: type,
items: []T,
context: anytype,
comptime lessThanFn: fn (@TypeOf(context), lhs: T, rhs: T) bool,
) void {
std.sort.pdq(T, items, context, lessThanFn);
}
/// TODO: currently this just calls `insertionSortContext`. The block sort implementation
/// in this file needs to be adapted to use the sort context.
pub fn sortContext(a: usize, b: usize, context: anytype) void {
std.sort.insertionContext(a, b, context);
}
pub fn sortUnstableContext(a: usize, b: usize, context: anytype) void {
std.sort.pdqContext(a, b, context);
}
/// Compares two slices of numbers lexicographically. O(n). /// Compares two slices of numbers lexicographically. O(n).
pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order { pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order {
const n = math.min(lhs.len, rhs.len); const n = math.min(lhs.len, rhs.len);

View file

@ -985,7 +985,7 @@ pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const De
for (decls, 0..) |decl, i| { for (decls, 0..) |decl, i| {
array[i] = &@field(Namespace, decl.name); array[i] = &@field(Namespace, decl.name);
} }
std.sort.sort(*const Decl, &array, {}, S.declNameLessThan); mem.sort(*const Decl, &array, {}, S.declNameLessThan);
return &array; return &array;
} }
} }

View file

@ -160,7 +160,7 @@ pub fn MultiArrayList(comptime T: type) type {
return lhs.alignment > rhs.alignment; return lhs.alignment > rhs.alignment;
} }
}; };
std.sort.sort(Data, &data, {}, Sort.lessThan); mem.sort(Data, &data, {}, Sort.lessThan);
var sizes_bytes: [fields.len]usize = undefined; var sizes_bytes: [fields.len]usize = undefined;
var field_indexes: [fields.len]usize = undefined; var field_indexes: [fields.len]usize = undefined;
for (data, 0..) |elem, i| { for (data, 0..) |elem, i| {
@ -488,10 +488,7 @@ pub fn MultiArrayList(comptime T: type) type {
} }
}; };
std.sort.sortContext(self.len, SortContext{ mem.sortContext(0, self.len, SortContext{ .sub_ctx = ctx, .slice = self.slice() });
.sub_ctx = ctx,
.slice = self.slice(),
});
} }
fn capacityInBytes(capacity: usize) usize { fn capacityInBytes(capacity: usize) usize {

View file

@ -1082,7 +1082,7 @@ fn linuxLookupName(
key |= (MAXADDRS - @intCast(i32, i)) << DAS_ORDER_SHIFT; key |= (MAXADDRS - @intCast(i32, i)) << DAS_ORDER_SHIFT;
addr.sortkey = key; addr.sortkey = key;
} }
std.sort.sort(LookupAddr, addrs.items, {}, addrCmpLessThan); mem.sort(LookupAddr, addrs.items, {}, addrCmpLessThan);
} }
const Policy = struct { const Policy = struct {

File diff suppressed because it is too large Load diff

1066
lib/std/sort/block.zig Normal file

File diff suppressed because it is too large Load diff

331
lib/std/sort/pdq.zig Normal file
View file

@ -0,0 +1,331 @@
const std = @import("../std.zig");
const sort = std.sort;
const mem = std.mem;
const math = std.math;
const testing = std.testing;
/// Unstable in-place sort. n best case, n*log(n) worst case and average case.
/// log(n) memory (no allocator required).
///
/// Sorts in ascending order with respect to the given `lessThan` function.
pub fn pdq(
comptime T: type,
items: []T,
context: anytype,
comptime lessThanFn: fn (context: @TypeOf(context), lhs: T, rhs: T) bool,
) void {
const Context = struct {
items: []T,
sub_ctx: @TypeOf(context),
pub fn lessThan(ctx: @This(), a: usize, b: usize) bool {
return lessThanFn(ctx.sub_ctx, ctx.items[a], ctx.items[b]);
}
pub fn swap(ctx: @This(), a: usize, b: usize) void {
return mem.swap(T, &ctx.items[a], &ctx.items[b]);
}
};
pdqContext(0, items.len, Context{ .items = items, .sub_ctx = context });
}
const Hint = enum {
increasing,
decreasing,
unknown,
};
/// Unstable in-place sort. O(n) best case, O(n*log(n)) worst case and average case.
/// O(log(n)) memory (no allocator required).
///
/// Sorts in ascending order with respect to the given `lessThan` function.
pub fn pdqContext(a: usize, b: usize, context: anytype) void {
// slices of up to this length get sorted using insertion sort.
const max_insertion = 24;
// number of allowed imbalanced partitions before switching to heap sort.
const max_limit = std.math.floorPowerOfTwo(usize, b) + 1;
// set upper bound on stack memory usage.
const Range = struct { a: usize, b: usize, limit: usize };
const stack_size = math.log2(math.maxInt(usize) + 1);
var stack: [stack_size]Range = undefined;
var range = Range{ .a = a, .b = b, .limit = max_limit };
var top: usize = 0;
while (true) {
var was_balanced = true;
var was_partitioned = true;
while (true) {
const len = range.b - range.a;
// very short slices get sorted using insertion sort.
if (len <= max_insertion) {
break sort.insertionContext(range.a, range.b, context);
}
// if too many bad pivot choices were made, simply fall back to heapsort in order to
// guarantee O(n*log(n)) worst-case.
if (range.limit == 0) {
break sort.heapContext(range.a, range.b, context);
}
// if the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
// some elements around. Hopefully we'll choose a better pivot this time.
if (!was_balanced) {
breakPatterns(range.a, range.b, context);
range.limit -= 1;
}
// choose a pivot and try guessing whether the slice is already sorted.
var pivot: usize = 0;
var hint = chosePivot(range.a, range.b, &pivot, context);
if (hint == .decreasing) {
// The maximum number of swaps was performed, so items are likely
// in reverse order. Reverse it to make sorting faster.
reverseRange(range.a, range.b, context);
pivot = (range.b - 1) - (pivot - range.a);
hint = .increasing;
}
// if the last partitioning was decently balanced and didn't shuffle elements, and if pivot
// selection predicts the slice is likely already sorted...
if (was_balanced and was_partitioned and hint == .increasing) {
// try identifying several out-of-order elements and shifting them to correct
// positions. If the slice ends up being completely sorted, we're done.
if (partialInsertionSort(range.a, range.b, context)) break;
}
// if the chosen pivot is equal to the predecessor, then it's the smallest element in the
// slice. Partition the slice into elements equal to and elements greater than the pivot.
// This case is usually hit when the slice contains many duplicate elements.
if (range.a > 0 and !context.lessThan(range.a - 1, pivot)) {
range.a = partitionEqual(range.a, range.b, pivot, context);
continue;
}
// partition the slice.
var mid = pivot;
was_partitioned = partition(range.a, range.b, &mid, context);
const left_len = mid - range.a;
const right_len = range.b - mid;
const balanced_threshold = len / 8;
if (left_len < right_len) {
was_balanced = left_len >= balanced_threshold;
stack[top] = .{ .a = range.a, .b = mid, .limit = range.limit };
top += 1;
range.a = mid + 1;
} else {
was_balanced = right_len >= balanced_threshold;
stack[top] = .{ .a = mid + 1, .b = range.b, .limit = range.limit };
top += 1;
range.b = mid;
}
}
top = math.sub(usize, top, 1) catch break;
range = stack[top];
}
}
/// partitions `items[a..b]` into elements smaller than `items[pivot]`,
/// followed by elements greater than or equal to `items[pivot]`.
///
/// sets the new pivot.
/// returns `true` if already partitioned.
fn partition(a: usize, b: usize, pivot: *usize, context: anytype) bool {
// move pivot to the first place
context.swap(a, pivot.*);
var i = a + 1;
var j = b - 1;
while (i <= j and context.lessThan(i, a)) i += 1;
while (i <= j and !context.lessThan(j, a)) j -= 1;
// check if items are already partitioned (no item to swap)
if (i > j) {
// put pivot back to the middle
context.swap(j, a);
pivot.* = j;
return true;
}
context.swap(i, j);
i += 1;
j -= 1;
while (true) {
while (i <= j and context.lessThan(i, a)) i += 1;
while (i <= j and !context.lessThan(j, a)) j -= 1;
if (i > j) break;
context.swap(i, j);
i += 1;
j -= 1;
}
// TODO: Enable the BlockQuicksort optimization
context.swap(j, a);
pivot.* = j;
return false;
}
/// partitions items into elements equal to `items[pivot]`
/// followed by elements greater than `items[pivot]`.
///
/// it assumed that `items[a..b]` does not contain elements smaller than the `items[pivot]`.
fn partitionEqual(a: usize, b: usize, pivot: usize, context: anytype) usize {
// move pivot to the first place
context.swap(a, pivot);
var i = a + 1;
var j = b - 1;
while (true) {
while (i <= j and !context.lessThan(a, i)) i += 1;
while (i <= j and context.lessThan(a, j)) j -= 1;
if (i > j) break;
context.swap(i, j);
i += 1;
j -= 1;
}
return i;
}
/// partially sorts a slice by shifting several out-of-order elements around.
///
/// returns `true` if the slice is sorted at the end. This function is `O(n)` worst-case.
fn partialInsertionSort(a: usize, b: usize, context: anytype) bool {
@setCold(true);
// maximum number of adjacent out-of-order pairs that will get shifted
const max_steps = 5;
// if the slice is shorter than this, don't shift any elements
const shortest_shifting = 50;
var i = a + 1;
for (0..max_steps) |_| {
// find the next pair of adjacent out-of-order elements.
while (i < b and !context.lessThan(i, i - 1)) i += 1;
// are we done?
if (i == b) return true;
// don't shift elements on short arrays, that has a performance cost.
if (b - a < shortest_shifting) return false;
// swap the found pair of elements. This puts them in correct order.
context.swap(i, i - 1);
// shift the smaller element to the left.
if (i - a >= 2) {
var j = i - 1;
while (j >= 1) : (j -= 1) {
if (!context.lessThan(j, j - 1)) break;
context.swap(j, j - 1);
}
}
// shift the greater element to the right.
if (b - i >= 2) {
var j = i + 1;
while (j < b) : (j += 1) {
if (!context.lessThan(j, j - 1)) break;
context.swap(j, j - 1);
}
}
}
return false;
}
fn breakPatterns(a: usize, b: usize, context: anytype) void {
@setCold(true);
const len = b - a;
if (len < 8) return;
var rand = @intCast(u64, len);
const modulus = math.ceilPowerOfTwoAssert(u64, len);
var i = a + (len / 4) * 2 - 1;
while (i <= a + (len / 4) * 2 + 1) : (i += 1) {
// xorshift64
rand ^= rand << 13;
rand ^= rand >> 7;
rand ^= rand << 17;
var other = @intCast(usize, rand & (modulus - 1));
if (other >= len) other -= len;
context.swap(i, a + other);
}
}
/// choses a pivot in `items[a..b]`.
/// swaps likely_sorted when `items[a..b]` seems to be already sorted.
fn chosePivot(a: usize, b: usize, pivot: *usize, context: anytype) Hint {
// minimum length for using the Tukey's ninther method
const shortest_ninther = 50;
// max_swaps is the maximum number of swaps allowed in this function
const max_swaps = 4 * 3;
var len = b - a;
var i = a + len / 4 * 1;
var j = a + len / 4 * 2;
var k = a + len / 4 * 3;
var swaps: usize = 0;
if (len >= 8) {
if (len >= shortest_ninther) {
// find medians in the neighborhoods of `i`, `j` and `k`
i = sort3(i - 1, i, i + 1, &swaps, context);
j = sort3(j - 1, j, j + 1, &swaps, context);
k = sort3(k - 1, k, k + 1, &swaps, context);
}
// find the median among `i`, `j` and `k`
j = sort3(i, j, k, &swaps, context);
}
pivot.* = j;
return switch (swaps) {
0 => .increasing,
max_swaps => .decreasing,
else => .unknown,
};
}
fn sort3(a: usize, b: usize, c: usize, swaps: *usize, context: anytype) usize {
if (context.lessThan(b, a)) {
swaps.* += 1;
context.swap(b, a);
}
if (context.lessThan(c, b)) {
swaps.* += 1;
context.swap(c, b);
}
if (context.lessThan(b, a)) {
swaps.* += 1;
context.swap(b, a);
}
return b;
}
fn reverseRange(a: usize, b: usize, context: anytype) void {
var i = a;
var j = b - 1;
while (i < j) {
context.swap(i, j);
i += 1;
j -= 1;
}
}

View file

@ -672,7 +672,7 @@ fn addPackageTableToCacheHash(
} }
} }
// Sort the slice by package name // Sort the slice by package name
std.sort.sort(Package.Table.KV, packages, {}, struct { mem.sort(Package.Table.KV, packages, {}, struct {
fn lessThan(_: void, lhs: Package.Table.KV, rhs: Package.Table.KV) bool { fn lessThan(_: void, lhs: Package.Table.KV, rhs: Package.Table.KV) bool {
return std.mem.lessThan(u8, lhs.key, rhs.key); return std.mem.lessThan(u8, lhs.key, rhs.key);
} }

View file

@ -672,7 +672,7 @@ fn computePackageHash(
} }
} }
std.sort.sort(*HashedFile, all_files.items, {}, HashedFile.lessThan); mem.sort(*HashedFile, all_files.items, {}, HashedFile.lessThan);
var hasher = Manifest.Hash.init(.{}); var hasher = Manifest.Hash.init(.{});
var any_failures = false; var any_failures = false;

View file

@ -60,7 +60,7 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {
if (self.ranges.items.len == 0) if (self.ranges.items.len == 0)
return false; return false;
std.sort.sort(Range, self.ranges.items, LessThanContext{ std.mem.sort(Range, self.ranges.items, LessThanContext{
.ty = ty, .ty = ty,
.module = self.module, .module = self.module,
}, lessThan); }, lessThan);

View file

@ -30979,7 +30979,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
ctx.struct_obj.fields.values()[b].ty.abiAlignment(target); ctx.struct_obj.fields.values()[b].ty.abiAlignment(target);
} }
}; };
std.sort.sort(u32, optimized_order, AlignSortContext{ mem.sort(u32, optimized_order, AlignSortContext{
.struct_obj = struct_obj, .struct_obj = struct_obj,
.sema = sema, .sema = sema,
}, AlignSortContext.lessThan); }, AlignSortContext.lessThan);

View file

@ -2176,7 +2176,7 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
} }
}; };
const sort_context = SortContext{ .frame_align = frame_align }; const sort_context = SortContext{ .frame_align = frame_align };
std.sort.sort(FrameIndex, stack_frame_order, sort_context, SortContext.lessThan); mem.sort(FrameIndex, stack_frame_order, sort_context, SortContext.lessThan);
} }
const call_frame_align = frame_align[@enumToInt(FrameIndex.call_frame)]; const call_frame_align = frame_align[@enumToInt(FrameIndex.call_frame)];

View file

@ -770,7 +770,7 @@ const mnemonic_to_encodings_map = init: {
@setEvalBranchQuota(30_000); @setEvalBranchQuota(30_000);
const encodings = @import("encodings.zig"); const encodings = @import("encodings.zig");
var entries = encodings.table; var entries = encodings.table;
std.sort.sort(encodings.Entry, &entries, {}, struct { std.mem.sort(encodings.Entry, &entries, {}, struct {
fn lessThan(_: void, lhs: encodings.Entry, rhs: encodings.Entry) bool { fn lessThan(_: void, lhs: encodings.Entry, rhs: encodings.Entry) bool {
return @enumToInt(lhs[0]) < @enumToInt(rhs[0]); return @enumToInt(lhs[0]) < @enumToInt(rhs[0]);
} }

View file

@ -1292,7 +1292,7 @@ pub const CType = extern union {
fn sortFields(self: *@This(), fields_len: usize) []Payload.Fields.Field { fn sortFields(self: *@This(), fields_len: usize) []Payload.Fields.Field {
const Field = Payload.Fields.Field; const Field = Payload.Fields.Field;
const slice = self.storage.anon.fields[0..fields_len]; const slice = self.storage.anon.fields[0..fields_len];
std.sort.sort(Field, slice, {}, struct { mem.sort(Field, slice, {}, struct {
fn before(_: void, lhs: Field, rhs: Field) bool { fn before(_: void, lhs: Field, rhs: Field) bool {
return lhs.alignas.@"align" > rhs.alignas.@"align"; return lhs.alignas.@"align" > rhs.alignas.@"align";
} }

View file

@ -1837,7 +1837,7 @@ fn writeBaseRelocations(self: *Coff) !void {
pages.appendAssumeCapacity(page.*); pages.appendAssumeCapacity(page.*);
} }
} }
std.sort.sort(u32, pages.items, {}, std.sort.asc(u32)); mem.sort(u32, pages.items, {}, std.sort.asc(u32));
var buffer = std.ArrayList(u8).init(gpa); var buffer = std.ArrayList(u8).init(gpa);
defer buffer.deinit(); defer buffer.deinit();

View file

@ -209,7 +209,7 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)
// afterwards by address in each group. Normally, dysymtab should // afterwards by address in each group. Normally, dysymtab should
// be enough to guarantee the sort, but turns out not every compiler // be enough to guarantee the sort, but turns out not every compiler
// is kind enough to specify the symbols in the correct order. // is kind enough to specify the symbols in the correct order.
sort.sort(SymbolAtIndex, sorted_all_syms.items, self, SymbolAtIndex.lessThan); mem.sort(SymbolAtIndex, sorted_all_syms.items, self, SymbolAtIndex.lessThan);
var prev_sect_id: u8 = 0; var prev_sect_id: u8 = 0;
var section_index_lookup: ?Entry = null; var section_index_lookup: ?Entry = null;
@ -462,7 +462,7 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
sorted_sections[id] = .{ .header = sect, .id = @intCast(u8, id) }; sorted_sections[id] = .{ .header = sect, .id = @intCast(u8, id) };
} }
std.sort.sort(SortedSection, sorted_sections, {}, sectionLessThanByAddress); mem.sort(SortedSection, sorted_sections, {}, sectionLessThanByAddress);
var sect_sym_index: u32 = 0; var sect_sym_index: u32 = 0;
for (sorted_sections) |section| { for (sorted_sections) |section| {
@ -663,7 +663,7 @@ fn parseRelocs(self: *Object, gpa: Allocator, sect_id: u8) !void {
if (self.getSourceRelocs(section)) |relocs| { if (self.getSourceRelocs(section)) |relocs| {
try self.relocations.ensureUnusedCapacity(gpa, relocs.len); try self.relocations.ensureUnusedCapacity(gpa, relocs.len);
self.relocations.appendUnalignedSliceAssumeCapacity(relocs); self.relocations.appendUnalignedSliceAssumeCapacity(relocs);
std.sort.sort(macho.relocation_info, self.relocations.items[start..], {}, relocGreaterThan); mem.sort(macho.relocation_info, self.relocations.items[start..], {}, relocGreaterThan);
} }
self.section_relocs_lookup.items[sect_id] = start; self.section_relocs_lookup.items[sect_id] = start;
} }
@ -901,7 +901,7 @@ pub fn parseDataInCode(self: *Object, gpa: Allocator) !void {
const dice = @ptrCast([*]align(1) const macho.data_in_code_entry, self.contents.ptr + cmd.dataoff)[0..ndice]; const dice = @ptrCast([*]align(1) const macho.data_in_code_entry, self.contents.ptr + cmd.dataoff)[0..ndice];
try self.data_in_code.ensureTotalCapacityPrecise(gpa, dice.len); try self.data_in_code.ensureTotalCapacityPrecise(gpa, dice.len);
self.data_in_code.appendUnalignedSliceAssumeCapacity(dice); self.data_in_code.appendUnalignedSliceAssumeCapacity(dice);
std.sort.sort(macho.data_in_code_entry, self.data_in_code.items, {}, diceLessThan); mem.sort(macho.data_in_code_entry, self.data_in_code.items, {}, diceLessThan);
} }
fn diceLessThan(ctx: void, lhs: macho.data_in_code_entry, rhs: macho.data_in_code_entry) bool { fn diceLessThan(ctx: void, lhs: macho.data_in_code_entry, rhs: macho.data_in_code_entry) bool {

View file

@ -411,7 +411,7 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
} }
var slice = common_encodings_counts.values(); var slice = common_encodings_counts.values();
std.sort.sort(CommonEncWithCount, slice, {}, CommonEncWithCount.greaterThan); mem.sort(CommonEncWithCount, slice, {}, CommonEncWithCount.greaterThan);
var i: u7 = 0; var i: u7 = 0;
while (i < slice.len) : (i += 1) { while (i < slice.len) : (i += 1) {

View file

@ -39,7 +39,7 @@ pub fn finalize(rebase: *Rebase, gpa: Allocator) !void {
const writer = rebase.buffer.writer(gpa); const writer = rebase.buffer.writer(gpa);
std.sort.sort(Entry, rebase.entries.items, {}, Entry.lessThan); std.mem.sort(Entry, rebase.entries.items, {}, Entry.lessThan);
try setTypePointer(writer); try setTypePointer(writer);

View file

@ -47,7 +47,7 @@ pub fn Bind(comptime Ctx: type, comptime Target: type) type {
const writer = self.buffer.writer(gpa); const writer = self.buffer.writer(gpa);
std.sort.sort(Entry, self.entries.items, ctx, Entry.lessThan); std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan);
var start: usize = 0; var start: usize = 0;
var seg_id: ?u8 = null; var seg_id: ?u8 = null;

View file

@ -1441,7 +1441,7 @@ pub const Zld = struct {
} }
} }
std.sort.sort(Section, sections.items, {}, SortSection.lessThan); mem.sort(Section, sections.items, {}, SortSection.lessThan);
self.sections.shrinkRetainingCapacity(0); self.sections.shrinkRetainingCapacity(0);
for (sections.items) |out| { for (sections.items) |out| {
@ -2237,7 +2237,7 @@ pub const Zld = struct {
} }
} }
std.sort.sort(u64, addresses.items, {}, asc_u64); mem.sort(u64, addresses.items, {}, asc_u64);
var offsets = std.ArrayList(u32).init(gpa); var offsets = std.ArrayList(u32).init(gpa);
defer offsets.deinit(); defer offsets.deinit();

View file

@ -2143,7 +2143,7 @@ fn sortDataSegments(wasm: *Wasm) !void {
} }
}; };
std.sort.sort([]const u8, keys, {}, SortContext.sort); mem.sort([]const u8, keys, {}, SortContext.sort);
for (keys) |key| { for (keys) |key| {
const segment_index = wasm.data_segments.get(key).?; const segment_index = wasm.data_segments.get(key).?;
new_mapping.putAssumeCapacity(key, segment_index); new_mapping.putAssumeCapacity(key, segment_index);
@ -2187,7 +2187,7 @@ fn setupInitFunctions(wasm: *Wasm) !void {
} }
// sort the initfunctions based on their priority // sort the initfunctions based on their priority
std.sort.sort(InitFuncLoc, wasm.init_funcs.items, {}, InitFuncLoc.lessThan); mem.sort(InitFuncLoc, wasm.init_funcs.items, {}, InitFuncLoc.lessThan);
} }
/// Generates an atom containing the global error set' size. /// Generates an atom containing the global error set' size.
@ -3687,7 +3687,7 @@ fn writeToFile(
} }
}.sort; }.sort;
std.sort.sort(*Atom, sorted_atoms.items, wasm, atom_sort_fn); mem.sort(*Atom, sorted_atoms.items, wasm, atom_sort_fn);
for (sorted_atoms.items) |sorted_atom| { for (sorted_atoms.items) |sorted_atom| {
try leb.writeULEB128(binary_writer, sorted_atom.size); try leb.writeULEB128(binary_writer, sorted_atom.size);
@ -4050,8 +4050,8 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
data_segment_index += 1; data_segment_index += 1;
} }
std.sort.sort(Name, funcs.values(), {}, Name.lessThan); mem.sort(Name, funcs.values(), {}, Name.lessThan);
std.sort.sort(Name, globals.items, {}, Name.lessThan); mem.sort(Name, globals.items, {}, Name.lessThan);
const header_offset = try reserveCustomSectionHeader(binary_bytes); const header_offset = try reserveCustomSectionHeader(binary_bytes);
const writer = binary_bytes.writer(); const writer = binary_bytes.writer();

View file

@ -402,7 +402,7 @@ const BinaryElfOutput = struct {
} }
} }
std.sort.sort(*BinaryElfSegment, self.segments.items, {}, segmentSortCompare); mem.sort(*BinaryElfSegment, self.segments.items, {}, segmentSortCompare);
for (self.segments.items, 0..) |firstSegment, i| { for (self.segments.items, 0..) |firstSegment, i| {
if (firstSegment.firstSection) |firstSection| { if (firstSegment.firstSection) |firstSection| {
@ -427,7 +427,7 @@ const BinaryElfOutput = struct {
} }
} }
std.sort.sort(*BinaryElfSection, self.sections.items, {}, sectionSortCompare); mem.sort(*BinaryElfSection, self.sections.items, {}, sectionSortCompare);
return self; return self;
} }

View file

@ -607,7 +607,7 @@ fn sortTestFilenames(filenames: [][]const u8) void {
}; };
} }
}; };
std.sort.sort([]const u8, filenames, Context{}, Context.lessThan); std.mem.sort([]const u8, filenames, Context{}, Context.lessThan);
} }
/// Iterates a set of filenames extracting batches that are either incremental /// Iterates a set of filenames extracting batches that are either incremental

View file

@ -437,7 +437,7 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian)
const dynstr = elf_bytes[dynstr_offset..]; const dynstr = elf_bytes[dynstr_offset..];
// Sort the list by address, ascending. // Sort the list by address, ascending.
std.sort.sort(Sym, @alignCast(8, dyn_syms), {}, S.symbolAddrLessThan); mem.sort(Sym, @alignCast(8, dyn_syms), {}, S.symbolAddrLessThan);
for (dyn_syms) |sym| { for (dyn_syms) |sym| {
const this_section = s(sym.st_shndx); const this_section = s(sym.st_shndx);

View file

@ -23,7 +23,7 @@ pub fn main() !void {
while (try it.next()) |entry| { while (try it.next()) |entry| {
try names.append(try allocator.dupe(u8, entry.name)); try names.append(try allocator.dupe(u8, entry.name));
} }
std.sort.sort([]const u8, names.items, {}, (struct { std.mem.sort([]const u8, names.items, {}, (struct {
fn lessThan(_: void, a: []const u8, b: []const u8) bool { fn lessThan(_: void, a: []const u8, b: []const u8) bool {
return std.mem.lessThan(u8, a, b); return std.mem.lessThan(u8, a, b);
} }

View file

@ -460,7 +460,7 @@ pub fn main() !void {
try contents_list.append(contents); try contents_list.append(contents);
} }
} }
std.sort.sort(*Contents, contents_list.items, {}, Contents.hitCountLessThan); std.mem.sort(*Contents, contents_list.items, {}, Contents.hitCountLessThan);
const best_contents = contents_list.popOrNull().?; const best_contents = contents_list.popOrNull().?;
if (best_contents.hit_count > 1) { if (best_contents.hit_count > 1) {
// worth it to make it generic // worth it to make it generic

View file

@ -260,7 +260,7 @@ pub fn main() !void {
try contents_list.append(contents); try contents_list.append(contents);
} }
} }
std.sort.sort(*Contents, contents_list.items, {}, Contents.hitCountLessThan); std.mem.sort(*Contents, contents_list.items, {}, Contents.hitCountLessThan);
const best_contents = contents_list.popOrNull().?; const best_contents = contents_list.popOrNull().?;
if (best_contents.hit_count > 1) { if (best_contents.hit_count > 1) {
// worth it to make it generic // worth it to make it generic

View file

@ -646,7 +646,7 @@ pub fn main() anyerror!void {
} }
// Some options have multiple matches. As an example, "-Wl,foo" matches both // Some options have multiple matches. As an example, "-Wl,foo" matches both
// "W" and "Wl,". So we sort this list in order of descending priority. // "W" and "Wl,". So we sort this list in order of descending priority.
std.sort.sort(*json.ObjectMap, all_objects.items, {}, objectLessThan); std.mem.sort(*json.ObjectMap, all_objects.items, {}, objectLessThan);
var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer());
const stdout = buffered_stdout.writer(); const stdout = buffered_stdout.writer();

View file

@ -1187,8 +1187,8 @@ fn processOneTarget(job: Job) anyerror!void {
for (llvm_target.extra_cpus) |extra_cpu| { for (llvm_target.extra_cpus) |extra_cpu| {
try all_cpus.append(extra_cpu); try all_cpus.append(extra_cpu);
} }
std.sort.sort(Feature, all_features.items, {}, featureLessThan); mem.sort(Feature, all_features.items, {}, featureLessThan);
std.sort.sort(Cpu, all_cpus.items, {}, cpuLessThan); mem.sort(Cpu, all_cpus.items, {}, cpuLessThan);
const target_sub_path = try fs.path.join(arena, &.{ "lib", "std", "target" }); const target_sub_path = try fs.path.join(arena, &.{ "lib", "std", "target" });
var target_dir = try job.zig_src_dir.makeOpenPath(target_sub_path, .{}); var target_dir = try job.zig_src_dir.makeOpenPath(target_sub_path, .{});
@ -1283,7 +1283,7 @@ fn processOneTarget(job: Job) anyerror!void {
try dependencies.append(key.*); try dependencies.append(key.*);
} }
} }
std.sort.sort([]const u8, dependencies.items, {}, asciiLessThan); mem.sort([]const u8, dependencies.items, {}, asciiLessThan);
if (dependencies.items.len == 0) { if (dependencies.items.len == 0) {
try w.writeAll( try w.writeAll(
@ -1328,7 +1328,7 @@ fn processOneTarget(job: Job) anyerror!void {
try cpu_features.append(key.*); try cpu_features.append(key.*);
} }
} }
std.sort.sort([]const u8, cpu_features.items, {}, asciiLessThan); mem.sort([]const u8, cpu_features.items, {}, asciiLessThan);
if (cpu.llvm_name) |llvm_name| { if (cpu.llvm_name) |llvm_name| {
try w.print( try w.print(
\\ pub const {} = CpuModel{{ \\ pub const {} = CpuModel{{

View file

@ -303,7 +303,7 @@ fn gatherVersions(allocator: Allocator, registry: g.CoreRegistry) ![]const Versi
} }
} }
std.sort.sort(Version, versions.items, {}, Version.lessThan); std.mem.sort(Version, versions.items, {}, Version.lessThan);
return versions.items; return versions.items;
} }