diff --git a/lib/std/http/protocol.zig b/lib/std/http/protocol.zig index 604267bf16..05b8f51b5e 100644 --- a/lib/std/http/protocol.zig +++ b/lib/std/http/protocol.zig @@ -182,8 +182,8 @@ pub const HeadersParser = struct { const chunk = bytes[index..][0..vector_len]; const v: Vector = chunk.*; - const matches_r = @as(BitVector, @bitCast(v == @splat(vector_len, @as(u8, '\r')))); - const matches_n = @as(BitVector, @bitCast(v == @splat(vector_len, @as(u8, '\n')))); + const matches_r = @as(BitVector, @bitCast(v == @as(Vector, @splat('\r')))); + const matches_n = @as(BitVector, @bitCast(v == @as(Vector, @splat('\n')))); const matches_or: SizeVector = matches_r | matches_n; const matches = @reduce(.Add, matches_or); diff --git a/lib/std/json/stringify_test.zig b/lib/std/json/stringify_test.zig index 19f8f06e5e..cb258eb24c 100644 --- a/lib/std/json/stringify_test.zig +++ b/lib/std/json/stringify_test.zig @@ -197,7 +197,7 @@ test "stringify struct with custom stringifier" { } test "stringify vector" { - try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{}); + try teststringify("[1,1]", @as(@Vector(2, u32), @splat(1)), StringifyOptions{}); } test "stringify tuple" { diff --git a/lib/std/math.zig b/lib/std/math.zig index a92ebd4890..25ecd779e9 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -507,8 +507,8 @@ pub fn shl(comptime T: type, a: T, shift_amt: anytype) T { if (@typeInfo(T) == .Vector) { const C = @typeInfo(T).Vector.child; const len = @typeInfo(T).Vector.len; - if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(len, @as(C, 0)); - break :blk @splat(len, @as(Log2Int(C), @intCast(abs_shift_amt))); + if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(0); + break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt)))); } else { if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0; break :blk @as(Log2Int(T), @intCast(abs_shift_amt)); @@ -551,8 +551,8 @@ pub fn shr(comptime T: type, a: T, shift_amt: anytype) T { if (@typeInfo(T) == .Vector) { const C = @typeInfo(T).Vector.child; const len = @typeInfo(T).Vector.len; - if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(len, @as(C, 0)); - break :blk @splat(len, @as(Log2Int(C), @intCast(abs_shift_amt))); + if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(0); + break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt)))); } else { if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0; break :blk @as(Log2Int(T), @intCast(abs_shift_amt)); @@ -597,7 +597,7 @@ pub fn rotr(comptime T: type, x: T, r: anytype) T { @compileError("cannot rotate signed integers"); } const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits))); - return (x >> @splat(@typeInfo(T).Vector.len, ar)) | (x << @splat(@typeInfo(T).Vector.len, 1 + ~ar)); + return (x >> @splat(ar)) | (x << @splat(1 + ~ar)); } else if (@typeInfo(T).Int.signedness == .signed) { @compileError("cannot rotate signed integer"); } else { @@ -641,7 +641,7 @@ pub fn rotl(comptime T: type, x: T, r: anytype) T { @compileError("cannot rotate signed integers"); } const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits))); - return (x << @splat(@typeInfo(T).Vector.len, ar)) | (x >> @splat(@typeInfo(T).Vector.len, 1 +% ~ar)); + return (x << @splat(ar)) | (x >> @splat(1 +% ~ar)); } else if (@typeInfo(T).Int.signedness == .signed) { @compileError("cannot rotate signed integer"); } else { @@ -794,10 +794,10 @@ pub fn absInt(x: anytype) !@TypeOf(x) { switch (@typeInfo(vinfo.child)) { .Int => |info| { comptime assert(info.signedness == .signed); // must pass a signed integer to absInt - if (@reduce(.Or, x == @splat(vinfo.len, @as(vinfo.child, minInt(vinfo.child))))) { + if (@reduce(.Or, x == @as(T, @splat(minInt(vinfo.child))))) { return error.Overflow; } - const zero = @splat(vinfo.len, @as(vinfo.child, 0)); + const zero: T = @splat(0); break :blk @select(vinfo.child, x > zero, x, -x); }, else => @compileError("Expected vector of ints, found " ++ @typeName(T)), @@ -1368,9 +1368,9 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { switch (@typeInfo(Type)) { .Float, .ComptimeFloat => assert(t >= 0 and t <= 1), - .Vector => |vector| { - const lower_bound = @reduce(.And, t >= @splat(vector.len, @as(vector.child, 0))); - const upper_bound = @reduce(.And, t <= @splat(vector.len, @as(vector.child, 1))); + .Vector => { + const lower_bound = @reduce(.And, t >= @as(Type, @splat(0))); + const upper_bound = @reduce(.And, t <= @as(Type, @splat(1))); assert(lower_bound and upper_bound); }, else => comptime unreachable, @@ -1392,14 +1392,24 @@ test "lerp" { try testing.expectEqual(@as(f32, 1.0), lerp(@as(f32, 1.0e7), 1.0, 1.0)); try testing.expectEqual(@as(f64, 1.0), lerp(@as(f64, 1.0e15), 1.0, 1.0)); - try testing.expectEqual( - lerp(@splat(3, @as(f32, 0)), @splat(3, @as(f32, 50)), @splat(3, @as(f32, 0.5))), - @Vector(3, f32){ 25, 25, 25 }, - ); - try testing.expectEqual( - lerp(@splat(3, @as(f64, 50)), @splat(3, @as(f64, 100)), @splat(3, @as(f64, 0.5))), - @Vector(3, f64){ 75, 75, 75 }, - ); + { + const a: @Vector(3, f32) = @splat(0); + const b: @Vector(3, f32) = @splat(50); + const t: @Vector(3, f32) = @splat(0.5); + try testing.expectEqual( + lerp(a, b, t), + @Vector(3, f32){ 25, 25, 25 }, + ); + } + { + const a: @Vector(3, f64) = @splat(50); + const b: @Vector(3, f64) = @splat(100); + const t: @Vector(3, f64) = @splat(0.5); + try testing.expectEqual( + lerp(a, b, t), + @Vector(3, f64){ 75, 75, 75 }, + ); + } } /// Returns the maximum value of integer type T. @@ -1719,8 +1729,8 @@ pub inline fn sign(i: anytype) @TypeOf(i) { .Vector => |vinfo| blk: { switch (@typeInfo(vinfo.child)) { .Int, .Float => { - const zero = @splat(vinfo.len, @as(vinfo.child, 0)); - const one = @splat(vinfo.len, @as(vinfo.child, 1)); + const zero: T = @splat(0); + const one: T = @splat(1); break :blk @select(vinfo.child, i > zero, one, zero) - @select(vinfo.child, i < zero, one, zero); }, else => @compileError("Expected vector of ints or floats, found " ++ @typeName(T)), diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 86f793ee56..4e6dba3268 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -289,7 +289,7 @@ pub fn zeroes(comptime T: type) T { return [_]info.child{zeroes(info.child)} ** info.len; }, .Vector => |info| { - return @splat(info.len, zeroes(info.child)); + return @splat(zeroes(info.child)); }, .Union => |info| { if (comptime meta.containerLayout(T) == .Extern) { @@ -393,9 +393,9 @@ test "zeroes" { for (b.array) |e| { try testing.expectEqual(@as(u32, 0), e); } - try testing.expectEqual(@splat(2, @as(u32, 0)), b.vector_u32); - try testing.expectEqual(@splat(2, @as(f32, 0.0)), b.vector_f32); - try testing.expectEqual(@splat(2, @as(bool, false)), b.vector_bool); + try testing.expectEqual(@as(@TypeOf(b.vector_u32), @splat(0)), b.vector_u32); + try testing.expectEqual(@as(@TypeOf(b.vector_f32), @splat(0.0)), b.vector_f32); + try testing.expectEqual(@as(@TypeOf(b.vector_bool), @splat(false)), b.vector_bool); try testing.expectEqual(@as(?u8, null), b.optional_int); for (b.sentinel) |e| { try testing.expectEqual(@as(u8, 0), e); diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 6c0f1a47a4..f1329134a0 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -860,9 +860,10 @@ test "std.meta.eql" { try testing.expect(eql(EU.tst(false), EU.tst(false))); try testing.expect(!eql(EU.tst(false), EU.tst(true))); - var v1 = @splat(4, @as(u32, 1)); - var v2 = @splat(4, @as(u32, 1)); - var v3 = @splat(4, @as(u32, 2)); + const V = @Vector(4, u32); + var v1: V = @splat(1); + var v2: V = @splat(1); + var v3: V = @splat(2); try testing.expect(eql(v1, v2)); try testing.expect(!eql(v1, v3)); diff --git a/lib/std/simd.zig b/lib/std/simd.zig index b3a50168ff..1a6b713148 100644 --- a/lib/std/simd.zig +++ b/lib/std/simd.zig @@ -107,7 +107,7 @@ pub inline fn iota(comptime T: type, comptime len: usize) @Vector(len, T) { pub fn repeat(comptime len: usize, vec: anytype) @Vector(len, std.meta.Child(@TypeOf(vec))) { const Child = std.meta.Child(@TypeOf(vec)); - return @shuffle(Child, vec, undefined, iota(i32, len) % @splat(len, @as(i32, @intCast(vectorLength(@TypeOf(vec)))))); + return @shuffle(Child, vec, undefined, iota(i32, len) % @as(@Vector(len, i32), @splat(@intCast(vectorLength(@TypeOf(vec)))))); } /// Returns a vector containing all elements of the first vector at the lower indices followed by all elements of the second vector @@ -147,11 +147,12 @@ pub fn interlace(vecs: anytype) @Vector(vectorLength(@TypeOf(vecs[0])) * vecs.le const len = a_len + b_len; const indices = comptime blk: { + const Vi32 = @Vector(len, i32); const count_up = iota(i32, len); - const cycle = @divFloor(count_up, @splat(len, @as(i32, @intCast(vecs_arr.len)))); - const select_mask = repeat(len, join(@splat(a_vec_count, true), @splat(b_vec_count, false))); - const a_indices = count_up - cycle * @splat(len, @as(i32, @intCast(b_vec_count))); - const b_indices = shiftElementsRight(count_up - cycle * @splat(len, @as(i32, @intCast(a_vec_count))), a_vec_count, 0); + const cycle = @divFloor(count_up, @as(Vi32, @splat(@intCast(vecs_arr.len)))); + const select_mask = repeat(len, join(@as(@Vector(a_vec_count, bool), @splat(true)), @as(@Vector(b_vec_count, bool), @splat(false)))); + const a_indices = count_up - cycle * @as(Vi32, @splat(@intCast(b_vec_count))); + const b_indices = shiftElementsRight(count_up - cycle * @as(Vi32, @splat(@intCast(a_vec_count))), a_vec_count, 0); break :blk @select(i32, select_mask, a_indices, ~b_indices); }; @@ -174,7 +175,7 @@ pub fn deinterlace( comptime var i: usize = 0; // for-loops don't work for this, apparently. inline while (i < out.len) : (i += 1) { - const indices = comptime iota(i32, vec_len) * @splat(vec_len, @as(i32, @intCast(vec_count))) + @splat(vec_len, @as(i32, @intCast(i))); + const indices = comptime iota(i32, vec_len) * @as(@Vector(vec_len, i32), @splat(@intCast(vec_count))) + @as(@Vector(vec_len, i32), @splat(@intCast(i))); out[i] = @shuffle(Child, interlaced, undefined, indices); } @@ -191,7 +192,7 @@ pub fn extract( std.debug.assert(@as(comptime_int, @intCast(first)) + @as(comptime_int, @intCast(count)) <= len); - return @shuffle(Child, vec, undefined, iota(i32, count) + @splat(count, @as(i32, @intCast(first)))); + return @shuffle(Child, vec, undefined, iota(i32, count) + @as(@Vector(count, i32), @splat(@intCast(first)))); } test "vector patterns" { @@ -236,17 +237,18 @@ pub fn shiftElementsRight(vec: anytype, comptime amount: VectorCount(@TypeOf(vec // It may be possible to implement shifts and rotates with a runtime-friendly slice of two joined vectors, as the length of the // slice would be comptime-known. This would permit vector shifts and rotates by a non-comptime-known amount. // However, I am unsure whether compiler optimizations would handle that well enough on all platforms. - const len = vectorLength(@TypeOf(vec)); + const V = @TypeOf(vec); + const len = vectorLength(V); - return mergeShift(@splat(len, shift_in), vec, len - amount); + return mergeShift(@as(V, @splat(shift_in)), vec, len - amount); } /// Elements are shifted leftwards (towards lower indices). New elements are added to the right, and the leftmost elements are cut off /// so that no elements with indices below 0 remain. pub fn shiftElementsLeft(vec: anytype, comptime amount: VectorCount(@TypeOf(vec)), shift_in: std.meta.Child(@TypeOf(vec))) @TypeOf(vec) { - const len = vectorLength(@TypeOf(vec)); + const V = @TypeOf(vec); - return mergeShift(vec, @splat(len, shift_in), amount); + return mergeShift(vec, @as(V, @splat(shift_in)), amount); } /// Elements are shifted leftwards (towards lower indices). Elements that leave to the left will reappear to the right in the same order. @@ -263,7 +265,7 @@ pub fn reverseOrder(vec: anytype) @TypeOf(vec) { const Child = std.meta.Child(@TypeOf(vec)); const len = vectorLength(@TypeOf(vec)); - return @shuffle(Child, vec, undefined, @splat(len, @as(i32, @intCast(len)) - 1) - iota(i32, len)); + return @shuffle(Child, vec, undefined, @as(@Vector(len, i32), @splat(@as(i32, @intCast(len)) - 1)) - iota(i32, len)); } test "vector shifting" { @@ -283,7 +285,8 @@ pub fn firstTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) { if (!@reduce(.Or, vec)) { return null; } - const indices = @select(IndexInt, vec, iota(IndexInt, len), @splat(len, ~@as(IndexInt, 0))); + const all_max: @Vector(len, IndexInt) = @splat(~@as(IndexInt, 0)); + const indices = @select(IndexInt, vec, iota(IndexInt, len), all_max); return @reduce(.Min, indices); } @@ -294,7 +297,9 @@ pub fn lastTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) { if (!@reduce(.Or, vec)) { return null; } - const indices = @select(IndexInt, vec, iota(IndexInt, len), @splat(len, @as(IndexInt, 0))); + + const all_zeroes: @Vector(len, IndexInt) = @splat(0); + const indices = @select(IndexInt, vec, iota(IndexInt, len), all_zeroes); return @reduce(.Max, indices); } @@ -302,26 +307,29 @@ pub fn countTrues(vec: anytype) VectorCount(@TypeOf(vec)) { const len = vectorLength(@TypeOf(vec)); const CountIntType = VectorCount(@TypeOf(vec)); - const one_if_true = @select(CountIntType, vec, @splat(len, @as(CountIntType, 1)), @splat(len, @as(CountIntType, 0))); + const all_ones: @Vector(len, CountIntType) = @splat(1); + const all_zeroes: @Vector(len, CountIntType) = @splat(0); + + const one_if_true = @select(CountIntType, vec, all_ones, all_zeroes); return @reduce(.Add, one_if_true); } pub fn firstIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) { - const len = vectorLength(@TypeOf(vec)); + const V = @TypeOf(vec); - return firstTrue(vec == @splat(len, value)); + return firstTrue(vec == @as(V, @splat(value))); } pub fn lastIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) { - const len = vectorLength(@TypeOf(vec)); + const V = @TypeOf(vec); - return lastTrue(vec == @splat(len, value)); + return lastTrue(vec == @as(V, @splat(value))); } pub fn countElementsWithValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) VectorCount(@TypeOf(vec)) { - const len = vectorLength(@TypeOf(vec)); + const V = @TypeOf(vec); - return countTrues(vec == @splat(len, value)); + return countTrues(vec == @as(V, @splat(value))); } test "vector searching" { @@ -370,7 +378,6 @@ pub fn prefixScanWithFunc( pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: anytype) @TypeOf(vec) { const VecType = @TypeOf(vec); const Child = std.meta.Child(VecType); - const len = vectorLength(VecType); const identity = comptime switch (@typeInfo(Child)) { .Bool => switch (op) { @@ -397,8 +404,8 @@ pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: a const fn_container = struct { fn opFn(a: VecType, b: VecType) VecType { return if (Child == bool) switch (op) { - .And => @select(bool, a, b, @splat(len, false)), - .Or => @select(bool, a, @splat(len, true), b), + .And => @select(bool, a, b, @as(VecType, @splat(false))), + .Or => @select(bool, a, @as(VecType, @splat(true)), b), .Xor => a != b, else => unreachable, } else switch (op) { @@ -431,7 +438,9 @@ test "vector prefix scan" { const float_base = @Vector(4, f32){ 2, 0.5, -10, 6.54321 }; const bool_base = @Vector(4, bool){ true, false, true, false }; - try std.testing.expectEqual(iota(u8, 32) + @splat(32, @as(u8, 1)), prefixScan(.Add, 1, @splat(32, @as(u8, 1)))); + const ones: @Vector(32, u8) = @splat(1); + + try std.testing.expectEqual(iota(u8, 32) + ones, prefixScan(.Add, 1, ones)); try std.testing.expectEqual(@Vector(4, i32){ 11, 3, 1, 1 }, prefixScan(.And, 1, int_base)); try std.testing.expectEqual(@Vector(4, i32){ 11, 31, 31, -1 }, prefixScan(.Or, 1, int_base)); try std.testing.expectEqual(@Vector(4, i32){ 11, 28, 21, -2 }, prefixScan(.Xor, 1, int_base)); diff --git a/lib/std/testing.zig b/lib/std/testing.zig index ca83870f1e..6c3952cfd6 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -606,8 +606,8 @@ test "expectEqual nested array" { } test "expectEqual vector" { - var a = @splat(4, @as(u32, 4)); - var b = @splat(4, @as(u32, 4)); + var a: @Vector(4, u32) = @splat(4); + var b: @Vector(4, u32) = @splat(4); try expectEqual(a, b); } @@ -903,7 +903,7 @@ test "expectEqualDeep composite type" { try expectEqualDeep([_][]const u8{ "a", "b", "c" }, [_][]const u8{ "a", "b", "c" }); // vector - try expectEqualDeep(@splat(4, @as(u32, 4)), @splat(4, @as(u32, 4))); + try expectEqualDeep(@as(@Vector(4, u32), @splat(4)), @as(@Vector(4, u32), @splat(4))); // nested array {