mirror of
https://github.com/ziglang/zig.git
synced 2026-01-03 03:53:20 +00:00
std.mem.reverse: Improve performance (#20455)
This commit is contained in:
parent
7591df5172
commit
fae742a680
@ -3448,22 +3448,77 @@ pub fn swap(comptime T: type, a: *T, b: *T) void {
|
|||||||
b.* = tmp;
|
b.* = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fn reverseVector(comptime N: usize, comptime T: type, a: []T) [N]T {
|
||||||
|
var res: [N]T = undefined;
|
||||||
|
inline for (0..N) |i| {
|
||||||
|
res[i] = a[N - i - 1];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/// In-place order reversal of a slice
|
/// In-place order reversal of a slice
|
||||||
pub fn reverse(comptime T: type, items: []T) void {
|
pub fn reverse(comptime T: type, items: []T) void {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
const end = items.len / 2;
|
const end = items.len / 2;
|
||||||
|
if (backend_supports_vectors and
|
||||||
|
!@inComptime() and
|
||||||
|
@bitSizeOf(T) > 0 and
|
||||||
|
std.math.isPowerOfTwo(@bitSizeOf(T)))
|
||||||
|
{
|
||||||
|
if (std.simd.suggestVectorLength(T)) |simd_size| {
|
||||||
|
if (simd_size <= end) {
|
||||||
|
const simd_end = end - (simd_size - 1);
|
||||||
|
while (i < simd_end) : (i += simd_size) {
|
||||||
|
const left_slice = items[i .. i + simd_size];
|
||||||
|
const right_slice = items[items.len - i - simd_size .. items.len - i];
|
||||||
|
|
||||||
|
const left_shuffled: [simd_size]T = reverseVector(simd_size, T, left_slice);
|
||||||
|
const right_shuffled: [simd_size]T = reverseVector(simd_size, T, right_slice);
|
||||||
|
|
||||||
|
@memcpy(right_slice, &left_shuffled);
|
||||||
|
@memcpy(left_slice, &right_shuffled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (i < end) : (i += 1) {
|
while (i < end) : (i += 1) {
|
||||||
swap(T, &items[i], &items[items.len - i - 1]);
|
swap(T, &items[i], &items[items.len - i - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test reverse {
|
test reverse {
|
||||||
|
{
|
||||||
var arr = [_]i32{ 5, 3, 1, 2, 4 };
|
var arr = [_]i32{ 5, 3, 1, 2, 4 };
|
||||||
reverse(i32, arr[0..]);
|
reverse(i32, arr[0..]);
|
||||||
|
try testing.expectEqualSlices(i32, &arr, &.{ 4, 2, 1, 3, 5 });
|
||||||
try testing.expect(eql(i32, &arr, &[_]i32{ 4, 2, 1, 3, 5 }));
|
}
|
||||||
|
{
|
||||||
|
var arr = [_]u0{};
|
||||||
|
reverse(u0, arr[0..]);
|
||||||
|
try testing.expectEqualSlices(u0, &arr, &.{});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var arr = [_]i64{ 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18 };
|
||||||
|
reverse(i64, arr[0..]);
|
||||||
|
try testing.expectEqualSlices(i64, &arr, &.{ 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 });
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var arr = [_][]const u8{ "a", "b", "c", "d" };
|
||||||
|
reverse([]const u8, arr[0..]);
|
||||||
|
try testing.expectEqualSlices([]const u8, &arr, &.{ "d", "c", "b", "a" });
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const MyType = union(enum) {
|
||||||
|
a: [3]u8,
|
||||||
|
b: u24,
|
||||||
|
c,
|
||||||
|
};
|
||||||
|
var arr = [_]MyType{ .{ .a = .{ 0, 0, 0 } }, .{ .b = 0 }, .c };
|
||||||
|
reverse(MyType, arr[0..]);
|
||||||
|
try testing.expectEqualSlices(MyType, &arr, &([_]MyType{ .c, .{ .b = 0 }, .{ .a = .{ 0, 0, 0 } } }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ReverseIterator(comptime T: type) type {
|
fn ReverseIterator(comptime T: type) type {
|
||||||
const Pointer = blk: {
|
const Pointer = blk: {
|
||||||
switch (@typeInfo(T)) {
|
switch (@typeInfo(T)) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user