diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 3b45bdbfef..20d68b8937 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -3448,22 +3448,77 @@ pub fn swap(comptime T: type, a: *T, b: *T) void { 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 pub fn reverse(comptime T: type, items: []T) void { var i: usize = 0; 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) { swap(T, &items[i], &items[items.len - i - 1]); } } test reverse { - var arr = [_]i32{ 5, 3, 1, 2, 4 }; - reverse(i32, arr[0..]); - - try testing.expect(eql(i32, &arr, &[_]i32{ 4, 2, 1, 3, 5 })); + { + var arr = [_]i32{ 5, 3, 1, 2, 4 }; + reverse(i32, arr[0..]); + try testing.expectEqualSlices(i32, &arr, &.{ 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 { const Pointer = blk: { switch (@typeInfo(T)) {