master
   1const std = @import("std");
   2const builtin = @import("builtin");
   3const mem = std.mem;
   4const math = std.math;
   5const assert = std.debug.assert;
   6const expect = std.testing.expect;
   7const expectEqual = std.testing.expectEqual;
   8
   9test "implicit cast vector to array - bool" {
  10    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
  11    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
  12
  13    const S = struct {
  14        fn doTheTest() !void {
  15            {
  16                var v: @Vector(4, bool) = undefined;
  17                v = .{ true, false, true, false };
  18                const a: [4]bool = v;
  19                try expect(mem.eql(bool, &a, &.{ true, false, true, false }));
  20            }
  21            {
  22                var v: @Vector(25, bool) = undefined;
  23                v = .{ false, false, false, false, true, true, false, false, false, true, false, true, false, false, true, false, false, true, false, false, true, true, true, false, false };
  24                const a: [25]bool = v;
  25                try expect(mem.eql(bool, &a, &.{ false, false, false, false, true, true, false, false, false, true, false, true, false, false, true, false, false, true, false, false, true, true, true, false, false }));
  26            }
  27        }
  28    };
  29    try S.doTheTest();
  30    try comptime S.doTheTest();
  31}
  32
  33test "implicit cast array to vector - bool" {
  34    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
  35
  36    const S = struct {
  37        fn doTheTest() !void {
  38            {
  39                var a: [4]bool = undefined;
  40                a = .{ true, false, false, true };
  41                const v: @Vector(4, bool) = a;
  42                try expect(mem.eql(bool, &@as([4]bool, v), &.{ true, false, false, true }));
  43            }
  44            {
  45                var a: [25]bool = undefined;
  46                a = .{ true, false, false, true, false, false, false, false, false, true, true, true, true, false, false, false, false, true, false, false, false, true, true, true, false };
  47                const v: @Vector(25, bool) = a;
  48                try expect(mem.eql(bool, &@as([25]bool, v), &.{ true, false, false, true, false, false, false, false, false, true, true, true, true, false, false, false, false, true, false, false, false, true, true, true, false }));
  49            }
  50        }
  51    };
  52    try S.doTheTest();
  53    try comptime S.doTheTest();
  54}
  55
  56test "vector wrap operators" {
  57    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
  58    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
  59    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
  60    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
  61    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
  62    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
  63
  64    const S = struct {
  65        fn doTheTest() !void {
  66            var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
  67            var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
  68            try expect(mem.eql(i32, &@as([4]i32, v +% x), &[4]i32{ -2147483648, 2147483645, 33, 44 }));
  69            try expect(mem.eql(i32, &@as([4]i32, v -% x), &[4]i32{ 2147483646, 2147483647, 27, 36 }));
  70            try expect(mem.eql(i32, &@as([4]i32, v *% x), &[4]i32{ 2147483647, 2, 90, 160 }));
  71            var z: @Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 };
  72            try expect(mem.eql(i32, &@as([4]i32, -%z), &[4]i32{ -1, -2, -3, -2147483648 }));
  73            _ = .{ &v, &x, &z };
  74        }
  75    };
  76    try S.doTheTest();
  77    try comptime S.doTheTest();
  78}
  79
  80test "vector bin compares with mem.eql" {
  81    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
  82    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
  83    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
  84    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
  85    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
  86    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
  87
  88    const S = struct {
  89        fn doTheTest() !void {
  90            var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
  91            var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 };
  92            _ = .{ &v, &x };
  93            try expect(mem.eql(bool, &@as([4]bool, v == x), &[4]bool{ false, false, true, false }));
  94            try expect(mem.eql(bool, &@as([4]bool, v != x), &[4]bool{ true, true, false, true }));
  95            try expect(mem.eql(bool, &@as([4]bool, v < x), &[4]bool{ false, true, false, false }));
  96            try expect(mem.eql(bool, &@as([4]bool, v > x), &[4]bool{ true, false, false, true }));
  97            try expect(mem.eql(bool, &@as([4]bool, v <= x), &[4]bool{ false, true, true, false }));
  98            try expect(mem.eql(bool, &@as([4]bool, v >= x), &[4]bool{ true, false, true, true }));
  99        }
 100    };
 101    try S.doTheTest();
 102    try comptime S.doTheTest();
 103}
 104
 105test "vector int operators" {
 106    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 107    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 108    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 109    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 110    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 111    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 112
 113    const S = struct {
 114        fn doTheTest() !void {
 115            var v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
 116            var x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };
 117            _ = .{ &v, &x };
 118            try expect(mem.eql(i32, &@as([4]i32, v + x), &[4]i32{ 11, 22, 33, 44 }));
 119            try expect(mem.eql(i32, &@as([4]i32, v - x), &[4]i32{ 9, 18, 27, 36 }));
 120            try expect(mem.eql(i32, &@as([4]i32, v * x), &[4]i32{ 10, 40, 90, 160 }));
 121            try expect(mem.eql(i32, &@as([4]i32, -v), &[4]i32{ -10, -20, -30, -40 }));
 122        }
 123    };
 124    try S.doTheTest();
 125    try comptime S.doTheTest();
 126}
 127
 128test "vector float operators" {
 129    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 130    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 131    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 132    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 133    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 134    if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
 135
 136    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
 137        // Triggers an assertion with LLVM 18:
 138        // https://github.com/ziglang/zig/issues/20680
 139        return error.SkipZigTest;
 140    }
 141
 142    const S = struct {
 143        fn doTheTest(T: type) !void {
 144            var v: @Vector(4, T) = .{ 10, 20, 30, 40 };
 145            var x: @Vector(4, T) = .{ 1, 2, 3, 4 };
 146            _ = .{ &v, &x };
 147            try expectEqual(v + x, .{ 11, 22, 33, 44 });
 148            try expectEqual(v - x, .{ 9, 18, 27, 36 });
 149            try expectEqual(v * x, .{ 10, 40, 90, 160 });
 150            if (builtin.zig_backend != .stage2_riscv64) try expectEqual(-x, .{ -1, -2, -3, -4 });
 151        }
 152    };
 153
 154    try S.doTheTest(f32);
 155    try comptime S.doTheTest(f32);
 156
 157    try S.doTheTest(f64);
 158    try comptime S.doTheTest(f64);
 159
 160    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 161
 162    try S.doTheTest(f16);
 163    try comptime S.doTheTest(f16);
 164
 165    try S.doTheTest(f80);
 166    try comptime S.doTheTest(f80);
 167
 168    try S.doTheTest(f128);
 169    try comptime S.doTheTest(f128);
 170}
 171
 172test "vector bit operators" {
 173    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 174    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 175    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 176    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 177    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 178    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 179
 180    const S = struct {
 181        fn doTheTest() !void {
 182            {
 183                var v: @Vector(4, bool) = [4]bool{ false, false, true, true };
 184                var x: @Vector(4, bool) = [4]bool{ true, false, true, false };
 185                _ = .{ &v, &x };
 186                try expect(mem.eql(bool, &@as([4]bool, v ^ x), &[4]bool{ true, false, false, true }));
 187                try expect(mem.eql(bool, &@as([4]bool, v | x), &[4]bool{ true, false, true, true }));
 188                try expect(mem.eql(bool, &@as([4]bool, v & x), &[4]bool{ false, false, true, false }));
 189            }
 190            {
 191                var v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
 192                var x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
 193                _ = .{ &v, &x };
 194                try expect(mem.eql(u8, &@as([4]u8, v ^ x), &[4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 }));
 195                try expect(mem.eql(u8, &@as([4]u8, v | x), &[4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 }));
 196                try expect(mem.eql(u8, &@as([4]u8, v & x), &[4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 }));
 197            }
 198        }
 199    };
 200    try S.doTheTest();
 201    try comptime S.doTheTest();
 202}
 203
 204test "implicit cast vector to array" {
 205    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 206    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 207    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 208    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 209    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 210
 211    const S = struct {
 212        fn doTheTest() !void {
 213            var a: @Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
 214            _ = &a;
 215            var result_array: [4]i32 = a;
 216            result_array = a;
 217            try expect(mem.eql(i32, &result_array, &[4]i32{ 1, 2, 3, 4 }));
 218        }
 219    };
 220    try S.doTheTest();
 221    try comptime S.doTheTest();
 222}
 223
 224test "array to vector" {
 225    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 226    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 227    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 228    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 229    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
 230
 231    const S = struct {
 232        fn doTheTest() !void {
 233            var foo: f32 = 3.14;
 234            _ = &foo;
 235            const arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
 236            const vec: @Vector(4, f32) = arr;
 237            try expect(mem.eql(f32, &@as([4]f32, vec), &arr));
 238        }
 239    };
 240    try S.doTheTest();
 241    try comptime S.doTheTest();
 242}
 243
 244test "array vector coercion - odd sizes" {
 245    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 246    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 247    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 248    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
 249    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 250
 251    const S = struct {
 252        fn doTheTest() !void {
 253            var foo1: i48 = 124578;
 254            _ = &foo1;
 255            const vec1: @Vector(2, i48) = [2]i48{ foo1, 1 };
 256            const arr1: [2]i48 = vec1;
 257            try expect(vec1[0] == foo1 and vec1[1] == 1);
 258            try expect(arr1[0] == foo1 and arr1[1] == 1);
 259
 260            var foo2: u4 = 5;
 261            _ = &foo2;
 262            const vec2: @Vector(2, u4) = [2]u4{ foo2, 1 };
 263            const arr2: [2]u4 = vec2;
 264            try expect(vec2[0] == foo2 and vec2[1] == 1);
 265            try expect(arr2[0] == foo2 and arr2[1] == 1);
 266
 267            var foo3: u13 = 13;
 268            _ = &foo3;
 269            const vec3: @Vector(3, u13) = [3]u13{ foo3, 0, 1 };
 270            const arr3: [3]u13 = vec3;
 271            try expect(vec3[0] == foo3 and vec3[1] == 0 and vec3[2] == 1);
 272            try expect(arr3[0] == foo3 and arr3[1] == 0 and arr3[2] == 1);
 273
 274            const arr4 = [4:0]u24{ foo3, foo2, 0, 1 };
 275            const vec4: @Vector(4, u24) = arr4;
 276            try expect(vec4[0] == foo3 and vec4[1] == foo2 and vec4[2] == 0 and vec4[3] == 1);
 277        }
 278    };
 279    try S.doTheTest();
 280    try comptime S.doTheTest();
 281}
 282
 283test "array to vector with element type coercion" {
 284    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 285    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 286    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 287    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 288    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 289    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 290
 291    const S = struct {
 292        fn doTheTest() !void {
 293            var foo: f16 = 3.14;
 294            _ = &foo;
 295            const arr32 = [4]f32{ foo, 1.5, 0.0, 0.0 };
 296            const vec: @Vector(4, f32) = [4]f16{ foo, 1.5, 0.0, 0.0 };
 297            try std.testing.expect(std.mem.eql(f32, &@as([4]f32, vec), &arr32));
 298        }
 299    };
 300    try S.doTheTest();
 301    try comptime S.doTheTest();
 302}
 303
 304test "peer type resolution with coercible element types" {
 305    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 306    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 307    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 308
 309    const S = struct {
 310        fn doTheTest() !void {
 311            var b: @Vector(2, u8) = .{ 1, 2 };
 312            var a: @Vector(2, u16) = .{ 2, 1 };
 313            var t: bool = true;
 314            _ = .{ &a, &b, &t };
 315            const c = if (t) a else b;
 316            try std.testing.expect(@TypeOf(c) == @Vector(2, u16));
 317        }
 318    };
 319    try comptime S.doTheTest();
 320}
 321
 322test "tuple to vector" {
 323    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 324    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 325    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 326    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 327    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 328
 329    const S = struct {
 330        fn doTheTest() !void {
 331            const Vec3 = @Vector(3, i32);
 332            var v: Vec3 = .{ 1, 0, 0 };
 333            for ([_]Vec3{ .{ 0, 1, 0 }, .{ 0, 0, 1 } }) |it| {
 334                v += it;
 335            }
 336
 337            try std.testing.expectEqual(v, Vec3{ 1, 1, 1 });
 338            try std.testing.expectEqual(v, .{ 1, 1, 1 });
 339        }
 340    };
 341    try S.doTheTest();
 342    try comptime S.doTheTest();
 343}
 344
 345test "vector casts of sizes not divisible by 8" {
 346    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 347    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 348    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 349    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 350    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 351    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 352
 353    const S = struct {
 354        fn doTheTest() !void {
 355            {
 356                var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0 };
 357                _ = &v;
 358                const x: [4]u3 = v;
 359                try expect(mem.eql(u3, &x, &@as([4]u3, v)));
 360            }
 361            {
 362                var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0 };
 363                _ = &v;
 364                const x: [4]u2 = v;
 365                try expect(mem.eql(u2, &x, &@as([4]u2, v)));
 366            }
 367            {
 368                var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0 };
 369                _ = &v;
 370                const x: [4]u1 = v;
 371                try expect(mem.eql(u1, &x, &@as([4]u1, v)));
 372            }
 373            {
 374                var v: @Vector(4, bool) = [4]bool{ false, false, true, false };
 375                _ = &v;
 376                const x: [4]bool = v;
 377                try expect(mem.eql(bool, &x, &@as([4]bool, v)));
 378            }
 379        }
 380    };
 381    try S.doTheTest();
 382    try comptime S.doTheTest();
 383}
 384
 385test "vector @splat" {
 386    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 387    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 388    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 389    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 390    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 391
 392    const S = struct {
 393        fn testForT(comptime N: comptime_int, v: anytype) !void {
 394            const T = @TypeOf(v);
 395            var vec: @Vector(N, T) = @splat(v);
 396            _ = &vec;
 397            const as_array = @as([N]T, vec);
 398            for (as_array) |elem| try expect(v == elem);
 399        }
 400        fn doTheTest() !void {
 401            // Splats with multiple-of-8 bit types that fill a 128bit vector.
 402            try testForT(16, @as(u8, 0xEE));
 403            try testForT(8, @as(u16, 0xBEEF));
 404            try testForT(4, @as(u32, 0xDEADBEEF));
 405            try testForT(2, @as(u64, 0xCAFEF00DDEADBEEF));
 406
 407            try testForT(8, @as(f16, 3.1415));
 408            try testForT(4, @as(f32, 3.1415));
 409            try testForT(2, @as(f64, 3.1415));
 410
 411            // Same but fill more than 128 bits.
 412            try testForT(16 * 2, @as(u8, 0xEE));
 413            try testForT(8 * 2, @as(u16, 0xBEEF));
 414            try testForT(4 * 2, @as(u32, 0xDEADBEEF));
 415            try testForT(2 * 2, @as(u64, 0xCAFEF00DDEADBEEF));
 416
 417            try testForT(8 * 2, @as(f16, 3.1415));
 418            try testForT(4 * 2, @as(f32, 3.1415));
 419            try testForT(2 * 2, @as(f64, 3.1415));
 420        }
 421    };
 422    try S.doTheTest();
 423    try comptime S.doTheTest();
 424}
 425
 426test "load vector elements via comptime index" {
 427    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 428    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 429
 430    const S = struct {
 431        fn doTheTest() !void {
 432            var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
 433            try expect(v[0] == 1);
 434            try expect(v[1] == 2);
 435            try expect(loadv(&v[2]) == 3);
 436        }
 437        fn loadv(ptr: anytype) i32 {
 438            return ptr.*;
 439        }
 440    };
 441
 442    try S.doTheTest();
 443    try comptime S.doTheTest();
 444}
 445
 446test "store vector elements via comptime index" {
 447    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 448    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 449
 450    const S = struct {
 451        fn doTheTest() !void {
 452            var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
 453
 454            v[2] = 42;
 455            try expect(v[1] == 5);
 456            v[3] = -364;
 457            try expect(v[2] == 42);
 458            try expect(-364 == v[3]);
 459
 460            storev(&v[0], 100);
 461            try expect(v[0] == 100);
 462        }
 463        fn storev(ptr: anytype, x: i32) void {
 464            ptr.* = x;
 465        }
 466    };
 467
 468    try S.doTheTest();
 469    try comptime S.doTheTest();
 470}
 471
 472test "initialize vector which is a struct field" {
 473    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 474    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 475
 476    const Vec4Obj = struct {
 477        data: @Vector(4, f32),
 478    };
 479
 480    const S = struct {
 481        fn doTheTest() !void {
 482            var foo = Vec4Obj{
 483                .data = [_]f32{ 1, 2, 3, 4 },
 484            };
 485            _ = &foo;
 486        }
 487    };
 488    try S.doTheTest();
 489    try comptime S.doTheTest();
 490}
 491
 492test "vector comparison operators" {
 493    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 494    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 495    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 496    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 497    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 498    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 499
 500    const S = struct {
 501        fn doTheTest() !void {
 502            {
 503                const V = @Vector(4, bool);
 504                var v1: V = [_]bool{ true, false, true, false };
 505                var v2: V = [_]bool{ false, true, false, true };
 506                _ = .{ &v1, &v2 };
 507                try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 == v1)));
 508                try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 == v2)));
 509                try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 != v2)));
 510                try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v2 != v2)));
 511            }
 512            {
 513                const V = @Vector(4, bool);
 514                var v1: @Vector(4, u32) = @splat(0xc0ffeeee);
 515                var v2: @Vector(4, c_uint) = v1;
 516                var v3: @Vector(4, u32) = @splat(0xdeadbeef);
 517                _ = .{ &v1, &v2, &v3 };
 518                try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 == v2)));
 519                try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 == v3)));
 520                try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 != v3)));
 521                try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 != v2)));
 522            }
 523            {
 524                // Comptime-known LHS/RHS
 525                var v1: @Vector(4, u32) = [_]u32{ 2, 1, 2, 1 };
 526                _ = &v1;
 527                const v2: @Vector(4, u32) = @splat(2);
 528                const v3: @Vector(4, bool) = [_]bool{ true, false, true, false };
 529                try expect(mem.eql(bool, &@as([4]bool, v3), &@as([4]bool, v1 == v2)));
 530                try expect(mem.eql(bool, &@as([4]bool, v3), &@as([4]bool, v2 == v1)));
 531            }
 532        }
 533    };
 534    try S.doTheTest();
 535    try comptime S.doTheTest();
 536}
 537
 538test "vector division operators" {
 539    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 540    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 541    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 542    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 543    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 544    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 545    if (comptime builtin.cpu.has(.riscv, .v) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/24301
 546
 547    const S = struct {
 548        fn doTheTestDiv(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void {
 549            const is_signed_int = switch (@typeInfo(T)) {
 550                .int => |info| info.signedness == .signed,
 551                else => false,
 552            };
 553            if (!is_signed_int) {
 554                const d0 = x / y;
 555                inline for (@as([4]T, d0), 0..) |v, i| {
 556                    try expect(x[i] / y[i] == v);
 557                }
 558            }
 559            const d1 = @divExact(x, y);
 560            inline for (@as([4]T, d1), 0..) |v, i| {
 561                try expect(@divExact(x[i], y[i]) == v);
 562            }
 563            const d2 = @divFloor(x, y);
 564            inline for (@as([4]T, d2), 0..) |v, i| {
 565                try expect(@divFloor(x[i], y[i]) == v);
 566            }
 567            const d3 = @divTrunc(x, y);
 568            inline for (@as([4]T, d3), 0..) |v, i| {
 569                try expect(@divTrunc(x[i], y[i]) == v);
 570            }
 571        }
 572
 573        fn doTheTestMod(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void {
 574            const is_signed_int = switch (@typeInfo(T)) {
 575                .int => |info| info.signedness == .signed,
 576                else => false,
 577            };
 578            if (!is_signed_int and @typeInfo(T) != .float) {
 579                const r0 = x % y;
 580                inline for (@as([4]T, r0), 0..) |v, i| {
 581                    try expect(x[i] % y[i] == v);
 582                }
 583            }
 584            const r1 = @mod(x, y);
 585            inline for (@as([4]T, r1), 0..) |v, i| {
 586                try expect(@mod(x[i], y[i]) == v);
 587            }
 588            const r2 = @rem(x, y);
 589            inline for (@as([4]T, r2), 0..) |v, i| {
 590                try expect(@rem(x[i], y[i]) == v);
 591            }
 592        }
 593
 594        fn doTheTest() !void {
 595            try doTheTestDiv(f16, [4]f16{ 4.0, -4.0, 4.0, -4.0 }, [4]f16{ 1.0, 2.0, -1.0, -2.0 });
 596
 597            try doTheTestDiv(f32, [4]f32{ 4.0, -4.0, 4.0, -4.0 }, [4]f32{ 1.0, 2.0, -1.0, -2.0 });
 598            try doTheTestDiv(f64, [4]f64{ 4.0, -4.0, 4.0, -4.0 }, [4]f64{ 1.0, 2.0, -1.0, -2.0 });
 599
 600            try doTheTestMod(f16, [4]f16{ 4.0, -4.0, 4.0, -4.0 }, [4]f16{ 1.0, 2.0, 0.5, 3.0 });
 601            try doTheTestMod(f32, [4]f32{ 4.0, -4.0, 4.0, -4.0 }, [4]f32{ 1.0, 2.0, 0.5, 3.0 });
 602            try doTheTestMod(f64, [4]f64{ 4.0, -4.0, 4.0, -4.0 }, [4]f64{ 1.0, 2.0, 0.5, 3.0 });
 603
 604            try doTheTestDiv(i8, [4]i8{ 4, -4, 4, -4 }, [4]i8{ 1, 2, -1, -2 });
 605            try doTheTestDiv(i16, [4]i16{ 4, -4, 4, -4 }, [4]i16{ 1, 2, -1, -2 });
 606            try doTheTestDiv(i32, [4]i32{ 4, -4, 4, -4 }, [4]i32{ 1, 2, -1, -2 });
 607            try doTheTestDiv(i64, [4]i64{ 4, -4, 4, -4 }, [4]i64{ 1, 2, -1, -2 });
 608
 609            try doTheTestMod(i8, [4]i8{ 4, -4, 4, -4 }, [4]i8{ 1, 2, 4, 8 });
 610            try doTheTestMod(i16, [4]i16{ 4, -4, 4, -4 }, [4]i16{ 1, 2, 4, 8 });
 611            try doTheTestMod(i32, [4]i32{ 4, -4, 4, -4 }, [4]i32{ 1, 2, 4, 8 });
 612            try doTheTestMod(i64, [4]i64{ 4, -4, 4, -4 }, [4]i64{ 1, 2, 4, 8 });
 613
 614            try doTheTestDiv(u8, [4]u8{ 1, 2, 4, 8 }, [4]u8{ 1, 1, 2, 4 });
 615            try doTheTestDiv(u16, [4]u16{ 1, 2, 4, 8 }, [4]u16{ 1, 1, 2, 4 });
 616            try doTheTestDiv(u32, [4]u32{ 1, 2, 4, 8 }, [4]u32{ 1, 1, 2, 4 });
 617            try doTheTestDiv(u64, [4]u64{ 1, 2, 4, 8 }, [4]u64{ 1, 1, 2, 4 });
 618
 619            try doTheTestMod(u8, [4]u8{ 1, 2, 4, 8 }, [4]u8{ 1, 1, 2, 4 });
 620            try doTheTestMod(u16, [4]u16{ 1, 2, 4, 8 }, [4]u16{ 1, 1, 2, 4 });
 621            try doTheTestMod(u32, [4]u32{ 1, 2, 4, 8 }, [4]u32{ 1, 1, 2, 4 });
 622            try doTheTestMod(u64, [4]u64{ 1, 2, 4, 8 }, [4]u64{ 1, 1, 2, 4 });
 623        }
 624    };
 625
 626    try comptime S.doTheTest();
 627    if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
 628    try S.doTheTest();
 629}
 630
 631test "vector bitwise not operator" {
 632    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 633    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 634    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 635    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 636    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 637    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 638
 639    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) {
 640        // https://github.com/ziglang/zig/issues/24061
 641        return error.SkipZigTest;
 642    }
 643
 644    const S = struct {
 645        fn doTheTestNot(comptime T: type, x: @Vector(4, T)) !void {
 646            const y = ~x;
 647            inline for (@as([4]T, y), 0..) |v, i| {
 648                try expect(~x[i] == v);
 649            }
 650        }
 651        fn doTheTest() !void {
 652            try doTheTestNot(bool, [_]bool{ true, false, true, false });
 653
 654            try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
 655            try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
 656            try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
 657            try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
 658
 659            try doTheTestNot(i8, [_]i8{ 0, 2, 4, 127 });
 660            try doTheTestNot(i16, [_]i16{ 0, 2, 4, 127 });
 661            try doTheTestNot(i32, [_]i32{ 0, 2, 4, 127 });
 662            try doTheTestNot(i64, [_]i64{ 0, 2, 4, 127 });
 663        }
 664    };
 665
 666    try S.doTheTest();
 667    try comptime S.doTheTest();
 668}
 669
 670test "vector boolean not operator" {
 671    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 672    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 673    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 674    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 675    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 676    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 677
 678    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) {
 679        // https://github.com/ziglang/zig/issues/24061
 680        return error.SkipZigTest;
 681    }
 682
 683    const S = struct {
 684        fn doTheTestNot(comptime T: type, x: @Vector(4, T)) !void {
 685            const y = !x;
 686            inline for (@as([4]T, y), 0..) |v, i| {
 687                try expect(!x[i] == v);
 688            }
 689        }
 690        fn doTheTest() !void {
 691            try doTheTestNot(bool, [_]bool{ true, false, true, false });
 692        }
 693    };
 694
 695    try S.doTheTest();
 696    try comptime S.doTheTest();
 697}
 698
 699test "vector shift operators" {
 700    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 701    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 702    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 703    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 704    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 705    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 706
 707    const S = struct {
 708        fn doTheTestShift(x: anytype, y: anytype) !void {
 709            const N = @typeInfo(@TypeOf(x)).array.len;
 710            const TX = @typeInfo(@TypeOf(x)).array.child;
 711            const TY = @typeInfo(@TypeOf(y)).array.child;
 712
 713            const xv = @as(@Vector(N, TX), x);
 714            const yv = @as(@Vector(N, TY), y);
 715
 716            const z0 = xv >> yv;
 717            for (@as([N]TX, z0), 0..) |v, i| {
 718                try expect(x[i] >> y[i] == v);
 719            }
 720            const z1 = xv << yv;
 721            for (@as([N]TX, z1), 0..) |v, i| {
 722                try expect(x[i] << y[i] == v);
 723            }
 724        }
 725        fn doTheTestShiftExact(x: anytype, y: anytype, dir: enum { Left, Right }) !void {
 726            const N = @typeInfo(@TypeOf(x)).array.len;
 727            const TX = @typeInfo(@TypeOf(x)).array.child;
 728            const TY = @typeInfo(@TypeOf(y)).array.child;
 729
 730            const xv = @as(@Vector(N, TX), x);
 731            const yv = @as(@Vector(N, TY), y);
 732
 733            const z = if (dir == .Left) @shlExact(xv, yv) else @shrExact(xv, yv);
 734            for (@as([N]TX, z), 0..) |v, i| {
 735                const check = if (dir == .Left) x[i] << y[i] else x[i] >> y[i];
 736                try expect(check == v);
 737            }
 738        }
 739        fn doTheTest() !void {
 740            try doTheTestShift([_]u8{ 0, 2, 4, math.maxInt(u8) }, [_]u3{ 2, 0, 2, 7 });
 741            try doTheTestShift([_]u16{ 0, 2, 4, math.maxInt(u16) }, [_]u4{ 2, 0, 2, 15 });
 742            try doTheTestShift([_]u24{ 0, 2, 4, math.maxInt(u24) }, [_]u5{ 2, 0, 2, 23 });
 743            try doTheTestShift([_]u32{ 0, 2, 4, math.maxInt(u32) }, [_]u5{ 2, 0, 2, 31 });
 744            try doTheTestShift([_]u64{ 0xfe, math.maxInt(u64) }, [_]u6{ 0, 63 });
 745
 746            try doTheTestShift([_]i8{ 0, 2, 4, math.maxInt(i8) }, [_]u3{ 2, 0, 2, 7 });
 747            try doTheTestShift([_]i16{ 0, 2, 4, math.maxInt(i16) }, [_]u4{ 2, 0, 2, 7 });
 748            try doTheTestShift([_]i24{ 0, 2, 4, math.maxInt(i24) }, [_]u5{ 2, 0, 2, 7 });
 749            try doTheTestShift([_]i32{ 0, 2, 4, math.maxInt(i32) }, [_]u5{ 2, 0, 2, 7 });
 750            try doTheTestShift([_]i64{ 0xfe, math.maxInt(i64) }, [_]u6{ 0, 63 });
 751
 752            try doTheTestShiftExact([_]u8{ 0, 1, 1 << 7, math.maxInt(u8) ^ 1 }, [_]u3{ 4, 0, 7, 1 }, .Right);
 753            try doTheTestShiftExact([_]u16{ 0, 1, 1 << 15, math.maxInt(u16) ^ 1 }, [_]u4{ 4, 0, 15, 1 }, .Right);
 754            try doTheTestShiftExact([_]u24{ 0, 1, 1 << 23, math.maxInt(u24) ^ 1 }, [_]u5{ 4, 0, 23, 1 }, .Right);
 755            try doTheTestShiftExact([_]u32{ 0, 1, 1 << 31, math.maxInt(u32) ^ 1 }, [_]u5{ 4, 0, 31, 1 }, .Right);
 756            try doTheTestShiftExact([_]u64{ 1 << 63, 1 }, [_]u6{ 63, 0 }, .Right);
 757
 758            try doTheTestShiftExact([_]u8{ 0, 1, 1, math.maxInt(u8) ^ (1 << 7) }, [_]u3{ 4, 0, 7, 1 }, .Left);
 759            try doTheTestShiftExact([_]u16{ 0, 1, 1, math.maxInt(u16) ^ (1 << 15) }, [_]u4{ 4, 0, 15, 1 }, .Left);
 760            try doTheTestShiftExact([_]u24{ 0, 1, 1, math.maxInt(u24) ^ (1 << 23) }, [_]u5{ 4, 0, 23, 1 }, .Left);
 761            try doTheTestShiftExact([_]u32{ 0, 1, 1, math.maxInt(u32) ^ (1 << 31) }, [_]u5{ 4, 0, 31, 1 }, .Left);
 762            try doTheTestShiftExact([_]u64{ 1 << 63, 1 }, [_]u6{ 0, 63 }, .Left);
 763        }
 764    };
 765
 766    try comptime S.doTheTest();
 767    if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
 768    try S.doTheTest();
 769}
 770
 771test "vector reduce operation" {
 772    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 773    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 774    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 775    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 776    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 777    if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
 778    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 779    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21091
 780    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isSPARC()) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23719
 781
 782    const S = struct {
 783        fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
 784            const N = @typeInfo(@TypeOf(x)).array.len;
 785            const TX = @typeInfo(@TypeOf(x)).array.child;
 786
 787            const r = @reduce(op, @as(@Vector(N, TX), x));
 788            switch (@typeInfo(TX)) {
 789                .int, .bool => try expect(expected == r),
 790                .float => {
 791                    const expected_nan = math.isNan(expected);
 792                    const got_nan = math.isNan(r);
 793
 794                    if (expected_nan and got_nan) {
 795                        // Do this check explicitly as two NaN values are never
 796                        // equal.
 797                    } else {
 798                        const F = @TypeOf(expected);
 799                        const tolerance = @sqrt(math.floatEps(TX));
 800                        try expect(std.math.approxEqRel(F, expected, r, tolerance));
 801                    }
 802                },
 803                else => unreachable,
 804            }
 805        }
 806        fn doTheTest() !void {
 807            try testReduce(.Add, [4]i16{ -9, -99, -999, -9999 }, @as(i32, -11106));
 808            try testReduce(.Add, [4]u16{ 9, 99, 999, 9999 }, @as(u32, 11106));
 809            try testReduce(.Add, [4]i32{ -9, -99, -999, -9999 }, @as(i32, -11106));
 810            try testReduce(.Add, [4]u32{ 9, 99, 999, 9999 }, @as(u32, 11106));
 811            try testReduce(.Add, [4]i64{ -9, -99, -999, -9999 }, @as(i64, -11106));
 812            try testReduce(.Add, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 11106));
 813            try testReduce(.Add, [4]i128{ -9, -99, -999, -9999 }, @as(i128, -11106));
 814            try testReduce(.Add, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 11106));
 815            try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9));
 816            try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9));
 817            try testReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9));
 818
 819            try testReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false));
 820            try testReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0));
 821            try testReduce(.And, [4]u16{ 0xffff, 0xff55, 0xaaff, 0x1010 }, @as(u16, 0x10));
 822            try testReduce(.And, [4]u32{ 0xffffffff, 0xffff5555, 0xaaaaffff, 0x10101010 }, @as(u32, 0x1010));
 823            try testReduce(.And, [4]u64{ 0xffffffff, 0xffff5555, 0xaaaaffff, 0x10101010 }, @as(u64, 0x1010));
 824
 825            try testReduce(.Min, [4]i16{ -1, 2, 3, 4 }, @as(i16, -1));
 826            try testReduce(.Min, [4]u16{ 1, 2, 3, 4 }, @as(u16, 1));
 827            try testReduce(.Min, [4]i32{ 1234567, -386, 0, 3 }, @as(i32, -386));
 828            try testReduce(.Min, [4]u32{ 99, 9999, 9, 99999 }, @as(u32, 9));
 829            try testReduce(.Min, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, -386));
 830            try testReduce(.Min, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 9));
 831            try testReduce(.Min, [4]i128{ 1234567, -386, 0, 3 }, @as(i128, -386));
 832            try testReduce(.Min, [4]u128{ 99, 9999, 9, 99999 }, @as(u128, 9));
 833            try testReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0));
 834            try testReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0));
 835            try testReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0));
 836
 837            try testReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4));
 838            try testReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4));
 839            try testReduce(.Max, [4]i32{ 1234567, -386, 0, 3 }, @as(i32, 1234567));
 840            try testReduce(.Max, [4]u32{ 99, 9999, 9, 99999 }, @as(u32, 99999));
 841            try testReduce(.Max, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, 1234567));
 842            try testReduce(.Max, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 99999));
 843            try testReduce(.Max, [4]i128{ 1234567, -386, 0, 3 }, @as(i128, 1234567));
 844            try testReduce(.Max, [4]u128{ 99, 9999, 9, 99999 }, @as(u128, 99999));
 845            try testReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9));
 846            try testReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9));
 847            try testReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9));
 848
 849            try testReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24));
 850            try testReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24));
 851            try testReduce(.Mul, [4]i32{ -9, -99, -999, 999 }, @as(i32, -889218891));
 852            try testReduce(.Mul, [4]u32{ 1, 2, 3, 4 }, @as(u32, 24));
 853            try testReduce(.Mul, [4]i64{ 9, 99, 999, 9999 }, @as(i64, 8900199891));
 854            try testReduce(.Mul, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 8900199891));
 855            try testReduce(.Mul, [4]i128{ -9, -99, -999, 9999 }, @as(i128, -8900199891));
 856            try testReduce(.Mul, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 8900199891));
 857            try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7));
 858            try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7));
 859            try testReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7));
 860
 861            try testReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true));
 862            try testReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1));
 863            try testReduce(.Or, [4]u16{ 0xff00, 0xff00, 0xf0, 0xf }, ~@as(u16, 0));
 864            try testReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0));
 865            try testReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff));
 866            try testReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff));
 867
 868            try testReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true));
 869            try testReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1));
 870            try testReduce(.Xor, [4]u16{ 0x0000, 0x3333, 0x8888, 0x4444 }, ~@as(u16, 0));
 871            try testReduce(.Xor, [4]u32{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, ~@as(u32, 0));
 872            try testReduce(.Xor, [4]u64{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, @as(u64, 0xffffffff));
 873            try testReduce(.Xor, [4]u128{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, @as(u128, 0xffffffff));
 874
 875            // Test the reduction on vectors containing NaNs.
 876            const f16_nan = math.nan(f16);
 877            const f32_nan = math.nan(f32);
 878            const f64_nan = math.nan(f64);
 879
 880            try testReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
 881            try testReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
 882            try testReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
 883
 884            try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9));
 885            try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9));
 886            try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, -1.9));
 887
 888            try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0));
 889            try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0));
 890            try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, 100.0));
 891
 892            try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
 893            try testReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
 894            try testReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
 895        }
 896    };
 897
 898    try S.doTheTest();
 899    try comptime S.doTheTest();
 900}
 901
 902test "vector @reduce comptime" {
 903    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 904    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 905    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 906
 907    const V = @Vector(4, i32);
 908
 909    const value = V{ 1, -1, 1, -1 };
 910    const result = value > @as(V, @splat(0));
 911    // result is { true, false, true, false };
 912    comptime assert(@TypeOf(result) == @Vector(4, bool));
 913    const is_all_true = @reduce(.And, result);
 914    comptime assert(@TypeOf(is_all_true) == bool);
 915    try expect(is_all_true == false);
 916}
 917
 918test "saturating add" {
 919    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 920    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 921    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 922    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 923    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 924    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 925
 926    const S = struct {
 927        fn doTheTest() !void {
 928            { // Broken out to avoid https://github.com/ziglang/zig/issues/11251
 929                const u8x3 = @Vector(3, u8);
 930                var lhs = u8x3{ 255, 254, 1 };
 931                var rhs = u8x3{ 1, 2, 255 };
 932                _ = .{ &lhs, &rhs };
 933                const result = lhs +| rhs;
 934                const expected = u8x3{ 255, 255, 255 };
 935                try expect(mem.eql(u8, &@as([3]u8, expected), &@as([3]u8, result)));
 936            }
 937            { // Broken out to avoid https://github.com/ziglang/zig/issues/11251
 938                const i8x3 = @Vector(3, i8);
 939                var lhs = i8x3{ 127, 126, 1 };
 940                var rhs = i8x3{ 1, 2, 127 };
 941                _ = .{ &lhs, &rhs };
 942                const result = lhs +| rhs;
 943                const expected = i8x3{ 127, 127, 127 };
 944                try expect(mem.eql(i8, &@as([3]i8, expected), &@as([3]i8, result)));
 945            }
 946            try testElemType(i4);
 947            try testElemType(u4);
 948            try testElemType(i8);
 949            try testElemType(u8);
 950            try testElemType(i12);
 951            try testElemType(u12);
 952            try testElemType(i16);
 953            try testElemType(u16);
 954            try testElemType(i24);
 955            try testElemType(u24);
 956            try testElemType(i32);
 957            try testElemType(u32);
 958            try testElemType(i48);
 959            try testElemType(u48);
 960            try testElemType(i64);
 961            try testElemType(u64);
 962        }
 963        fn testElemType(comptime Elem: type) !void {
 964            const min = std.math.minInt(Elem);
 965            const max = std.math.maxInt(Elem);
 966
 967            var v: @Vector(4, Elem) = .{ 0, 1, 0, 1 };
 968            v +|= .{ 0, 0, 1, 1 };
 969            try expect(v[0] == 0);
 970            try expect(v[1] == 1);
 971            try expect(v[2] == 1);
 972            try expect(v[3] == 2);
 973
 974            v = .{ 0, max, 1, max };
 975            v +|= .{ max, 0, max, 1 };
 976            try expect(v[0] == max);
 977            try expect(v[1] == max);
 978            try expect(v[2] == max);
 979            try expect(v[3] == max);
 980
 981            v = .{ 1, max - 1, max / 2, max };
 982            v +|= .{ max - 1, 1, max / 2, max };
 983            try expect(v[0] == max);
 984            try expect(v[1] == max);
 985            try expect(v[2] == max - 1);
 986            try expect(v[3] == max);
 987
 988            switch (@typeInfo(Elem).int.signedness) {
 989                .signed => {
 990                    v = .{ -1, -1, 0, -1 };
 991                    v +|= .{ 1, 0, -1, -1 };
 992                    try expect(v[0] == 0);
 993                    try expect(v[1] == -1);
 994                    try expect(v[2] == -1);
 995                    try expect(v[3] == -2);
 996
 997                    v = .{ 0, min, -1, min };
 998                    v +|= .{ min, 0, min, -1 };
 999                    try expect(v[0] == min);
1000                    try expect(v[1] == min);
1001                    try expect(v[2] == min);
1002                    try expect(v[3] == min);
1003
1004                    v = .{ -1, min + 1, min / 2, min };
1005                    v +|= .{ min + 1, -1, min / 2, min };
1006                    try expect(v[0] == min);
1007                    try expect(v[1] == min);
1008                    try expect(v[2] == min);
1009                    try expect(v[3] == min);
1010                },
1011                .unsigned => {},
1012            }
1013        }
1014    };
1015    try S.doTheTest();
1016    try comptime S.doTheTest();
1017}
1018
1019test "saturating subtraction" {
1020    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1021    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1022    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1023    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1024    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1025    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1026
1027    const S = struct {
1028        fn doTheTest() !void {
1029            {
1030                // Broken out to avoid https://github.com/ziglang/zig/issues/11251
1031                const u8x3 = @Vector(3, u8);
1032                var lhs = u8x3{ 0, 0, 0 };
1033                var rhs = u8x3{ 255, 255, 255 };
1034                _ = .{ &lhs, &rhs };
1035                const result = lhs -| rhs;
1036                const expected = u8x3{ 0, 0, 0 };
1037                try expect(mem.eql(u8, &@as([3]u8, expected), &@as([3]u8, result)));
1038            }
1039            try testElemType(i4);
1040            try testElemType(u4);
1041            try testElemType(i8);
1042            try testElemType(u8);
1043            try testElemType(i12);
1044            try testElemType(u12);
1045            try testElemType(i16);
1046            try testElemType(u16);
1047            try testElemType(i24);
1048            try testElemType(u24);
1049            try testElemType(i32);
1050            try testElemType(u32);
1051            try testElemType(i48);
1052            try testElemType(u48);
1053            try testElemType(i64);
1054            try testElemType(u64);
1055        }
1056        fn testElemType(comptime Elem: type) !void {
1057            const min = std.math.minInt(Elem);
1058            const max = std.math.maxInt(Elem);
1059
1060            var v: @Vector(4, Elem) = .{ 0, 1, 0, 1 };
1061            v -|= .{ 0, 0, 1, 1 };
1062            try expect(v[0] == 0);
1063            try expect(v[1] == 1);
1064            try expect(v[2] == @max(min, -1));
1065            try expect(v[3] == 0);
1066
1067            v = .{ 0, max, 1, max };
1068            v -|= .{ max, 0, max, 1 };
1069            try expect(v[0] == @min(min + 1, 0));
1070            try expect(v[1] == max);
1071            try expect(v[2] == @min(min + 2, 0));
1072            try expect(v[3] == max - 1);
1073
1074            v = .{ 1, max - 1, max / 2, max };
1075            v -|= .{ max - 1, 1, max / 2, max };
1076            try expect(v[0] == @min(min + 3, 0));
1077            try expect(v[1] == max - 2);
1078            try expect(v[2] == 0);
1079            try expect(v[3] == 0);
1080
1081            switch (@typeInfo(Elem).int.signedness) {
1082                .signed => {
1083                    v = .{ -1, -1, 0, -1 };
1084                    v -|= .{ -1, 0, 1, 1 };
1085                    try expect(v[0] == 0);
1086                    try expect(v[1] == -1);
1087                    try expect(v[2] == -1);
1088                    try expect(v[3] == -2);
1089
1090                    v = .{ 0, min, -1, min };
1091                    v -|= .{ max, 0, max, 1 };
1092                    try expect(v[0] == min + 1);
1093                    try expect(v[1] == min);
1094                    try expect(v[2] == min);
1095                    try expect(v[3] == min);
1096
1097                    v = .{ -1, min + 1, min / 2, min };
1098                    v -|= .{ max, 1, max / 2, max };
1099                    try expect(v[0] == min);
1100                    try expect(v[1] == min);
1101                    try expect(v[2] == min + 1);
1102                    try expect(v[3] == min);
1103                },
1104                .unsigned => {},
1105            }
1106        }
1107    };
1108    try S.doTheTest();
1109    try comptime S.doTheTest();
1110}
1111
1112test "saturating multiplication" {
1113    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1114    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1115    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1116    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1117    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1118    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1119
1120    // TODO: once #9660 has been solved, remove this line
1121    if (builtin.target.cpu.arch.isWasm()) return error.SkipZigTest;
1122
1123    const S = struct {
1124        fn doTheTest() !void {
1125            // Broken out to avoid https://github.com/ziglang/zig/issues/11251
1126            const u8x3 = @Vector(3, u8);
1127            var lhs = u8x3{ 2, 2, 2 };
1128            var rhs = u8x3{ 255, 255, 255 };
1129            _ = .{ &lhs, &rhs };
1130            const result = lhs *| rhs;
1131            const expected = u8x3{ 255, 255, 255 };
1132            try expect(mem.eql(u8, &@as([3]u8, expected), &@as([3]u8, result)));
1133        }
1134    };
1135
1136    try S.doTheTest();
1137    try comptime S.doTheTest();
1138}
1139
1140test "saturating shift-left" {
1141    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1142    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1143    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1144    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1145    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1146    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1147
1148    const S = struct {
1149        fn doTheTest() !void {
1150            // Broken out to avoid https://github.com/ziglang/zig/issues/11251
1151            const u8x3 = @Vector(3, u8);
1152            var lhs = u8x3{ 1, 1, 1 };
1153            var rhs = u8x3{ 255, 255, 255 };
1154            _ = .{ &lhs, &rhs };
1155            const result = lhs <<| rhs;
1156            const expected = u8x3{ 255, 255, 255 };
1157            try expect(mem.eql(u8, &@as([3]u8, expected), &@as([3]u8, result)));
1158        }
1159    };
1160    try S.doTheTest();
1161    try comptime S.doTheTest();
1162}
1163
1164test "multiplication-assignment operator with an array operand" {
1165    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1166    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1167    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1168    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1169    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1170    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1171
1172    const S = struct {
1173        fn doTheTest() !void {
1174            var x: @Vector(3, i32) = .{ 1, 2, 3 };
1175            x *= [_]i32{ 4, 5, 6 };
1176            try expect(x[0] == 4);
1177            try expect(x[1] == 10);
1178            try expect(x[2] == 18);
1179        }
1180    };
1181    try S.doTheTest();
1182    try comptime S.doTheTest();
1183}
1184
1185test "@addWithOverflow" {
1186    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1187    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1188    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1189    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1190    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1191    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1192    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1193
1194    const S = struct {
1195        fn doTheTest() !void {
1196            {
1197                var lhs = @Vector(4, u8){ 250, 250, 250, 250 };
1198                var rhs = @Vector(4, u8){ 0, 5, 6, 10 };
1199                _ = .{ &lhs, &rhs };
1200                const overflow = @addWithOverflow(lhs, rhs)[1];
1201                const expected: @Vector(4, u1) = .{ 0, 0, 1, 1 };
1202                try expectEqual(expected, overflow);
1203            }
1204            {
1205                var lhs = @Vector(4, i8){ -125, -125, 125, 125 };
1206                var rhs = @Vector(4, i8){ -3, -4, 2, 3 };
1207                _ = .{ &lhs, &rhs };
1208                const overflow = @addWithOverflow(lhs, rhs)[1];
1209                const expected: @Vector(4, u1) = .{ 0, 1, 0, 1 };
1210                try expectEqual(expected, overflow);
1211            }
1212            {
1213                var lhs = @Vector(4, u1){ 0, 0, 1, 1 };
1214                var rhs = @Vector(4, u1){ 0, 1, 0, 1 };
1215                _ = .{ &lhs, &rhs };
1216                const overflow = @addWithOverflow(lhs, rhs)[1];
1217                const expected: @Vector(4, u1) = .{ 0, 0, 0, 1 };
1218                try expectEqual(expected, overflow);
1219            }
1220            {
1221                var lhs = @Vector(4, u0){ 0, 0, 0, 0 };
1222                var rhs = @Vector(4, u0){ 0, 0, 0, 0 };
1223                _ = .{ &lhs, &rhs };
1224                const overflow = @addWithOverflow(lhs, rhs)[1];
1225                const expected: @Vector(4, u1) = .{ 0, 0, 0, 0 };
1226                try expectEqual(expected, overflow);
1227            }
1228        }
1229    };
1230    try comptime S.doTheTest();
1231    try S.doTheTest();
1232}
1233
1234test "@subWithOverflow" {
1235    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1236    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1237    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1238    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1239    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1240    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1241    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1242
1243    const S = struct {
1244        fn doTheTest() !void {
1245            {
1246                var lhs = @Vector(2, u8){ 5, 5 };
1247                var rhs = @Vector(2, u8){ 5, 6 };
1248                _ = .{ &lhs, &rhs };
1249                const overflow = @subWithOverflow(lhs, rhs)[1];
1250                const expected: @Vector(2, u1) = .{ 0, 1 };
1251                try expectEqual(expected, overflow);
1252            }
1253            {
1254                var lhs = @Vector(4, i8){ -120, -120, 120, 120 };
1255                var rhs = @Vector(4, i8){ 8, 9, -7, -8 };
1256                _ = .{ &lhs, &rhs };
1257                const overflow = @subWithOverflow(lhs, rhs)[1];
1258                const expected: @Vector(4, u1) = .{ 0, 1, 0, 1 };
1259                try expectEqual(expected, overflow);
1260            }
1261        }
1262    };
1263    try comptime S.doTheTest();
1264    try S.doTheTest();
1265}
1266
1267test "@mulWithOverflow" {
1268    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1269    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1270    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1271    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1272    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1273    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1274
1275    const S = struct {
1276        fn doTheTest() !void {
1277            var lhs = @Vector(4, u8){ 10, 10, 10, 10 };
1278            var rhs = @Vector(4, u8){ 25, 26, 0, 30 };
1279            _ = .{ &lhs, &rhs };
1280            const overflow = @mulWithOverflow(lhs, rhs)[1];
1281            const expected: @Vector(4, u1) = .{ 0, 1, 0, 1 };
1282            try expectEqual(expected, overflow);
1283        }
1284    };
1285    try comptime S.doTheTest();
1286    try S.doTheTest();
1287}
1288
1289test "@shlWithOverflow" {
1290    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1291    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1292    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1293    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1294    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1295    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1296
1297    const S = struct {
1298        fn doTheTest() !void {
1299            var lhs = @Vector(4, u8){ 0, 1, 8, 255 };
1300            var rhs = @Vector(4, u3){ 7, 7, 7, 7 };
1301            _ = .{ &lhs, &rhs };
1302            const overflow = @shlWithOverflow(lhs, rhs)[1];
1303            const expected: @Vector(4, u1) = .{ 0, 0, 1, 1 };
1304            try expectEqual(expected, overflow);
1305        }
1306    };
1307    try S.doTheTest();
1308    try comptime S.doTheTest();
1309}
1310
1311test "alignment of vectors" {
1312    try expect(@alignOf(@Vector(2, u8)) == switch (builtin.zig_backend) {
1313        else => 2,
1314        .stage2_c => @alignOf(u8),
1315        .stage2_x86_64 => 16,
1316    });
1317    try expect(@alignOf(@Vector(2, u1)) == switch (builtin.zig_backend) {
1318        else => 1,
1319        .stage2_c => @alignOf(u1),
1320        .stage2_x86_64 => 16,
1321    });
1322    try expect(@alignOf(@Vector(1, u1)) == switch (builtin.zig_backend) {
1323        else => 1,
1324        .stage2_c => @alignOf(u1),
1325        .stage2_x86_64 => 16,
1326    });
1327    try expect(@alignOf(@Vector(2, u16)) == switch (builtin.zig_backend) {
1328        else => 4,
1329        .stage2_c => @alignOf(u16),
1330        .stage2_x86_64 => 16,
1331    });
1332}
1333
1334test "loading the second vector from a slice of vectors" {
1335    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1336    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1337    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1338    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1339
1340    @setRuntimeSafety(false);
1341    var small_bases = [2]@Vector(2, u8){
1342        @Vector(2, u8){ 0, 1 },
1343        @Vector(2, u8){ 2, 3 },
1344    };
1345    const a: []const @Vector(2, u8) = &small_bases;
1346    const a4 = a[1][1];
1347    try expect(a4 == 3);
1348}
1349
1350test "array of vectors is copied" {
1351    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1352    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1353    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1354    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1355    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1356
1357    const Vec3 = @Vector(3, i32);
1358    var points = [_]Vec3{
1359        Vec3{ 404, -588, -901 },
1360        Vec3{ 528, -643, 409 },
1361        Vec3{ -838, 591, 734 },
1362        Vec3{ 390, -675, -793 },
1363        Vec3{ -537, -823, -458 },
1364        Vec3{ -485, -357, 347 },
1365        Vec3{ -345, -311, 381 },
1366        Vec3{ -661, -816, -575 },
1367    };
1368    _ = &points;
1369    var points2: [20]Vec3 = undefined;
1370    points2[0..points.len].* = points;
1371    try std.testing.expectEqual(points2[6], Vec3{ -345, -311, 381 });
1372}
1373
1374test "byte vector initialized in inline function" {
1375    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1376    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1377    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1378    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1379    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1380    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1381    if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1382
1383    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and comptime builtin.cpu.has(.x86, .avx512f)) {
1384        // TODO https://github.com/ziglang/zig/issues/13279
1385        return error.SkipZigTest;
1386    }
1387
1388    const S = struct {
1389        fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {
1390            return .{ e0, e1, e2, e3 };
1391        }
1392
1393        fn all(vb: @Vector(4, bool)) bool {
1394            return @reduce(.And, vb);
1395        }
1396    };
1397
1398    try expect(S.all(S.boolx4(true, true, true, true)));
1399}
1400
1401test "zero divisor" {
1402    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1403    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1404    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1405
1406    const zeros = @Vector(2, f32){ 0.0, 0.0 };
1407    const ones = @Vector(2, f32){ 1.0, 1.0 };
1408
1409    const v1 = zeros / ones;
1410    const v2 = @divExact(zeros, ones);
1411    const v3 = @divTrunc(zeros, ones);
1412    const v4 = @divFloor(zeros, ones);
1413
1414    _ = v1[0];
1415    _ = v2[0];
1416    _ = v3[0];
1417    _ = v4[0];
1418}
1419
1420test "zero multiplicand" {
1421    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1422    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1423    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1424    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1425    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1426
1427    const zeros = @Vector(2, u32){ 0.0, 0.0 };
1428    var ones = @Vector(2, u32){ 1.0, 1.0 };
1429    _ = &ones;
1430
1431    _ = (ones * zeros)[0];
1432    _ = (zeros * zeros)[0];
1433    _ = (zeros * ones)[0];
1434
1435    _ = (ones *| zeros)[0];
1436    _ = (zeros *| zeros)[0];
1437    _ = (zeros *| ones)[0];
1438
1439    _ = (ones *% zeros)[0];
1440    _ = (zeros *% zeros)[0];
1441    _ = (zeros *% ones)[0];
1442}
1443
1444test "@intCast to u0" {
1445    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1446    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1447    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1448    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1449    if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1450
1451    var zeros = @Vector(2, u32){ 0, 0 };
1452    _ = &zeros;
1453    const casted = @as(@Vector(2, u0), @intCast(zeros));
1454
1455    _ = casted[0];
1456}
1457
1458test "modRem with zero divisor" {
1459    comptime {
1460        var zeros = @Vector(2, u32){ 0, 0 };
1461        const ones = @Vector(2, u32){ 1, 1 };
1462
1463        zeros %= ones;
1464        _ = zeros[0];
1465    }
1466}
1467
1468test "array operands to shuffle are coerced to vectors" {
1469    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1470    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1471    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1472    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1473    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1474
1475    const mask = [5]i32{ -1, 0, 1, 2, 3 };
1476
1477    var a = [5]u32{ 3, 5, 7, 9, 0 };
1478    _ = &a;
1479    const b = @shuffle(u32, a, @as(@Vector(5, u24), @splat(0)), mask);
1480    try expectEqual([_]u32{ 0, 3, 5, 7, 9 }, b);
1481}
1482
1483test "load packed vector element" {
1484    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1485    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1486    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1487    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1488    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1489
1490    var x: @Vector(2, u15) = .{ 1, 4 };
1491    try expect((&x[0]).* == 1);
1492    try expect((&x[1]).* == 4);
1493}
1494
1495test "store packed vector element" {
1496    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1497    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1498    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1499    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1500    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1501    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1502    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1503
1504    var v = @Vector(4, u1){ 1, 1, 1, 1 };
1505    try expectEqual(@Vector(4, u1){ 1, 1, 1, 1 }, v);
1506    const index: usize = 0;
1507    v[index] = 0;
1508    try expectEqual(@Vector(4, u1){ 0, 1, 1, 1 }, v);
1509}
1510
1511test "store to vector in slice" {
1512    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1513    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1514    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1515    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1516    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1517
1518    var v = [_]@Vector(3, f32){
1519        .{ 1, 1, 1 },
1520        .{ 0, 0, 0 },
1521    };
1522    var s: []@Vector(3, f32) = &v;
1523    var i: usize = 1;
1524    _ = &i;
1525    s[i] = s[0];
1526    try expectEqual(v[1], v[0]);
1527}
1528
1529test "store vector with memset" {
1530    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1531    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1532    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1533    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1534    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1535    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1536    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1537    if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1538
1539    var a: [5]@Vector(2, i1) = undefined;
1540    var b: [5]@Vector(2, u2) = undefined;
1541    var c: [5]@Vector(2, i4) = undefined;
1542    var d: [5]@Vector(2, u8) = undefined;
1543    var e: [5]@Vector(2, i9) = undefined;
1544    var ka = @Vector(2, i1){ -1, 0 };
1545    var kb = @Vector(2, u2){ 0, 1 };
1546    var kc = @Vector(2, i4){ 2, 3 };
1547    var kd = @Vector(2, u8){ 4, 5 };
1548    var ke = @Vector(2, i9){ 6, 7 };
1549    _ = .{ &ka, &kb, &kc, &kd, &ke };
1550    @memset(&a, ka);
1551    @memset(&b, kb);
1552    @memset(&c, kc);
1553    @memset(&d, kd);
1554    @memset(&e, ke);
1555    try std.testing.expectEqual(ka, a[0]);
1556    try std.testing.expectEqual(kb, b[1]);
1557    try std.testing.expectEqual(kc, c[2]);
1558    try std.testing.expectEqual(kd, d[3]);
1559    try std.testing.expectEqual(ke, e[4]);
1560}
1561
1562test "addition of vectors represented as strings" {
1563    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1564    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1565
1566    const V = @Vector(3, u8);
1567    const foo: V = "foo".*;
1568    const bar: V = @typeName(u32).*;
1569    try expectEqual(V{ 219, 162, 161 }, foo + bar);
1570}
1571
1572test "compare vectors with different element types" {
1573    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1574    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1575    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1576    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1577    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1578
1579    var a: @Vector(2, u8) = .{ 1, 2 };
1580    var b: @Vector(2, u9) = .{ 3, 0 };
1581    _ = .{ &a, &b };
1582    try expectEqual(@Vector(2, bool){ true, false }, a < b);
1583}
1584
1585test "vector pointer is indexable" {
1586    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1587    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1588    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1589
1590    const V = @Vector(2, u32);
1591
1592    const x: V = .{ 123, 456 };
1593    comptime assert(@TypeOf(&(&x)[0]) == *const u32); // validate constness
1594    try expectEqual(@as(u32, 123), (&x)[0]);
1595    try expectEqual(@as(u32, 456), (&x)[1]);
1596
1597    var y: V = .{ 123, 456 };
1598    comptime assert(@TypeOf(&(&y)[0]) == *u32); // validate constness
1599    try expectEqual(@as(u32, 123), (&y)[0]);
1600    try expectEqual(@as(u32, 456), (&y)[1]);
1601
1602    (&y)[0] = 100;
1603    (&y)[1] = 200;
1604    try expectEqual(@as(u32, 100), (&y)[0]);
1605    try expectEqual(@as(u32, 200), (&y)[1]);
1606}
1607
1608test "boolean vector with 2 or more booleans" {
1609    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1610    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1611    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1612
1613    const vec1 = @Vector(2, bool){ true, true };
1614    _ = vec1;
1615
1616    const vec2 = @Vector(3, bool){ true, true, true };
1617    _ = vec2;
1618}
1619
1620test "bitcast to vector with different child type" {
1621    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1622    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1623    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1624    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1625    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1626    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1627
1628    const S = struct {
1629        fn doTheTest() !void {
1630            const VecA = @Vector(8, u16);
1631            const VecB = @Vector(4, u32);
1632
1633            var vec_a = VecA{ 1, 1, 1, 1, 1, 1, 1, 1 };
1634            _ = &vec_a;
1635            const vec_b: VecB = @bitCast(vec_a);
1636            const vec_c: VecA = @bitCast(vec_b);
1637            try expectEqual(vec_a, vec_c);
1638        }
1639    };
1640
1641    // Originally reported at https://github.com/ziglang/zig/issues/8184
1642    try S.doTheTest();
1643    try comptime S.doTheTest();
1644}
1645
1646test "index into comptime-known vector is comptime-known" {
1647    const vec: @Vector(2, f16) = [2]f16{ 1.5, 3.5 };
1648    if (vec[0] != 1.5) @compileError("vec should be comptime");
1649}
1650
1651test "arithmetic on zero-length vectors" {
1652    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1653    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1654
1655    {
1656        const a = @Vector(0, i32){};
1657        const b = @Vector(0, i32){};
1658        _ = a + b;
1659    }
1660    {
1661        const a = @Vector(0, i32){};
1662        const b = @Vector(0, i32){};
1663        _ = a - b;
1664    }
1665}
1666
1667test "@reduce on bool vector" {
1668    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1669    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1670
1671    const a = @Vector(2, bool){ true, true };
1672    const b = @Vector(1, bool){true};
1673    try std.testing.expect(@reduce(.And, a));
1674    try std.testing.expect(@reduce(.And, b));
1675}
1676
1677test "bitcast vector to array of smaller vectors" {
1678    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1679    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1680    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1681
1682    const u8x32 = @Vector(32, u8);
1683    const u8x64 = @Vector(64, u8);
1684    const S = struct {
1685        fn doTheTest(input_vec: u8x64) !void {
1686            try compare(@bitCast(input_vec));
1687        }
1688        fn compare(chunks: [2]u8x32) !void {
1689            try expectEqual(@as(u8x32, @splat(1)), chunks[0]);
1690            try expectEqual(@as(u8x32, @splat(2)), chunks[1]);
1691        }
1692    };
1693    const input: u8x64 = @bitCast([2]u8x32{ @splat(1), @splat(2) });
1694    try S.doTheTest(input);
1695}