1const std = @import("std"); 2const builtin = @import("builtin"); 3const mem = std.mem; 4const math = std.math; 5const expect = std.testing.expect; 6const expectEqual = std.testing.expectEqual; 7const expectApproxEqRel = std.testing.expectApproxEqRel; 8const Vector = std.meta.Vector; 9 10test "implicit cast vector to array - bool" { 11 const S = struct { 12 fn doTheTest() !void { 13 const a: Vector(4, bool) = [_]bool{ true, false, true, false }; 14 const result_array: [4]bool = a; 15 try expect(mem.eql(bool, &result_array, &[4]bool{ true, false, true, false })); 16 } 17 }; 18 try S.doTheTest(); 19 comptime try S.doTheTest(); 20} 21 22test "vector wrap operators" { 23 const S = struct { 24 fn doTheTest() !void { 25 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 }; 26 var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 }; 27 try expect(mem.eql(i32, &@as([4]i32, v +% x), &[4]i32{ -2147483648, 2147483645, 33, 44 })); 28 try expect(mem.eql(i32, &@as([4]i32, v -% x), &[4]i32{ 2147483646, 2147483647, 27, 36 })); 29 try expect(mem.eql(i32, &@as([4]i32, v *% x), &[4]i32{ 2147483647, 2, 90, 160 })); 30 var z: Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 }; 31 try expect(mem.eql(i32, &@as([4]i32, -%z), &[4]i32{ -1, -2, -3, -2147483648 })); 32 } 33 }; 34 try S.doTheTest(); 35 comptime try S.doTheTest(); 36} 37 38test "vector bin compares with mem.eql" { 39 const S = struct { 40 fn doTheTest() !void { 41 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 }; 42 var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 }; 43 try expect(mem.eql(bool, &@as([4]bool, v == x), &[4]bool{ false, false, true, false })); 44 try expect(mem.eql(bool, &@as([4]bool, v != x), &[4]bool{ true, true, false, true })); 45 try expect(mem.eql(bool, &@as([4]bool, v < x), &[4]bool{ false, true, false, false })); 46 try expect(mem.eql(bool, &@as([4]bool, v > x), &[4]bool{ true, false, false, true })); 47 try expect(mem.eql(bool, &@as([4]bool, v <= x), &[4]bool{ false, true, true, false })); 48 try expect(mem.eql(bool, &@as([4]bool, v >= x), &[4]bool{ true, false, true, true })); 49 } 50 }; 51 try S.doTheTest(); 52 comptime try S.doTheTest(); 53} 54 55test "vector int operators" { 56 const S = struct { 57 fn doTheTest() !void { 58 var v: Vector(4, i32) = [4]i32{ 10, 20, 30, 40 }; 59 var x: Vector(4, i32) = [4]i32{ 1, 2, 3, 4 }; 60 try expect(mem.eql(i32, &@as([4]i32, v + x), &[4]i32{ 11, 22, 33, 44 })); 61 try expect(mem.eql(i32, &@as([4]i32, v - x), &[4]i32{ 9, 18, 27, 36 })); 62 try expect(mem.eql(i32, &@as([4]i32, v * x), &[4]i32{ 10, 40, 90, 160 })); 63 try expect(mem.eql(i32, &@as([4]i32, -v), &[4]i32{ -10, -20, -30, -40 })); 64 } 65 }; 66 try S.doTheTest(); 67 comptime try S.doTheTest(); 68} 69 70test "vector float operators" { 71 const S = struct { 72 fn doTheTest() !void { 73 var v: Vector(4, f32) = [4]f32{ 10, 20, 30, 40 }; 74 var x: Vector(4, f32) = [4]f32{ 1, 2, 3, 4 }; 75 try expect(mem.eql(f32, &@as([4]f32, v + x), &[4]f32{ 11, 22, 33, 44 })); 76 try expect(mem.eql(f32, &@as([4]f32, v - x), &[4]f32{ 9, 18, 27, 36 })); 77 try expect(mem.eql(f32, &@as([4]f32, v * x), &[4]f32{ 10, 40, 90, 160 })); 78 try expect(mem.eql(f32, &@as([4]f32, -x), &[4]f32{ -1, -2, -3, -4 })); 79 } 80 }; 81 try S.doTheTest(); 82 comptime try S.doTheTest(); 83} 84 85test "vector bit operators" { 86 const S = struct { 87 fn doTheTest() !void { 88 var v: Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 }; 89 var x: Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 }; 90 try expect(mem.eql(u8, &@as([4]u8, v ^ x), &[4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 })); 91 try expect(mem.eql(u8, &@as([4]u8, v | x), &[4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 })); 92 try expect(mem.eql(u8, &@as([4]u8, v & x), &[4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 })); 93 } 94 }; 95 try S.doTheTest(); 96 comptime try S.doTheTest(); 97} 98 99test "implicit cast vector to array" { 100 const S = struct { 101 fn doTheTest() !void { 102 var a: Vector(4, i32) = [_]i32{ 1, 2, 3, 4 }; 103 var result_array: [4]i32 = a; 104 result_array = a; 105 try expect(mem.eql(i32, &result_array, &[4]i32{ 1, 2, 3, 4 })); 106 } 107 }; 108 try S.doTheTest(); 109 comptime try S.doTheTest(); 110} 111 112test "array to vector" { 113 var foo: f32 = 3.14; 114 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 }; 115 var vec: Vector(4, f32) = arr; 116 _ = vec; 117} 118 119test "vector casts of sizes not divisible by 8" { 120 const S = struct { 121 fn doTheTest() !void { 122 { 123 var v: Vector(4, u3) = [4]u3{ 5, 2, 3, 0 }; 124 var x: [4]u3 = v; 125 try expect(mem.eql(u3, &x, &@as([4]u3, v))); 126 } 127 { 128 var v: Vector(4, u2) = [4]u2{ 1, 2, 3, 0 }; 129 var x: [4]u2 = v; 130 try expect(mem.eql(u2, &x, &@as([4]u2, v))); 131 } 132 { 133 var v: Vector(4, u1) = [4]u1{ 1, 0, 1, 0 }; 134 var x: [4]u1 = v; 135 try expect(mem.eql(u1, &x, &@as([4]u1, v))); 136 } 137 { 138 var v: Vector(4, bool) = [4]bool{ false, false, true, false }; 139 var x: [4]bool = v; 140 try expect(mem.eql(bool, &x, &@as([4]bool, v))); 141 } 142 } 143 }; 144 try S.doTheTest(); 145 comptime try S.doTheTest(); 146} 147 148test "vector @splat" { 149 const S = struct { 150 fn testForT(comptime N: comptime_int, v: anytype) !void { 151 const T = @TypeOf(v); 152 var vec = @splat(N, v); 153 try expectEqual(Vector(N, T), @TypeOf(vec)); 154 var as_array = @as([N]T, vec); 155 for (as_array) |elem| try expectEqual(v, elem); 156 } 157 fn doTheTest() !void { 158 // Splats with multiple-of-8 bit types that fill a 128bit vector. 159 try testForT(16, @as(u8, 0xEE)); 160 try testForT(8, @as(u16, 0xBEEF)); 161 try testForT(4, @as(u32, 0xDEADBEEF)); 162 try testForT(2, @as(u64, 0xCAFEF00DDEADBEEF)); 163 164 try testForT(8, @as(f16, 3.1415)); 165 try testForT(4, @as(f32, 3.1415)); 166 try testForT(2, @as(f64, 3.1415)); 167 168 // Same but fill more than 128 bits. 169 try testForT(16 * 2, @as(u8, 0xEE)); 170 try testForT(8 * 2, @as(u16, 0xBEEF)); 171 try testForT(4 * 2, @as(u32, 0xDEADBEEF)); 172 try testForT(2 * 2, @as(u64, 0xCAFEF00DDEADBEEF)); 173 174 try testForT(8 * 2, @as(f16, 3.1415)); 175 try testForT(4 * 2, @as(f32, 3.1415)); 176 try testForT(2 * 2, @as(f64, 3.1415)); 177 } 178 }; 179 try S.doTheTest(); 180 comptime try S.doTheTest(); 181} 182 183test "load vector elements via comptime index" { 184 const S = struct { 185 fn doTheTest() !void { 186 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined }; 187 try expect(v[0] == 1); 188 try expect(v[1] == 2); 189 try expect(loadv(&v[2]) == 3); 190 } 191 fn loadv(ptr: anytype) i32 { 192 return ptr.*; 193 } 194 }; 195 196 try S.doTheTest(); 197 comptime try S.doTheTest(); 198} 199 200test "store vector elements via comptime index" { 201 const S = struct { 202 fn doTheTest() !void { 203 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined }; 204 205 v[2] = 42; 206 try expect(v[1] == 5); 207 v[3] = -364; 208 try expect(v[2] == 42); 209 try expect(-364 == v[3]); 210 211 storev(&v[0], 100); 212 try expect(v[0] == 100); 213 } 214 fn storev(ptr: anytype, x: i32) void { 215 ptr.* = x; 216 } 217 }; 218 219 try S.doTheTest(); 220 comptime try S.doTheTest(); 221} 222 223test "load vector elements via runtime index" { 224 const S = struct { 225 fn doTheTest() !void { 226 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined }; 227 var i: u32 = 0; 228 try expect(v[i] == 1); 229 i += 1; 230 try expect(v[i] == 2); 231 i += 1; 232 try expect(v[i] == 3); 233 } 234 }; 235 236 try S.doTheTest(); 237 comptime try S.doTheTest(); 238} 239 240test "store vector elements via runtime index" { 241 const S = struct { 242 fn doTheTest() !void { 243 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined }; 244 var i: u32 = 2; 245 v[i] = 1; 246 try expect(v[1] == 5); 247 try expect(v[2] == 1); 248 i += 1; 249 v[i] = -364; 250 try expect(-364 == v[3]); 251 } 252 }; 253 254 try S.doTheTest(); 255 comptime try S.doTheTest(); 256} 257 258test "initialize vector which is a struct field" { 259 const Vec4Obj = struct { 260 data: Vector(4, f32), 261 }; 262 263 const S = struct { 264 fn doTheTest() !void { 265 var foo = Vec4Obj{ 266 .data = [_]f32{ 1, 2, 3, 4 }, 267 }; 268 _ = foo; 269 } 270 }; 271 try S.doTheTest(); 272 comptime try S.doTheTest(); 273} 274 275test "vector comparison operators" { 276 const S = struct { 277 fn doTheTest() !void { 278 { 279 const v1: Vector(4, bool) = [_]bool{ true, false, true, false }; 280 const v2: Vector(4, bool) = [_]bool{ false, true, false, true }; 281 try expectEqual(@splat(4, true), v1 == v1); 282 try expectEqual(@splat(4, false), v1 == v2); 283 try expectEqual(@splat(4, true), v1 != v2); 284 try expectEqual(@splat(4, false), v2 != v2); 285 } 286 { 287 const v1 = @splat(4, @as(u32, 0xc0ffeeee)); 288 const v2: Vector(4, c_uint) = v1; 289 const v3 = @splat(4, @as(u32, 0xdeadbeef)); 290 try expectEqual(@splat(4, true), v1 == v2); 291 try expectEqual(@splat(4, false), v1 == v3); 292 try expectEqual(@splat(4, true), v1 != v3); 293 try expectEqual(@splat(4, false), v1 != v2); 294 } 295 { 296 // Comptime-known LHS/RHS 297 var v1: @Vector(4, u32) = [_]u32{ 2, 1, 2, 1 }; 298 const v2 = @splat(4, @as(u32, 2)); 299 const v3: @Vector(4, bool) = [_]bool{ true, false, true, false }; 300 try expectEqual(v3, v1 == v2); 301 try expectEqual(v3, v2 == v1); 302 } 303 } 304 }; 305 try S.doTheTest(); 306 comptime try S.doTheTest(); 307} 308 309test "vector division operators" { 310 const S = struct { 311 fn doTheTestDiv(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void { 312 if (!comptime std.meta.trait.isSignedInt(T)) { 313 const d0 = x / y; 314 for (@as([4]T, d0)) |v, i| { 315 try expectEqual(x[i] / y[i], v); 316 } 317 } 318 const d1 = @divExact(x, y); 319 for (@as([4]T, d1)) |v, i| { 320 try expectEqual(@divExact(x[i], y[i]), v); 321 } 322 const d2 = @divFloor(x, y); 323 for (@as([4]T, d2)) |v, i| { 324 try expectEqual(@divFloor(x[i], y[i]), v); 325 } 326 const d3 = @divTrunc(x, y); 327 for (@as([4]T, d3)) |v, i| { 328 try expectEqual(@divTrunc(x[i], y[i]), v); 329 } 330 } 331 332 fn doTheTestMod(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void { 333 if ((!comptime std.meta.trait.isSignedInt(T)) and @typeInfo(T) != .Float) { 334 const r0 = x % y; 335 for (@as([4]T, r0)) |v, i| { 336 try expectEqual(x[i] % y[i], v); 337 } 338 } 339 const r1 = @mod(x, y); 340 for (@as([4]T, r1)) |v, i| { 341 try expectEqual(@mod(x[i], y[i]), v); 342 } 343 const r2 = @rem(x, y); 344 for (@as([4]T, r2)) |v, i| { 345 try expectEqual(@rem(x[i], y[i]), v); 346 } 347 } 348 349 fn doTheTest() !void { 350 // https://github.com/ziglang/zig/issues/4952 351 if (builtin.target.os.tag != .windows) { 352 try doTheTestDiv(f16, [4]f16{ 4.0, -4.0, 4.0, -4.0 }, [4]f16{ 1.0, 2.0, -1.0, -2.0 }); 353 } 354 355 try doTheTestDiv(f32, [4]f32{ 4.0, -4.0, 4.0, -4.0 }, [4]f32{ 1.0, 2.0, -1.0, -2.0 }); 356 try doTheTestDiv(f64, [4]f64{ 4.0, -4.0, 4.0, -4.0 }, [4]f64{ 1.0, 2.0, -1.0, -2.0 }); 357 358 // https://github.com/ziglang/zig/issues/4952 359 if (builtin.target.os.tag != .windows) { 360 try doTheTestMod(f16, [4]f16{ 4.0, -4.0, 4.0, -4.0 }, [4]f16{ 1.0, 2.0, 0.5, 3.0 }); 361 } 362 try doTheTestMod(f32, [4]f32{ 4.0, -4.0, 4.0, -4.0 }, [4]f32{ 1.0, 2.0, 0.5, 3.0 }); 363 try doTheTestMod(f64, [4]f64{ 4.0, -4.0, 4.0, -4.0 }, [4]f64{ 1.0, 2.0, 0.5, 3.0 }); 364 365 try doTheTestDiv(i8, [4]i8{ 4, -4, 4, -4 }, [4]i8{ 1, 2, -1, -2 }); 366 try doTheTestDiv(i16, [4]i16{ 4, -4, 4, -4 }, [4]i16{ 1, 2, -1, -2 }); 367 try doTheTestDiv(i32, [4]i32{ 4, -4, 4, -4 }, [4]i32{ 1, 2, -1, -2 }); 368 try doTheTestDiv(i64, [4]i64{ 4, -4, 4, -4 }, [4]i64{ 1, 2, -1, -2 }); 369 370 try doTheTestMod(i8, [4]i8{ 4, -4, 4, -4 }, [4]i8{ 1, 2, 4, 8 }); 371 try doTheTestMod(i16, [4]i16{ 4, -4, 4, -4 }, [4]i16{ 1, 2, 4, 8 }); 372 try doTheTestMod(i32, [4]i32{ 4, -4, 4, -4 }, [4]i32{ 1, 2, 4, 8 }); 373 try doTheTestMod(i64, [4]i64{ 4, -4, 4, -4 }, [4]i64{ 1, 2, 4, 8 }); 374 375 try doTheTestDiv(u8, [4]u8{ 1, 2, 4, 8 }, [4]u8{ 1, 1, 2, 4 }); 376 try doTheTestDiv(u16, [4]u16{ 1, 2, 4, 8 }, [4]u16{ 1, 1, 2, 4 }); 377 try doTheTestDiv(u32, [4]u32{ 1, 2, 4, 8 }, [4]u32{ 1, 1, 2, 4 }); 378 try doTheTestDiv(u64, [4]u64{ 1, 2, 4, 8 }, [4]u64{ 1, 1, 2, 4 }); 379 380 try doTheTestMod(u8, [4]u8{ 1, 2, 4, 8 }, [4]u8{ 1, 1, 2, 4 }); 381 try doTheTestMod(u16, [4]u16{ 1, 2, 4, 8 }, [4]u16{ 1, 1, 2, 4 }); 382 try doTheTestMod(u32, [4]u32{ 1, 2, 4, 8 }, [4]u32{ 1, 1, 2, 4 }); 383 try doTheTestMod(u64, [4]u64{ 1, 2, 4, 8 }, [4]u64{ 1, 1, 2, 4 }); 384 } 385 }; 386 387 try S.doTheTest(); 388 comptime try S.doTheTest(); 389} 390 391test "vector bitwise not operator" { 392 const S = struct { 393 fn doTheTestNot(comptime T: type, x: Vector(4, T)) !void { 394 var y = ~x; 395 for (@as([4]T, y)) |v, i| { 396 try expectEqual(~x[i], v); 397 } 398 } 399 fn doTheTest() !void { 400 try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 }); 401 try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 }); 402 try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 }); 403 try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 }); 404 405 try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 }); 406 try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 }); 407 try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 }); 408 try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 }); 409 } 410 }; 411 412 try S.doTheTest(); 413 comptime try S.doTheTest(); 414} 415 416test "vector shift operators" { 417 const S = struct { 418 fn doTheTestShift(x: anytype, y: anytype) !void { 419 const N = @typeInfo(@TypeOf(x)).Array.len; 420 const TX = @typeInfo(@TypeOf(x)).Array.child; 421 const TY = @typeInfo(@TypeOf(y)).Array.child; 422 423 var xv = @as(Vector(N, TX), x); 424 var yv = @as(Vector(N, TY), y); 425 426 var z0 = xv >> yv; 427 for (@as([N]TX, z0)) |v, i| { 428 try expectEqual(x[i] >> y[i], v); 429 } 430 var z1 = xv << yv; 431 for (@as([N]TX, z1)) |v, i| { 432 try expectEqual(x[i] << y[i], v); 433 } 434 } 435 fn doTheTestShiftExact(x: anytype, y: anytype, dir: enum { Left, Right }) !void { 436 const N = @typeInfo(@TypeOf(x)).Array.len; 437 const TX = @typeInfo(@TypeOf(x)).Array.child; 438 const TY = @typeInfo(@TypeOf(y)).Array.child; 439 440 var xv = @as(Vector(N, TX), x); 441 var yv = @as(Vector(N, TY), y); 442 443 var z = if (dir == .Left) @shlExact(xv, yv) else @shrExact(xv, yv); 444 for (@as([N]TX, z)) |v, i| { 445 const check = if (dir == .Left) x[i] << y[i] else x[i] >> y[i]; 446 try expectEqual(check, v); 447 } 448 } 449 fn doTheTest() !void { 450 try doTheTestShift([_]u8{ 0, 2, 4, math.maxInt(u8) }, [_]u3{ 2, 0, 2, 7 }); 451 try doTheTestShift([_]u16{ 0, 2, 4, math.maxInt(u16) }, [_]u4{ 2, 0, 2, 15 }); 452 try doTheTestShift([_]u24{ 0, 2, 4, math.maxInt(u24) }, [_]u5{ 2, 0, 2, 23 }); 453 try doTheTestShift([_]u32{ 0, 2, 4, math.maxInt(u32) }, [_]u5{ 2, 0, 2, 31 }); 454 try doTheTestShift([_]u64{ 0xfe, math.maxInt(u64) }, [_]u6{ 0, 63 }); 455 456 try doTheTestShift([_]i8{ 0, 2, 4, math.maxInt(i8) }, [_]u3{ 2, 0, 2, 7 }); 457 try doTheTestShift([_]i16{ 0, 2, 4, math.maxInt(i16) }, [_]u4{ 2, 0, 2, 7 }); 458 try doTheTestShift([_]i24{ 0, 2, 4, math.maxInt(i24) }, [_]u5{ 2, 0, 2, 7 }); 459 try doTheTestShift([_]i32{ 0, 2, 4, math.maxInt(i32) }, [_]u5{ 2, 0, 2, 7 }); 460 try doTheTestShift([_]i64{ 0xfe, math.maxInt(i64) }, [_]u6{ 0, 63 }); 461 462 try doTheTestShiftExact([_]u8{ 0, 1, 1 << 7, math.maxInt(u8) ^ 1 }, [_]u3{ 4, 0, 7, 1 }, .Right); 463 try doTheTestShiftExact([_]u16{ 0, 1, 1 << 15, math.maxInt(u16) ^ 1 }, [_]u4{ 4, 0, 15, 1 }, .Right); 464 try doTheTestShiftExact([_]u24{ 0, 1, 1 << 23, math.maxInt(u24) ^ 1 }, [_]u5{ 4, 0, 23, 1 }, .Right); 465 try doTheTestShiftExact([_]u32{ 0, 1, 1 << 31, math.maxInt(u32) ^ 1 }, [_]u5{ 4, 0, 31, 1 }, .Right); 466 try doTheTestShiftExact([_]u64{ 1 << 63, 1 }, [_]u6{ 63, 0 }, .Right); 467 468 try doTheTestShiftExact([_]u8{ 0, 1, 1, math.maxInt(u8) ^ (1 << 7) }, [_]u3{ 4, 0, 7, 1 }, .Left); 469 try doTheTestShiftExact([_]u16{ 0, 1, 1, math.maxInt(u16) ^ (1 << 15) }, [_]u4{ 4, 0, 15, 1 }, .Left); 470 try doTheTestShiftExact([_]u24{ 0, 1, 1, math.maxInt(u24) ^ (1 << 23) }, [_]u5{ 4, 0, 23, 1 }, .Left); 471 try doTheTestShiftExact([_]u32{ 0, 1, 1, math.maxInt(u32) ^ (1 << 31) }, [_]u5{ 4, 0, 31, 1 }, .Left); 472 try doTheTestShiftExact([_]u64{ 1 << 63, 1 }, [_]u6{ 0, 63 }, .Left); 473 } 474 }; 475 476 switch (builtin.target.cpu.arch) { 477 .i386, 478 .aarch64, 479 .aarch64_be, 480 .aarch64_32, 481 .arm, 482 .armeb, 483 .thumb, 484 .thumbeb, 485 .mips, 486 .mipsel, 487 .mips64, 488 .mips64el, 489 .riscv64, 490 .sparcv9, 491 => { 492 // LLVM miscompiles on this architecture 493 // https://github.com/ziglang/zig/issues/4951 494 return error.SkipZigTest; 495 }, 496 else => {}, 497 } 498 499 try S.doTheTest(); 500 comptime try S.doTheTest(); 501} 502 503test "vector reduce operation" { 504 const S = struct { 505 fn doTheTestReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void { 506 const N = @typeInfo(@TypeOf(x)).Array.len; 507 const TX = @typeInfo(@TypeOf(x)).Array.child; 508 509 var r = @reduce(op, @as(Vector(N, TX), x)); 510 switch (@typeInfo(TX)) { 511 .Int, .Bool => try expectEqual(expected, r), 512 .Float => { 513 const expected_nan = math.isNan(expected); 514 const got_nan = math.isNan(r); 515 516 if (expected_nan and got_nan) { 517 // Do this check explicitly as two NaN values are never 518 // equal. 519 } else { 520 try expectApproxEqRel(expected, r, math.sqrt(math.epsilon(TX))); 521 } 522 }, 523 else => unreachable, 524 } 525 } 526 fn doTheTest() !void { 527 try doTheTestReduce(.Add, [4]i16{ -9, -99, -999, -9999 }, @as(i32, -11106)); 528 try doTheTestReduce(.Add, [4]u16{ 9, 99, 999, 9999 }, @as(u32, 11106)); 529 try doTheTestReduce(.Add, [4]i32{ -9, -99, -999, -9999 }, @as(i32, -11106)); 530 try doTheTestReduce(.Add, [4]u32{ 9, 99, 999, 9999 }, @as(u32, 11106)); 531 try doTheTestReduce(.Add, [4]i64{ -9, -99, -999, -9999 }, @as(i64, -11106)); 532 try doTheTestReduce(.Add, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 11106)); 533 try doTheTestReduce(.Add, [4]i128{ -9, -99, -999, -9999 }, @as(i128, -11106)); 534 try doTheTestReduce(.Add, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 11106)); 535 try doTheTestReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9)); 536 try doTheTestReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9)); 537 try doTheTestReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9)); 538 539 try doTheTestReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false)); 540 try doTheTestReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0)); 541 try doTheTestReduce(.And, [4]u16{ 0xffff, 0xff55, 0xaaff, 0x1010 }, @as(u16, 0x10)); 542 try doTheTestReduce(.And, [4]u32{ 0xffffffff, 0xffff5555, 0xaaaaffff, 0x10101010 }, @as(u32, 0x1010)); 543 try doTheTestReduce(.And, [4]u64{ 0xffffffff, 0xffff5555, 0xaaaaffff, 0x10101010 }, @as(u64, 0x1010)); 544 545 try doTheTestReduce(.Min, [4]i16{ -1, 2, 3, 4 }, @as(i16, -1)); 546 try doTheTestReduce(.Min, [4]u16{ 1, 2, 3, 4 }, @as(u16, 1)); 547 try doTheTestReduce(.Min, [4]i32{ 1234567, -386, 0, 3 }, @as(i32, -386)); 548 try doTheTestReduce(.Min, [4]u32{ 99, 9999, 9, 99999 }, @as(u32, 9)); 549 550 // LLVM 11 ERROR: Cannot select type 551 // https://github.com/ziglang/zig/issues/7138 552 if (builtin.target.cpu.arch != .aarch64) { 553 try doTheTestReduce(.Min, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, -386)); 554 try doTheTestReduce(.Min, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 9)); 555 } 556 557 try doTheTestReduce(.Min, [4]i128{ 1234567, -386, 0, 3 }, @as(i128, -386)); 558 try doTheTestReduce(.Min, [4]u128{ 99, 9999, 9, 99999 }, @as(u128, 9)); 559 try doTheTestReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0)); 560 try doTheTestReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0)); 561 try doTheTestReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0)); 562 563 try doTheTestReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4)); 564 try doTheTestReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4)); 565 try doTheTestReduce(.Max, [4]i32{ 1234567, -386, 0, 3 }, @as(i32, 1234567)); 566 try doTheTestReduce(.Max, [4]u32{ 99, 9999, 9, 99999 }, @as(u32, 99999)); 567 568 // LLVM 11 ERROR: Cannot select type 569 // https://github.com/ziglang/zig/issues/7138 570 if (builtin.target.cpu.arch != .aarch64) { 571 try doTheTestReduce(.Max, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, 1234567)); 572 try doTheTestReduce(.Max, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 99999)); 573 } 574 575 try doTheTestReduce(.Max, [4]i128{ 1234567, -386, 0, 3 }, @as(i128, 1234567)); 576 try doTheTestReduce(.Max, [4]u128{ 99, 9999, 9, 99999 }, @as(u128, 99999)); 577 try doTheTestReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9)); 578 try doTheTestReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9)); 579 try doTheTestReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9)); 580 581 try doTheTestReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24)); 582 try doTheTestReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24)); 583 try doTheTestReduce(.Mul, [4]i32{ -9, -99, -999, 999 }, @as(i32, -889218891)); 584 try doTheTestReduce(.Mul, [4]u32{ 1, 2, 3, 4 }, @as(u32, 24)); 585 try doTheTestReduce(.Mul, [4]i64{ 9, 99, 999, 9999 }, @as(i64, 8900199891)); 586 try doTheTestReduce(.Mul, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 8900199891)); 587 try doTheTestReduce(.Mul, [4]i128{ -9, -99, -999, 9999 }, @as(i128, -8900199891)); 588 try doTheTestReduce(.Mul, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 8900199891)); 589 try doTheTestReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7)); 590 try doTheTestReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7)); 591 try doTheTestReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7)); 592 593 try doTheTestReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true)); 594 try doTheTestReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1)); 595 try doTheTestReduce(.Or, [4]u16{ 0xff00, 0xff00, 0xf0, 0xf }, ~@as(u16, 0)); 596 try doTheTestReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0)); 597 try doTheTestReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff)); 598 try doTheTestReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff)); 599 600 try doTheTestReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true)); 601 try doTheTestReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1)); 602 try doTheTestReduce(.Xor, [4]u16{ 0x0000, 0x3333, 0x8888, 0x4444 }, ~@as(u16, 0)); 603 try doTheTestReduce(.Xor, [4]u32{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, ~@as(u32, 0)); 604 try doTheTestReduce(.Xor, [4]u64{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, @as(u64, 0xffffffff)); 605 try doTheTestReduce(.Xor, [4]u128{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, @as(u128, 0xffffffff)); 606 607 // Test the reduction on vectors containing NaNs. 608 const f16_nan = math.nan(f16); 609 const f32_nan = math.nan(f32); 610 const f64_nan = math.nan(f64); 611 612 try doTheTestReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); 613 try doTheTestReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); 614 try doTheTestReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan); 615 616 // LLVM 11 ERROR: Cannot select type 617 // https://github.com/ziglang/zig/issues/7138 618 if (false) { 619 try doTheTestReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); 620 try doTheTestReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); 621 try doTheTestReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan); 622 623 try doTheTestReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); 624 try doTheTestReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); 625 try doTheTestReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan); 626 } 627 628 try doTheTestReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); 629 try doTheTestReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); 630 try doTheTestReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan); 631 } 632 }; 633 634 try S.doTheTest(); 635 comptime try S.doTheTest(); 636} 637 638test "mask parameter of @shuffle is comptime scope" { 639 const __v4hi = std.meta.Vector(4, i16); 640 var v4_a = __v4hi{ 0, 0, 0, 0 }; 641 var v4_b = __v4hi{ 0, 0, 0, 0 }; 642 var shuffled: __v4hi = @shuffle(i16, v4_a, v4_b, std.meta.Vector(4, i32){ 643 std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), 644 std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), 645 std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), 646 std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), 647 }); 648 _ = shuffled; 649} 650 651test "saturating add" { 652 const S = struct { 653 fn doTheTest() !void { 654 const u8x3 = std.meta.Vector(3, u8); 655 try expectEqual(u8x3{ 255, 255, 255 }, (u8x3{ 255, 254, 1 } +| u8x3{ 1, 2, 255 })); 656 const i8x3 = std.meta.Vector(3, i8); 657 try expectEqual(i8x3{ 127, 127, 127 }, (i8x3{ 127, 126, 1 } +| i8x3{ 1, 2, 127 })); 658 } 659 }; 660 try S.doTheTest(); 661 comptime try S.doTheTest(); 662} 663 664test "saturating subtraction" { 665 const S = struct { 666 fn doTheTest() !void { 667 const u8x3 = std.meta.Vector(3, u8); 668 try expectEqual(u8x3{ 0, 0, 0 }, (u8x3{ 0, 0, 0 } -| u8x3{ 255, 255, 255 })); 669 } 670 }; 671 try S.doTheTest(); 672 comptime try S.doTheTest(); 673} 674 675test "saturating multiplication" { 676 // TODO: once #9660 has been solved, remove this line 677 if (builtin.target.cpu.arch == .wasm32) return error.SkipZigTest; 678 679 const S = struct { 680 fn doTheTest() !void { 681 const u8x3 = std.meta.Vector(3, u8); 682 try expectEqual(u8x3{ 255, 255, 255 }, (u8x3{ 2, 2, 2 } *| u8x3{ 255, 255, 255 })); 683 } 684 }; 685 686 try S.doTheTest(); 687 comptime try S.doTheTest(); 688} 689 690test "saturating shift-left" { 691 const S = struct { 692 fn doTheTest() !void { 693 const u8x3 = std.meta.Vector(3, u8); 694 try expectEqual(u8x3{ 255, 255, 255 }, (u8x3{ 255, 255, 255 } <<| u8x3{ 1, 1, 1 })); 695 } 696 }; 697 try S.doTheTest(); 698 comptime try S.doTheTest(); 699} 700