Commit b463e429b8

antlilja <liljaanton2001@gmail.com>
2023-07-06 19:48:42
Remove len parameter from splat in standard lib
1 parent 4bce7b1
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);
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" {
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)),
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);
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));
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));
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
     {