mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
feat(libzigc): add qsort
* also remove musl implementation
This commit is contained in:
committed by
Andrew Kelley
parent
6412aebc90
commit
fa625e878f
@@ -8,6 +8,9 @@ comptime {
|
||||
@export(&abs, .{ .name = "abs", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&labs, .{ .name = "labs", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&llabs, .{ .name = "llabs", .linkage = common.linkage, .visibility = common.visibility });
|
||||
|
||||
@export(&qsort_r, .{ .name = "qsort_r", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&qsort, .{ .name = "qsort", .linkage = common.linkage, .visibility = common.visibility });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +26,47 @@ fn llabs(a: c_longlong) callconv(.c) c_longlong {
|
||||
return @intCast(@abs(a));
|
||||
}
|
||||
|
||||
// NOTE: Despite its name, `qsort` doesn't have to use quicksort or make any complexity or stability guarantee.
|
||||
fn qsort_r(base: *anyopaque, n: usize, size: usize, compare: *const fn (a: *const anyopaque, b: *const anyopaque, arg: ?*anyopaque) callconv(.c) c_int, arg: ?*anyopaque) callconv(.c) void {
|
||||
const Context = struct {
|
||||
base: [*]u8,
|
||||
size: usize,
|
||||
compare: *const fn (a: *const anyopaque, b: *const anyopaque, arg: ?*anyopaque) callconv(.c) c_int,
|
||||
arg: ?*anyopaque,
|
||||
|
||||
pub fn lessThan(ctx: @This(), a: usize, b: usize) bool {
|
||||
return ctx.compare(&ctx.base[a * ctx.size], &ctx.base[b * ctx.size], ctx.arg) < 0;
|
||||
}
|
||||
|
||||
pub fn swap(ctx: @This(), a: usize, b: usize) void {
|
||||
const a_bytes: []u8 = ctx.base[a * ctx.size ..][0..ctx.size];
|
||||
const b_bytes: []u8 = ctx.base[b * ctx.size ..][0..ctx.size];
|
||||
|
||||
for (a_bytes, b_bytes) |*ab, *bb| {
|
||||
const tmp = ab.*;
|
||||
ab.* = bb.*;
|
||||
bb.* = tmp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std.mem.sortUnstableContext(0, n, Context{
|
||||
.base = @ptrCast(base),
|
||||
.size = size,
|
||||
.compare = compare,
|
||||
.arg = arg,
|
||||
});
|
||||
}
|
||||
|
||||
fn qsort(base: *anyopaque, n: usize, size: usize, compare: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int) callconv(.c) void {
|
||||
return qsort_r(base, n, size, (struct {
|
||||
fn wrap(a: *const anyopaque, b: *const anyopaque, arg: ?*anyopaque) callconv(.c) c_int {
|
||||
const cmp: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int = @ptrCast(@alignCast(arg.?));
|
||||
return cmp(a, b);
|
||||
}
|
||||
}).wrap, @constCast(compare));
|
||||
}
|
||||
|
||||
test abs {
|
||||
const val: c_int = -10;
|
||||
try std.testing.expectEqual(10, abs(val));
|
||||
|
||||
Reference in New Issue
Block a user