| ... | @@ -3448,22 +3448,77 @@ pub fn swap(comptime T: type, a: *T, b: *T) void { | ... | @@ -3448,22 +3448,77 @@ pub fn swap(comptime T: type, a: *T, b: *T) void { |
| 3448 | b.* = tmp; | 3448 | b.* = tmp; |
| 3449 | } | 3449 | } |
| 3450 | | 3450 | |
| | 3451 | inline fn reverseVector(comptime N: usize, comptime T: type, a: []T) [N]T { |
| | 3452 | var res: [N]T = undefined; |
| | 3453 | inline for (0..N) |i| { |
| | 3454 | res[i] = a[N - i - 1]; |
| | 3455 | } |
| | 3456 | return res; |
| | 3457 | } |
| | 3458 | |
| 3451 | /// In-place order reversal of a slice | 3459 | /// In-place order reversal of a slice |
| 3452 | pub fn reverse(comptime T: type, items: []T) void { | 3460 | pub fn reverse(comptime T: type, items: []T) void { |
| 3453 | var i: usize = 0; | 3461 | var i: usize = 0; |
| 3454 | const end = items.len / 2; | 3462 | const end = items.len / 2; |
| | 3463 | if (backend_supports_vectors and |
| | 3464 | !@inComptime() and |
| | 3465 | @bitSizeOf(T) > 0 and |
| | 3466 | std.math.isPowerOfTwo(@bitSizeOf(T))) |
| | 3467 | { |
| | 3468 | if (std.simd.suggestVectorLength(T)) |simd_size| { |
| | 3469 | if (simd_size <= end) { |
| | 3470 | const simd_end = end - (simd_size - 1); |
| | 3471 | while (i < simd_end) : (i += simd_size) { |
| | 3472 | const left_slice = items[i .. i + simd_size]; |
| | 3473 | const right_slice = items[items.len - i - simd_size .. items.len - i]; |
| | 3474 | |
| | 3475 | const left_shuffled: [simd_size]T = reverseVector(simd_size, T, left_slice); |
| | 3476 | const right_shuffled: [simd_size]T = reverseVector(simd_size, T, right_slice); |
| | 3477 | |
| | 3478 | @memcpy(right_slice, &left_shuffled); |
| | 3479 | @memcpy(left_slice, &right_shuffled); |
| | 3480 | } |
| | 3481 | } |
| | 3482 | } |
| | 3483 | } |
| | 3484 | |
| 3455 | while (i < end) : (i += 1) { | 3485 | while (i < end) : (i += 1) { |
| 3456 | swap(T, &items[i], &items[items.len - i - 1]); | 3486 | swap(T, &items[i], &items[items.len - i - 1]); |
| 3457 | } | 3487 | } |
| 3458 | } | 3488 | } |
| 3459 | | 3489 | |
| 3460 | test reverse { | 3490 | test reverse { |
| 3461 | var arr = [_]i32{ 5, 3, 1, 2, 4 }; | 3491 | { |
| 3462 | reverse(i32, arr[0..]); | 3492 | var arr = [_]i32{ 5, 3, 1, 2, 4 }; |
| 3463 | | 3493 | reverse(i32, arr[0..]); |
| 3464 | try testing.expect(eql(i32, &arr, &[_]i32{ 4, 2, 1, 3, 5 })); | 3494 | try testing.expectEqualSlices(i32, &arr, &.{ 4, 2, 1, 3, 5 }); |
| | 3495 | } |
| | 3496 | { |
| | 3497 | var arr = [_]u0{}; |
| | 3498 | reverse(u0, arr[0..]); |
| | 3499 | try testing.expectEqualSlices(u0, &arr, &.{}); |
| | 3500 | } |
| | 3501 | { |
| | 3502 | var arr = [_]i64{ 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18 }; |
| | 3503 | reverse(i64, arr[0..]); |
| | 3504 | try testing.expectEqualSlices(i64, &arr, &.{ 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }); |
| | 3505 | } |
| | 3506 | { |
| | 3507 | var arr = [_][]const u8{ "a", "b", "c", "d" }; |
| | 3508 | reverse([]const u8, arr[0..]); |
| | 3509 | try testing.expectEqualSlices([]const u8, &arr, &.{ "d", "c", "b", "a" }); |
| | 3510 | } |
| | 3511 | { |
| | 3512 | const MyType = union(enum) { |
| | 3513 | a: [3]u8, |
| | 3514 | b: u24, |
| | 3515 | c, |
| | 3516 | }; |
| | 3517 | var arr = [_]MyType{ .{ .a = .{ 0, 0, 0 } }, .{ .b = 0 }, .c }; |
| | 3518 | reverse(MyType, arr[0..]); |
| | 3519 | try testing.expectEqualSlices(MyType, &arr, &([_]MyType{ .c, .{ .b = 0 }, .{ .a = .{ 0, 0, 0 } } })); |
| | 3520 | } |
| 3465 | } | 3521 | } |
| 3466 | | | |
| 3467 | fn ReverseIterator(comptime T: type) type { | 3522 | fn ReverseIterator(comptime T: type) type { |
| 3468 | const Pointer = blk: { | 3523 | const Pointer = blk: { |
| 3469 | switch (@typeInfo(T)) { | 3524 | switch (@typeInfo(T)) { |