| author | |
| committer | |
| log | b463e429b8e2b3d39592ff1c84bd886f46d21452 |
| tree | 61639aa39187571c23225d4e2fbf41c21fce7f22 |
| parent | 4bce7b1db964098e4a9163201fa3adcb26af6d97 |
7 files changed, 79 insertions(+), 59 deletions(-)
lib/std/http/protocol.zig+2-2| ... | @@ -182,8 +182,8 @@ pub const HeadersParser = struct { | ... | @@ -182,8 +182,8 @@ pub const HeadersParser = struct { |
| 182 | 182 | ||
| 183 | const chunk = bytes[index..][0..vector_len]; | 183 | const chunk = bytes[index..][0..vector_len]; |
| 184 | const v: Vector = chunk.*; | 184 | const v: Vector = chunk.*; |
| 185 | const matches_r = @as(BitVector, @bitCast(v == @splat(vector_len, @as(u8, '\r')))); | 185 | const matches_r = @as(BitVector, @bitCast(v == @as(Vector, @splat('\r')))); |
| 186 | const matches_n = @as(BitVector, @bitCast(v == @splat(vector_len, @as(u8, '\n')))); | 186 | const matches_n = @as(BitVector, @bitCast(v == @as(Vector, @splat('\n')))); |
| 187 | const matches_or: SizeVector = matches_r | matches_n; | 187 | const matches_or: SizeVector = matches_r | matches_n; |
| 188 | 188 | ||
| 189 | const matches = @reduce(.Add, matches_or); | 189 | const matches = @reduce(.Add, matches_or); |
lib/std/json/stringify_test.zig+1-1| ... | @@ -197,7 +197,7 @@ test "stringify struct with custom stringifier" { | ... | @@ -197,7 +197,7 @@ test "stringify struct with custom stringifier" { |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | test "stringify vector" { | 199 | test "stringify vector" { |
| 200 | try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{}); | 200 | try teststringify("[1,1]", @as(@Vector(2, u32), @splat(1)), StringifyOptions{}); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | test "stringify tuple" { | 203 | test "stringify tuple" { |
lib/std/math.zig+31-21| ... | @@ -507,8 +507,8 @@ pub fn shl(comptime T: type, a: T, shift_amt: anytype) T { | ... | @@ -507,8 +507,8 @@ pub fn shl(comptime T: type, a: T, shift_amt: anytype) T { |
| 507 | if (@typeInfo(T) == .Vector) { | 507 | if (@typeInfo(T) == .Vector) { |
| 508 | const C = @typeInfo(T).Vector.child; | 508 | const C = @typeInfo(T).Vector.child; |
| 509 | const len = @typeInfo(T).Vector.len; | 509 | const len = @typeInfo(T).Vector.len; |
| 510 | if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(len, @as(C, 0)); | 510 | if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(0); |
| 511 | break :blk @splat(len, @as(Log2Int(C), @intCast(abs_shift_amt))); | 511 | break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt)))); |
| 512 | } else { | 512 | } else { |
| 513 | if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0; | 513 | if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0; |
| 514 | break :blk @as(Log2Int(T), @intCast(abs_shift_amt)); | 514 | 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 { | ... | @@ -551,8 +551,8 @@ pub fn shr(comptime T: type, a: T, shift_amt: anytype) T { |
| 551 | if (@typeInfo(T) == .Vector) { | 551 | if (@typeInfo(T) == .Vector) { |
| 552 | const C = @typeInfo(T).Vector.child; | 552 | const C = @typeInfo(T).Vector.child; |
| 553 | const len = @typeInfo(T).Vector.len; | 553 | const len = @typeInfo(T).Vector.len; |
| 554 | if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(len, @as(C, 0)); | 554 | if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(0); |
| 555 | break :blk @splat(len, @as(Log2Int(C), @intCast(abs_shift_amt))); | 555 | break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt)))); |
| 556 | } else { | 556 | } else { |
| 557 | if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0; | 557 | if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0; |
| 558 | break :blk @as(Log2Int(T), @intCast(abs_shift_amt)); | 558 | break :blk @as(Log2Int(T), @intCast(abs_shift_amt)); |
| ... | @@ -597,7 +597,7 @@ pub fn rotr(comptime T: type, x: T, r: anytype) T { | ... | @@ -597,7 +597,7 @@ pub fn rotr(comptime T: type, x: T, r: anytype) T { |
| 597 | @compileError("cannot rotate signed integers"); | 597 | @compileError("cannot rotate signed integers"); |
| 598 | } | 598 | } |
| 599 | const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits))); | 599 | const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits))); |
| 600 | return (x >> @splat(@typeInfo(T).Vector.len, ar)) | (x << @splat(@typeInfo(T).Vector.len, 1 + ~ar)); | 600 | return (x >> @splat(ar)) | (x << @splat(1 + ~ar)); |
| 601 | } else if (@typeInfo(T).Int.signedness == .signed) { | 601 | } else if (@typeInfo(T).Int.signedness == .signed) { |
| 602 | @compileError("cannot rotate signed integer"); | 602 | @compileError("cannot rotate signed integer"); |
| 603 | } else { | 603 | } else { |
| ... | @@ -641,7 +641,7 @@ pub fn rotl(comptime T: type, x: T, r: anytype) T { | ... | @@ -641,7 +641,7 @@ pub fn rotl(comptime T: type, x: T, r: anytype) T { |
| 641 | @compileError("cannot rotate signed integers"); | 641 | @compileError("cannot rotate signed integers"); |
| 642 | } | 642 | } |
| 643 | const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits))); | 643 | const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits))); |
| 644 | return (x << @splat(@typeInfo(T).Vector.len, ar)) | (x >> @splat(@typeInfo(T).Vector.len, 1 +% ~ar)); | 644 | return (x << @splat(ar)) | (x >> @splat(1 +% ~ar)); |
| 645 | } else if (@typeInfo(T).Int.signedness == .signed) { | 645 | } else if (@typeInfo(T).Int.signedness == .signed) { |
| 646 | @compileError("cannot rotate signed integer"); | 646 | @compileError("cannot rotate signed integer"); |
| 647 | } else { | 647 | } else { |
| ... | @@ -794,10 +794,10 @@ pub fn absInt(x: anytype) !@TypeOf(x) { | ... | @@ -794,10 +794,10 @@ pub fn absInt(x: anytype) !@TypeOf(x) { |
| 794 | switch (@typeInfo(vinfo.child)) { | 794 | switch (@typeInfo(vinfo.child)) { |
| 795 | .Int => |info| { | 795 | .Int => |info| { |
| 796 | comptime assert(info.signedness == .signed); // must pass a signed integer to absInt | 796 | comptime assert(info.signedness == .signed); // must pass a signed integer to absInt |
| 797 | if (@reduce(.Or, x == @splat(vinfo.len, @as(vinfo.child, minInt(vinfo.child))))) { | 797 | if (@reduce(.Or, x == @as(T, @splat(minInt(vinfo.child))))) { |
| 798 | return error.Overflow; | 798 | return error.Overflow; |
| 799 | } | 799 | } |
| 800 | const zero = @splat(vinfo.len, @as(vinfo.child, 0)); | 800 | const zero: T = @splat(0); |
| 801 | break :blk @select(vinfo.child, x > zero, x, -x); | 801 | break :blk @select(vinfo.child, x > zero, x, -x); |
| 802 | }, | 802 | }, |
| 803 | else => @compileError("Expected vector of ints, found " ++ @typeName(T)), | 803 | 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) { | ... | @@ -1368,9 +1368,9 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { |
| 1368 | 1368 | ||
| 1369 | switch (@typeInfo(Type)) { | 1369 | switch (@typeInfo(Type)) { |
| 1370 | .Float, .ComptimeFloat => assert(t >= 0 and t <= 1), | 1370 | .Float, .ComptimeFloat => assert(t >= 0 and t <= 1), |
| 1371 | .Vector => |vector| { | 1371 | .Vector => { |
| 1372 | const lower_bound = @reduce(.And, t >= @splat(vector.len, @as(vector.child, 0))); | 1372 | const lower_bound = @reduce(.And, t >= @as(Type, @splat(0))); |
| 1373 | const upper_bound = @reduce(.And, t <= @splat(vector.len, @as(vector.child, 1))); | 1373 | const upper_bound = @reduce(.And, t <= @as(Type, @splat(1))); |
| 1374 | assert(lower_bound and upper_bound); | 1374 | assert(lower_bound and upper_bound); |
| 1375 | }, | 1375 | }, |
| 1376 | else => comptime unreachable, | 1376 | else => comptime unreachable, |
| ... | @@ -1392,14 +1392,24 @@ test "lerp" { | ... | @@ -1392,14 +1392,24 @@ test "lerp" { |
| 1392 | try testing.expectEqual(@as(f32, 1.0), lerp(@as(f32, 1.0e7), 1.0, 1.0)); | 1392 | try testing.expectEqual(@as(f32, 1.0), lerp(@as(f32, 1.0e7), 1.0, 1.0)); |
| 1393 | try testing.expectEqual(@as(f64, 1.0), lerp(@as(f64, 1.0e15), 1.0, 1.0)); | 1393 | try testing.expectEqual(@as(f64, 1.0), lerp(@as(f64, 1.0e15), 1.0, 1.0)); |
| 1394 | 1394 | ||
| 1395 | try testing.expectEqual( | 1395 | { |
| 1396 | lerp(@splat(3, @as(f32, 0)), @splat(3, @as(f32, 50)), @splat(3, @as(f32, 0.5))), | 1396 | const a: @Vector(3, f32) = @splat(0); |
| 1397 | @Vector(3, f32){ 25, 25, 25 }, | 1397 | const b: @Vector(3, f32) = @splat(50); |
| 1398 | ); | 1398 | const t: @Vector(3, f32) = @splat(0.5); |
| 1399 | try testing.expectEqual( | 1399 | try testing.expectEqual( |
| 1400 | lerp(@splat(3, @as(f64, 50)), @splat(3, @as(f64, 100)), @splat(3, @as(f64, 0.5))), | 1400 | lerp(a, b, t), |
| 1401 | @Vector(3, f64){ 75, 75, 75 }, | 1401 | @Vector(3, f32){ 25, 25, 25 }, |
| 1402 | ); | 1402 | ); |
| 1403 | } | ||
| 1404 | { | ||
| 1405 | const a: @Vector(3, f64) = @splat(50); | ||
| 1406 | const b: @Vector(3, f64) = @splat(100); | ||
| 1407 | const t: @Vector(3, f64) = @splat(0.5); | ||
| 1408 | try testing.expectEqual( | ||
| 1409 | lerp(a, b, t), | ||
| 1410 | @Vector(3, f64){ 75, 75, 75 }, | ||
| 1411 | ); | ||
| 1412 | } | ||
| 1403 | } | 1413 | } |
| 1404 | 1414 | ||
| 1405 | /// Returns the maximum value of integer type T. | 1415 | /// Returns the maximum value of integer type T. |
| ... | @@ -1719,8 +1729,8 @@ pub inline fn sign(i: anytype) @TypeOf(i) { | ... | @@ -1719,8 +1729,8 @@ pub inline fn sign(i: anytype) @TypeOf(i) { |
| 1719 | .Vector => |vinfo| blk: { | 1729 | .Vector => |vinfo| blk: { |
| 1720 | switch (@typeInfo(vinfo.child)) { | 1730 | switch (@typeInfo(vinfo.child)) { |
| 1721 | .Int, .Float => { | 1731 | .Int, .Float => { |
| 1722 | const zero = @splat(vinfo.len, @as(vinfo.child, 0)); | 1732 | const zero: T = @splat(0); |
| 1723 | const one = @splat(vinfo.len, @as(vinfo.child, 1)); | 1733 | const one: T = @splat(1); |
| 1724 | break :blk @select(vinfo.child, i > zero, one, zero) - @select(vinfo.child, i < zero, one, zero); | 1734 | break :blk @select(vinfo.child, i > zero, one, zero) - @select(vinfo.child, i < zero, one, zero); |
| 1725 | }, | 1735 | }, |
| 1726 | else => @compileError("Expected vector of ints or floats, found " ++ @typeName(T)), | 1736 | else => @compileError("Expected vector of ints or floats, found " ++ @typeName(T)), |
lib/std/mem.zig+4-4| ... | @@ -289,7 +289,7 @@ pub fn zeroes(comptime T: type) T { | ... | @@ -289,7 +289,7 @@ pub fn zeroes(comptime T: type) T { |
| 289 | return [_]info.child{zeroes(info.child)} ** info.len; | 289 | return [_]info.child{zeroes(info.child)} ** info.len; |
| 290 | }, | 290 | }, |
| 291 | .Vector => |info| { | 291 | .Vector => |info| { |
| 292 | return @splat(info.len, zeroes(info.child)); | 292 | return @splat(zeroes(info.child)); |
| 293 | }, | 293 | }, |
| 294 | .Union => |info| { | 294 | .Union => |info| { |
| 295 | if (comptime meta.containerLayout(T) == .Extern) { | 295 | if (comptime meta.containerLayout(T) == .Extern) { |
| ... | @@ -393,9 +393,9 @@ test "zeroes" { | ... | @@ -393,9 +393,9 @@ test "zeroes" { |
| 393 | for (b.array) |e| { | 393 | for (b.array) |e| { |
| 394 | try testing.expectEqual(@as(u32, 0), e); | 394 | try testing.expectEqual(@as(u32, 0), e); |
| 395 | } | 395 | } |
| 396 | try testing.expectEqual(@splat(2, @as(u32, 0)), b.vector_u32); | 396 | try testing.expectEqual(@as(@TypeOf(b.vector_u32), @splat(0)), b.vector_u32); |
| 397 | try testing.expectEqual(@splat(2, @as(f32, 0.0)), b.vector_f32); | 397 | try testing.expectEqual(@as(@TypeOf(b.vector_f32), @splat(0.0)), b.vector_f32); |
| 398 | try testing.expectEqual(@splat(2, @as(bool, false)), b.vector_bool); | 398 | try testing.expectEqual(@as(@TypeOf(b.vector_bool), @splat(false)), b.vector_bool); |
| 399 | try testing.expectEqual(@as(?u8, null), b.optional_int); | 399 | try testing.expectEqual(@as(?u8, null), b.optional_int); |
| 400 | for (b.sentinel) |e| { | 400 | for (b.sentinel) |e| { |
| 401 | try testing.expectEqual(@as(u8, 0), e); | 401 | try testing.expectEqual(@as(u8, 0), e); |
lib/std/meta.zig+4-3| ... | @@ -860,9 +860,10 @@ test "std.meta.eql" { | ... | @@ -860,9 +860,10 @@ test "std.meta.eql" { |
| 860 | try testing.expect(eql(EU.tst(false), EU.tst(false))); | 860 | try testing.expect(eql(EU.tst(false), EU.tst(false))); |
| 861 | try testing.expect(!eql(EU.tst(false), EU.tst(true))); | 861 | try testing.expect(!eql(EU.tst(false), EU.tst(true))); |
| 862 | 862 | ||
| 863 | var v1 = @splat(4, @as(u32, 1)); | 863 | const V = @Vector(4, u32); |
| 864 | var v2 = @splat(4, @as(u32, 1)); | 864 | var v1: V = @splat(1); |
| 865 | var v3 = @splat(4, @as(u32, 2)); | 865 | var v2: V = @splat(1); |
| 866 | var v3: V = @splat(2); | ||
| 866 | 867 | ||
| 867 | try testing.expect(eql(v1, v2)); | 868 | try testing.expect(eql(v1, v2)); |
| 868 | try testing.expect(!eql(v1, v3)); | 869 | try testing.expect(!eql(v1, v3)); |
lib/std/simd.zig+34-25| ... | @@ -107,7 +107,7 @@ pub inline fn iota(comptime T: type, comptime len: usize) @Vector(len, T) { | ... | @@ -107,7 +107,7 @@ pub inline fn iota(comptime T: type, comptime len: usize) @Vector(len, T) { |
| 107 | pub fn repeat(comptime len: usize, vec: anytype) @Vector(len, std.meta.Child(@TypeOf(vec))) { | 107 | pub fn repeat(comptime len: usize, vec: anytype) @Vector(len, std.meta.Child(@TypeOf(vec))) { |
| 108 | const Child = std.meta.Child(@TypeOf(vec)); | 108 | const Child = std.meta.Child(@TypeOf(vec)); |
| 109 | 109 | ||
| 110 | return @shuffle(Child, vec, undefined, iota(i32, len) % @splat(len, @as(i32, @intCast(vectorLength(@TypeOf(vec)))))); | 110 | return @shuffle(Child, vec, undefined, iota(i32, len) % @as(@Vector(len, i32), @splat(@intCast(vectorLength(@TypeOf(vec)))))); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | /// Returns a vector containing all elements of the first vector at the lower indices followed by all elements of the second vector | 113 | /// 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 | ... | @@ -147,11 +147,12 @@ pub fn interlace(vecs: anytype) @Vector(vectorLength(@TypeOf(vecs[0])) * vecs.le |
| 147 | const len = a_len + b_len; | 147 | const len = a_len + b_len; |
| 148 | 148 | ||
| 149 | const indices = comptime blk: { | 149 | const indices = comptime blk: { |
| 150 | const Vi32 = @Vector(len, i32); | ||
| 150 | const count_up = iota(i32, len); | 151 | const count_up = iota(i32, len); |
| 151 | const cycle = @divFloor(count_up, @splat(len, @as(i32, @intCast(vecs_arr.len)))); | 152 | const cycle = @divFloor(count_up, @as(Vi32, @splat(@intCast(vecs_arr.len)))); |
| 152 | const select_mask = repeat(len, join(@splat(a_vec_count, true), @splat(b_vec_count, false))); | 153 | const select_mask = repeat(len, join(@as(@Vector(a_vec_count, bool), @splat(true)), @as(@Vector(b_vec_count, bool), @splat(false)))); |
| 153 | const a_indices = count_up - cycle * @splat(len, @as(i32, @intCast(b_vec_count))); | 154 | const a_indices = count_up - cycle * @as(Vi32, @splat(@intCast(b_vec_count))); |
| 154 | const b_indices = shiftElementsRight(count_up - cycle * @splat(len, @as(i32, @intCast(a_vec_count))), a_vec_count, 0); | 155 | const b_indices = shiftElementsRight(count_up - cycle * @as(Vi32, @splat(@intCast(a_vec_count))), a_vec_count, 0); |
| 155 | break :blk @select(i32, select_mask, a_indices, ~b_indices); | 156 | break :blk @select(i32, select_mask, a_indices, ~b_indices); |
| 156 | }; | 157 | }; |
| 157 | 158 | ||
| ... | @@ -174,7 +175,7 @@ pub fn deinterlace( | ... | @@ -174,7 +175,7 @@ pub fn deinterlace( |
| 174 | 175 | ||
| 175 | comptime var i: usize = 0; // for-loops don't work for this, apparently. | 176 | comptime var i: usize = 0; // for-loops don't work for this, apparently. |
| 176 | inline while (i < out.len) : (i += 1) { | 177 | inline while (i < out.len) : (i += 1) { |
| 177 | const indices = comptime iota(i32, vec_len) * @splat(vec_len, @as(i32, @intCast(vec_count))) + @splat(vec_len, @as(i32, @intCast(i))); | 178 | const indices = comptime iota(i32, vec_len) * @as(@Vector(vec_len, i32), @splat(@intCast(vec_count))) + @as(@Vector(vec_len, i32), @splat(@intCast(i))); |
| 178 | out[i] = @shuffle(Child, interlaced, undefined, indices); | 179 | out[i] = @shuffle(Child, interlaced, undefined, indices); |
| 179 | } | 180 | } |
| 180 | 181 | ||
| ... | @@ -191,7 +192,7 @@ pub fn extract( | ... | @@ -191,7 +192,7 @@ pub fn extract( |
| 191 | 192 | ||
| 192 | std.debug.assert(@as(comptime_int, @intCast(first)) + @as(comptime_int, @intCast(count)) <= len); | 193 | std.debug.assert(@as(comptime_int, @intCast(first)) + @as(comptime_int, @intCast(count)) <= len); |
| 193 | 194 | ||
| 194 | return @shuffle(Child, vec, undefined, iota(i32, count) + @splat(count, @as(i32, @intCast(first)))); | 195 | return @shuffle(Child, vec, undefined, iota(i32, count) + @as(@Vector(count, i32), @splat(@intCast(first)))); |
| 195 | } | 196 | } |
| 196 | 197 | ||
| 197 | test "vector patterns" { | 198 | test "vector patterns" { |
| ... | @@ -236,17 +237,18 @@ pub fn shiftElementsRight(vec: anytype, comptime amount: VectorCount(@TypeOf(vec | ... | @@ -236,17 +237,18 @@ pub fn shiftElementsRight(vec: anytype, comptime amount: VectorCount(@TypeOf(vec |
| 236 | // It may be possible to implement shifts and rotates with a runtime-friendly slice of two joined vectors, as the length of the | 237 | // It may be possible to implement shifts and rotates with a runtime-friendly slice of two joined vectors, as the length of the |
| 237 | // slice would be comptime-known. This would permit vector shifts and rotates by a non-comptime-known amount. | 238 | // slice would be comptime-known. This would permit vector shifts and rotates by a non-comptime-known amount. |
| 238 | // However, I am unsure whether compiler optimizations would handle that well enough on all platforms. | 239 | // However, I am unsure whether compiler optimizations would handle that well enough on all platforms. |
| 239 | const len = vectorLength(@TypeOf(vec)); | 240 | const V = @TypeOf(vec); |
| 241 | const len = vectorLength(V); | ||
| 240 | 242 | ||
| 241 | return mergeShift(@splat(len, shift_in), vec, len - amount); | 243 | return mergeShift(@as(V, @splat(shift_in)), vec, len - amount); |
| 242 | } | 244 | } |
| 243 | 245 | ||
| 244 | /// Elements are shifted leftwards (towards lower indices). New elements are added to the right, and the leftmost elements are cut off | 246 | /// Elements are shifted leftwards (towards lower indices). New elements are added to the right, and the leftmost elements are cut off |
| 245 | /// so that no elements with indices below 0 remain. | 247 | /// so that no elements with indices below 0 remain. |
| 246 | pub fn shiftElementsLeft(vec: anytype, comptime amount: VectorCount(@TypeOf(vec)), shift_in: std.meta.Child(@TypeOf(vec))) @TypeOf(vec) { | 248 | pub fn shiftElementsLeft(vec: anytype, comptime amount: VectorCount(@TypeOf(vec)), shift_in: std.meta.Child(@TypeOf(vec))) @TypeOf(vec) { |
| 247 | const len = vectorLength(@TypeOf(vec)); | 249 | const V = @TypeOf(vec); |
| 248 | 250 | ||
| 249 | return mergeShift(vec, @splat(len, shift_in), amount); | 251 | return mergeShift(vec, @as(V, @splat(shift_in)), amount); |
| 250 | } | 252 | } |
| 251 | 253 | ||
| 252 | /// Elements are shifted leftwards (towards lower indices). Elements that leave to the left will reappear to the right in the same order. | 254 | /// 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) { | ... | @@ -263,7 +265,7 @@ pub fn reverseOrder(vec: anytype) @TypeOf(vec) { |
| 263 | const Child = std.meta.Child(@TypeOf(vec)); | 265 | const Child = std.meta.Child(@TypeOf(vec)); |
| 264 | const len = vectorLength(@TypeOf(vec)); | 266 | const len = vectorLength(@TypeOf(vec)); |
| 265 | 267 | ||
| 266 | return @shuffle(Child, vec, undefined, @splat(len, @as(i32, @intCast(len)) - 1) - iota(i32, len)); | 268 | return @shuffle(Child, vec, undefined, @as(@Vector(len, i32), @splat(@as(i32, @intCast(len)) - 1)) - iota(i32, len)); |
| 267 | } | 269 | } |
| 268 | 270 | ||
| 269 | test "vector shifting" { | 271 | test "vector shifting" { |
| ... | @@ -283,7 +285,8 @@ pub fn firstTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) { | ... | @@ -283,7 +285,8 @@ pub fn firstTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) { |
| 283 | if (!@reduce(.Or, vec)) { | 285 | if (!@reduce(.Or, vec)) { |
| 284 | return null; | 286 | return null; |
| 285 | } | 287 | } |
| 286 | const indices = @select(IndexInt, vec, iota(IndexInt, len), @splat(len, ~@as(IndexInt, 0))); | 288 | const all_max: @Vector(len, IndexInt) = @splat(~@as(IndexInt, 0)); |
| 289 | const indices = @select(IndexInt, vec, iota(IndexInt, len), all_max); | ||
| 287 | return @reduce(.Min, indices); | 290 | return @reduce(.Min, indices); |
| 288 | } | 291 | } |
| 289 | 292 | ||
| ... | @@ -294,7 +297,9 @@ pub fn lastTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) { | ... | @@ -294,7 +297,9 @@ pub fn lastTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) { |
| 294 | if (!@reduce(.Or, vec)) { | 297 | if (!@reduce(.Or, vec)) { |
| 295 | return null; | 298 | return null; |
| 296 | } | 299 | } |
| 297 | const indices = @select(IndexInt, vec, iota(IndexInt, len), @splat(len, @as(IndexInt, 0))); | 300 | |
| 301 | const all_zeroes: @Vector(len, IndexInt) = @splat(0); | ||
| 302 | const indices = @select(IndexInt, vec, iota(IndexInt, len), all_zeroes); | ||
| 298 | return @reduce(.Max, indices); | 303 | return @reduce(.Max, indices); |
| 299 | } | 304 | } |
| 300 | 305 | ||
| ... | @@ -302,26 +307,29 @@ pub fn countTrues(vec: anytype) VectorCount(@TypeOf(vec)) { | ... | @@ -302,26 +307,29 @@ pub fn countTrues(vec: anytype) VectorCount(@TypeOf(vec)) { |
| 302 | const len = vectorLength(@TypeOf(vec)); | 307 | const len = vectorLength(@TypeOf(vec)); |
| 303 | const CountIntType = VectorCount(@TypeOf(vec)); | 308 | const CountIntType = VectorCount(@TypeOf(vec)); |
| 304 | 309 | ||
| 305 | const one_if_true = @select(CountIntType, vec, @splat(len, @as(CountIntType, 1)), @splat(len, @as(CountIntType, 0))); | 310 | const all_ones: @Vector(len, CountIntType) = @splat(1); |
| 311 | const all_zeroes: @Vector(len, CountIntType) = @splat(0); | ||
| 312 | |||
| 313 | const one_if_true = @select(CountIntType, vec, all_ones, all_zeroes); | ||
| 306 | return @reduce(.Add, one_if_true); | 314 | return @reduce(.Add, one_if_true); |
| 307 | } | 315 | } |
| 308 | 316 | ||
| 309 | pub fn firstIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) { | 317 | pub fn firstIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) { |
| 310 | const len = vectorLength(@TypeOf(vec)); | 318 | const V = @TypeOf(vec); |
| 311 | 319 | ||
| 312 | return firstTrue(vec == @splat(len, value)); | 320 | return firstTrue(vec == @as(V, @splat(value))); |
| 313 | } | 321 | } |
| 314 | 322 | ||
| 315 | pub fn lastIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) { | 323 | pub fn lastIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) { |
| 316 | const len = vectorLength(@TypeOf(vec)); | 324 | const V = @TypeOf(vec); |
| 317 | 325 | ||
| 318 | return lastTrue(vec == @splat(len, value)); | 326 | return lastTrue(vec == @as(V, @splat(value))); |
| 319 | } | 327 | } |
| 320 | 328 | ||
| 321 | pub fn countElementsWithValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) VectorCount(@TypeOf(vec)) { | 329 | pub fn countElementsWithValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) VectorCount(@TypeOf(vec)) { |
| 322 | const len = vectorLength(@TypeOf(vec)); | 330 | const V = @TypeOf(vec); |
| 323 | 331 | ||
| 324 | return countTrues(vec == @splat(len, value)); | 332 | return countTrues(vec == @as(V, @splat(value))); |
| 325 | } | 333 | } |
| 326 | 334 | ||
| 327 | test "vector searching" { | 335 | test "vector searching" { |
| ... | @@ -370,7 +378,6 @@ pub fn prefixScanWithFunc( | ... | @@ -370,7 +378,6 @@ pub fn prefixScanWithFunc( |
| 370 | pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: anytype) @TypeOf(vec) { | 378 | pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: anytype) @TypeOf(vec) { |
| 371 | const VecType = @TypeOf(vec); | 379 | const VecType = @TypeOf(vec); |
| 372 | const Child = std.meta.Child(VecType); | 380 | const Child = std.meta.Child(VecType); |
| 373 | const len = vectorLength(VecType); | ||
| 374 | 381 | ||
| 375 | const identity = comptime switch (@typeInfo(Child)) { | 382 | const identity = comptime switch (@typeInfo(Child)) { |
| 376 | .Bool => switch (op) { | 383 | .Bool => switch (op) { |
| ... | @@ -397,8 +404,8 @@ pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: a | ... | @@ -397,8 +404,8 @@ pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: a |
| 397 | const fn_container = struct { | 404 | const fn_container = struct { |
| 398 | fn opFn(a: VecType, b: VecType) VecType { | 405 | fn opFn(a: VecType, b: VecType) VecType { |
| 399 | return if (Child == bool) switch (op) { | 406 | return if (Child == bool) switch (op) { |
| 400 | .And => @select(bool, a, b, @splat(len, false)), | 407 | .And => @select(bool, a, b, @as(VecType, @splat(false))), |
| 401 | .Or => @select(bool, a, @splat(len, true), b), | 408 | .Or => @select(bool, a, @as(VecType, @splat(true)), b), |
| 402 | .Xor => a != b, | 409 | .Xor => a != b, |
| 403 | else => unreachable, | 410 | else => unreachable, |
| 404 | } else switch (op) { | 411 | } else switch (op) { |
| ... | @@ -431,7 +438,9 @@ test "vector prefix scan" { | ... | @@ -431,7 +438,9 @@ test "vector prefix scan" { |
| 431 | const float_base = @Vector(4, f32){ 2, 0.5, -10, 6.54321 }; | 438 | const float_base = @Vector(4, f32){ 2, 0.5, -10, 6.54321 }; |
| 432 | const bool_base = @Vector(4, bool){ true, false, true, false }; | 439 | const bool_base = @Vector(4, bool){ true, false, true, false }; |
| 433 | 440 | ||
| 434 | try std.testing.expectEqual(iota(u8, 32) + @splat(32, @as(u8, 1)), prefixScan(.Add, 1, @splat(32, @as(u8, 1)))); | 441 | const ones: @Vector(32, u8) = @splat(1); |
| 442 | |||
| 443 | try std.testing.expectEqual(iota(u8, 32) + ones, prefixScan(.Add, 1, ones)); | ||
| 435 | try std.testing.expectEqual(@Vector(4, i32){ 11, 3, 1, 1 }, prefixScan(.And, 1, int_base)); | 444 | try std.testing.expectEqual(@Vector(4, i32){ 11, 3, 1, 1 }, prefixScan(.And, 1, int_base)); |
| 436 | try std.testing.expectEqual(@Vector(4, i32){ 11, 31, 31, -1 }, prefixScan(.Or, 1, int_base)); | 445 | try std.testing.expectEqual(@Vector(4, i32){ 11, 31, 31, -1 }, prefixScan(.Or, 1, int_base)); |
| 437 | try std.testing.expectEqual(@Vector(4, i32){ 11, 28, 21, -2 }, prefixScan(.Xor, 1, int_base)); | 446 | try std.testing.expectEqual(@Vector(4, i32){ 11, 28, 21, -2 }, prefixScan(.Xor, 1, int_base)); |
lib/std/testing.zig+3-3| ... | @@ -606,8 +606,8 @@ test "expectEqual nested array" { | ... | @@ -606,8 +606,8 @@ test "expectEqual nested array" { |
| 606 | } | 606 | } |
| 607 | 607 | ||
| 608 | test "expectEqual vector" { | 608 | test "expectEqual vector" { |
| 609 | var a = @splat(4, @as(u32, 4)); | 609 | var a: @Vector(4, u32) = @splat(4); |
| 610 | var b = @splat(4, @as(u32, 4)); | 610 | var b: @Vector(4, u32) = @splat(4); |
| 611 | 611 | ||
| 612 | try expectEqual(a, b); | 612 | try expectEqual(a, b); |
| 613 | } | 613 | } |
| ... | @@ -903,7 +903,7 @@ test "expectEqualDeep composite type" { | ... | @@ -903,7 +903,7 @@ test "expectEqualDeep composite type" { |
| 903 | try expectEqualDeep([_][]const u8{ "a", "b", "c" }, [_][]const u8{ "a", "b", "c" }); | 903 | try expectEqualDeep([_][]const u8{ "a", "b", "c" }, [_][]const u8{ "a", "b", "c" }); |
| 904 | 904 | ||
| 905 | // vector | 905 | // vector |
| 906 | try expectEqualDeep(@splat(4, @as(u32, 4)), @splat(4, @as(u32, 4))); | 906 | try expectEqualDeep(@as(@Vector(4, u32), @splat(4)), @as(@Vector(4, u32), @splat(4))); |
| 907 | 907 | ||
| 908 | // nested array | 908 | // nested array |
| 909 | { | 909 | { |