1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;
6
7test "@shuffle int" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13
14 const S = struct {
15 fn doTheTest() !void {
16 var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
17 _ = &v;
18 var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
19 _ = &x;
20 const mask = [4]i32{ 0, ~@as(i32, 2), 3, ~@as(i32, 3) };
21 var res = @shuffle(i32, v, x, mask);
22 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 40, 4 }));
23
24 // Implicit cast from array (of mask)
25 res = @shuffle(i32, v, x, [4]i32{ 0, ~@as(i32, 2), 3, ~@as(i32, 3) });
26 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 40, 4 }));
27
28 // Undefined
29 const mask2 = [4]i32{ 3, 1, 2, 0 };
30 res = @shuffle(i32, v, undefined, mask2);
31 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 40, -2, 30, 2147483647 }));
32
33 // Upcasting of b
34 var v2: @Vector(2, i32) = [2]i32{ 2147483647, undefined };
35 _ = &v2;
36 const mask3 = [4]i32{ ~@as(i32, 0), 2, ~@as(i32, 0), 3 };
37 res = @shuffle(i32, x, v2, mask3);
38 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 2147483647, 4 }));
39
40 // Upcasting of a
41 var v3: @Vector(2, i32) = [2]i32{ 2147483647, -2 };
42 _ = &v3;
43 const mask4 = [4]i32{ 0, ~@as(i32, 2), 1, ~@as(i32, 3) };
44 res = @shuffle(i32, v3, x, mask4);
45 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, -2, 4 }));
46 }
47 };
48 try S.doTheTest();
49 try comptime S.doTheTest();
50}
51
52test "@shuffle int strange sizes" {
53 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
57 try comptime testShuffle(2, 2, 2);
58 try testShuffle(2, 2, 2);
59 try comptime testShuffle(4, 4, 4);
60 try testShuffle(4, 4, 4);
61 try comptime testShuffle(7, 4, 4);
62 try testShuffle(7, 4, 4);
63 try comptime testShuffle(8, 6, 4);
64 try testShuffle(8, 6, 4);
65 try comptime testShuffle(2, 7, 5);
66 try testShuffle(2, 7, 5);
67 try comptime testShuffle(13, 16, 12);
68 try testShuffle(13, 16, 12);
69 try comptime testShuffle(19, 3, 17);
70 try testShuffle(19, 3, 17);
71 try comptime testShuffle(1, 10, 1);
72 try testShuffle(1, 10, 1);
73}
74
75fn testShuffle(
76 comptime x_len: comptime_int,
77 comptime a_len: comptime_int,
78 comptime b_len: comptime_int,
79) !void {
80 const T = i32;
81 const XT = @Vector(x_len, T);
82 const AT = @Vector(a_len, T);
83 const BT = @Vector(b_len, T);
84
85 const a_elems = comptime blk: {
86 var elems: [a_len]T = undefined;
87 for (&elems, 0..) |*elem, i| elem.* = @intCast(100 + i);
88 break :blk elems;
89 };
90 var a: AT = a_elems;
91 _ = &a;
92
93 const b_elems = comptime blk: {
94 var elems: [b_len]T = undefined;
95 for (&elems, 0..) |*elem, i| elem.* = @intCast(1000 + i);
96 break :blk elems;
97 };
98 var b: BT = b_elems;
99 _ = &b;
100
101 const mask_seed: []const i32 = &.{ -14, -31, 23, 1, 21, 13, 17, -21, -10, -27, -16, -5, 15, 14, -2, 26, 2, -31, -24, -16 };
102
103 const mask = comptime blk: {
104 var elems: [x_len]i32 = undefined;
105 for (&elems, 0..) |*elem, i| {
106 const mask_val = mask_seed[i];
107 if (mask_val >= 0) {
108 elem.* = @mod(mask_val, a_len);
109 } else {
110 elem.* = @mod(mask_val, -b_len);
111 }
112 }
113
114 break :blk elems;
115 };
116
117 const x: XT = @shuffle(T, a, b, mask);
118
119 const x_elems: [x_len]T = x;
120 for (mask, x_elems) |m, x_elem| {
121 if (m >= 0) {
122 // Element from A
123 try expectEqual(x_elem, a_elems[@intCast(m)]);
124 } else {
125 // Element from B
126 try expectEqual(x_elem, b_elems[@intCast(~m)]);
127 }
128 }
129}
130
131test "@shuffle bool 1" {
132 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
135 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
137 const S = struct {
138 fn doTheTest() !void {
139 var x: @Vector(4, bool) = [4]bool{ false, true, false, true };
140 _ = &x;
141 var v: @Vector(2, bool) = [2]bool{ true, false };
142 _ = &v;
143 const mask = [4]i32{ 0, ~@as(i32, 1), 1, 2 };
144 const res = @shuffle(bool, x, v, mask);
145 try expect(mem.eql(bool, &@as([4]bool, res), &[4]bool{ false, false, true, false }));
146 }
147 };
148 try S.doTheTest();
149 try comptime S.doTheTest();
150}
151
152test "@shuffle bool 2" {
153 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
157 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
158
159 const S = struct {
160 fn doTheTest() !void {
161 var x: @Vector(3, bool) = [3]bool{ false, true, false };
162 _ = &x;
163 var v: @Vector(2, bool) = [2]bool{ true, false };
164 _ = &v;
165 const mask = [4]i32{ 0, ~@as(i32, 1), 1, 2 };
166 const res = @shuffle(bool, x, v, mask);
167 try expect(mem.eql(bool, &@as([4]bool, res), &[4]bool{ false, false, true, false }));
168 }
169 };
170 try S.doTheTest();
171 try comptime S.doTheTest();
172}
173
174test "@shuffle u0" {
175 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
176 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
177 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
178 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
179 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
180
181 const S = struct {
182 fn doTheTest() !void {
183 var v: @Vector(4, u0) = @splat(0);
184 const mask = @Vector(4, i32){ undefined, 0, -1, 3 };
185 _ = .{ &v, &mask };
186 const res = @shuffle(u0, v, v, mask);
187 comptime if (!std.mem.eql(u0, &@as([4]u0, res), &[4]u0{ 0, 0, 0, 0 })) unreachable;
188 }
189 };
190 try S.doTheTest();
191 try comptime S.doTheTest();
192}