authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-21 18:56:30+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-21 18:56:30+02:00
logd1f80fe1063ab9ef28d527e27d2f19b23ea06bc3
tree2a4f010ae1533a2f451a8f72895057bbf2cd5ef7
parent755d09660d8886f77b089bb97157649d2fe65cf9
parentbd2db84eede87bf2336a624ff21e798e8b631921

Merge pull request 'Sema: allow splatting to scalar types' (#37349) from masonremaley/generic-splat into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37349 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

8 files changed, 58 insertions(+), 48 deletions(-)

doc/langref.html.in+1-1
...@@ -5591,7 +5591,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5591,7 +5591,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5591 <p>5591 <p>
5592 Produces an array or vector where each element is the value5592 Produces an array or vector where each element is the value
5593 {#syntax#}element{#endsyntax#}. The return type, including the number of5593 {#syntax#}element{#endsyntax#}. The return type, including the number of
5594 elements, is inferred.5594 elements, is inferred. If the result type is a scalar, `element` is returned.
5595 </p>5595 </p>
5596 {#code|test_splat_builtin.zig#}5596 {#code|test_splat_builtin.zig#}
5597 {#see_also|Vectors|Arrays|@shuffle#}5597 {#see_also|Vectors|Arrays|@shuffle#}
doc/langref/test_splat_builtin.zig+7
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const expectEqualSlices = std.testing.expectEqualSlices;2const expectEqualSlices = std.testing.expectEqualSlices;
3const expectEqual = std.testing.expectEqual;
34
4test "vector @splat" {5test "vector @splat" {
5 const scalar: u32 = 5;6 const scalar: u32 = 5;
...@@ -13,4 +14,10 @@ test "array @splat" {...@@ -13,4 +14,10 @@ test "array @splat" {
13 try expectEqualSlices(u32, &[_]u32{ 5, 5, 5, 5 }, &@as([4]u32, result));14 try expectEqualSlices(u32, &[_]u32{ 5, 5, 5, 5 }, &@as([4]u32, result));
14}15}
1516
17test "scalar @splat" {
18 const scalar: u32 = 5;
19 const result: u32 = @splat(scalar);
20 try expectEqual(5, result);
21}
22
16// test23// test
src/Sema.zig+9-10
...@@ -7515,13 +7515,12 @@ fn zirSplatOpResultType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -7515,13 +7515,12 @@ fn zirSplatOpResultType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
7515 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node;7515 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node;
75167516
7517 const raw_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;7517 const raw_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
7518 const vec_ty = raw_ty.optEuBaseType(zcu);7518 const base_ty = raw_ty.optEuBaseType(zcu);
75197519
7520 switch (vec_ty.zigTypeTag(zcu)) {7520 switch (base_ty.zigTypeTag(zcu)) {
7521 .array, .vector => {},7521 .array, .vector => return Air.internedToRef(base_ty.childType(zcu).toIntern()),
7522 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{f}'", .{vec_ty.fmt(zcu)}),7522 else => return Air.internedToRef(base_ty.toIntern()),
7523 }7523 }
7524 return Air.internedToRef(vec_ty.childType(zcu).toIntern());
7525}7524}
75267525
7527fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7526fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -23314,17 +23313,17 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -23314,17 +23313,17 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
23314 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node;23313 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node;
23315 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;23314 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
23316 const src = block.nodeOffset(inst_data.src_node);23315 const src = block.nodeOffset(inst_data.src_node);
23317 const scalar_src = block.builtinCallArgSrc(inst_data.src_node, 0);23316 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
23318 const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@splat");23317 const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@splat");
23318 const operand = sema.resolveInst(extra.rhs);
2331923319
23320 switch (dest_ty.zigTypeTag(zcu)) {23320 switch (dest_ty.zigTypeTag(zcu)) {
23321 .array, .vector => {},23321 .array, .vector => {},
23322 else => return sema.fail(block, src, "expected array or vector type, found '{f}'", .{dest_ty.fmt(zcu)}),23322 else => return sema.coerce(block, dest_ty, operand, operand_src),
23323 }23323 }
2332423324
23325 const operand = sema.resolveInst(extra.rhs);
23326 const scalar_ty = dest_ty.childType(zcu);23325 const scalar_ty = dest_ty.childType(zcu);
23327 const scalar = try sema.coerce(block, scalar_ty, operand, scalar_src);23326 const scalar = try sema.coerce(block, scalar_ty, operand, operand_src);
2332823327
23329 const len = try sema.usizeCast(block, src, dest_ty.arrayLen(zcu));23328 const len = try sema.usizeCast(block, src, dest_ty.arrayLen(zcu));
2333023329
...@@ -23348,7 +23347,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -23348,7 +23347,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
23348 return .fromValue(try pt.aggregateSplatValue(dest_ty, scalar_val));23347 return .fromValue(try pt.aggregateSplatValue(dest_ty, scalar_val));
23349 }23348 }
2335023349
23351 try sema.requireRuntimeBlock(block, src, scalar_src);23350 try sema.requireRuntimeBlock(block, src, operand_src);
2335223351
23353 switch (dest_ty.zigTypeTag(zcu)) {23352 switch (dest_ty.zigTypeTag(zcu)) {
23354 .vector, .array => return block.addTyOp(.splat, dest_ty, scalar),23353 .vector, .array => return block.addTyOp(.splat, dest_ty, scalar),
test/behavior/splat.zig+19
...@@ -160,3 +160,22 @@ test "vector @splat" {...@@ -160,3 +160,22 @@ test "vector @splat" {
160 try S.doTheTest();160 try S.doTheTest();
161 try comptime S.doTheTest();161 try comptime S.doTheTest();
162}162}
163
164test "scalar @splat" {
165 const S = struct {
166 fn testForTypes(R: type, result: R, Op: type, op: Op) !void {
167 try expect(@as(R, result) == @as(Op, @splat(op)));
168 }
169 fn doTheTest() !void {
170 try testForTypes(comptime_float, 3.1415, comptime_float, 3.1415);
171 try testForTypes(f32, 3.1415, comptime_float, 3.1415);
172 try testForTypes(f32, 3.1415, f32, 3.1415);
173 try testForTypes(u8, 31, u8, 31);
174 try testForTypes(u8, 31, u16, 31);
175 try testForTypes(i16, 31, i16, 31);
176 try testForTypes(i16, 31, i8, 31);
177 }
178 };
179 try S.doTheTest();
180 try comptime S.doTheTest();
181}
test/behavior/x86_64/binary.zig+9-10
...@@ -16,7 +16,6 @@ const nan = math.nan;...@@ -16,7 +16,6 @@ const nan = math.nan;
16const Scalar = math.Scalar;16const Scalar = math.Scalar;
17const select = math.select;17const select = math.select;
18const sign = math.sign;18const sign = math.sign;
19const splat = math.splat;
20const Sse = math.Sse;19const Sse = math.Sse;
21const tmin = math.tmin;20const tmin = math.tmin;
2221
...@@ -5250,7 +5249,7 @@ test divTruncUnoptimized {...@@ -5250,7 +5249,7 @@ test divTruncUnoptimized {
52505249
5251inline fn divTruncOptimized(comptime Type: type, lhs: Type, rhs: Type) Type {5250inline fn divTruncOptimized(comptime Type: type, lhs: Type, rhs: Type) Type {
5252 @setFloatMode(.optimized);5251 @setFloatMode(.optimized);
5253 return @divTrunc(lhs, select(@abs(rhs) > splat(Type, 0.0), rhs, splat(Type, 1.0)));5252 return @divTrunc(lhs, select(@abs(rhs) > @as(Type, @splat(0.0)), rhs, @as(Type, @splat(1.0))));
5254}5253}
5255test divTruncOptimized {5254test divTruncOptimized {
5256 const test_div_trunc_optimized = binary(divTruncOptimized, .{ .compare = .approx_int });5255 const test_div_trunc_optimized = binary(divTruncOptimized, .{ .compare = .approx_int });
...@@ -5271,7 +5270,7 @@ test divFloorUnoptimized {...@@ -5271,7 +5270,7 @@ test divFloorUnoptimized {
52715270
5272inline fn divFloorOptimized(comptime Type: type, lhs: Type, rhs: Type) Type {5271inline fn divFloorOptimized(comptime Type: type, lhs: Type, rhs: Type) Type {
5273 @setFloatMode(.optimized);5272 @setFloatMode(.optimized);
5274 return @divFloor(lhs, select(@abs(rhs) > splat(Type, 0.0), rhs, splat(Type, 1.0)));5273 return @divFloor(lhs, select(@abs(rhs) > @as(Type, @splat(0.0)), rhs, @as(Type, @splat(1.0))));
5275}5274}
5276test divFloorOptimized {5275test divFloorOptimized {
5277 const test_div_floor_optimized = binary(divFloorOptimized, .{ .compare = .approx_int });5276 const test_div_floor_optimized = binary(divFloorOptimized, .{ .compare = .approx_int });
...@@ -5292,7 +5291,7 @@ test divCeilUnoptimized {...@@ -5292,7 +5291,7 @@ test divCeilUnoptimized {
52925291
5293inline fn divCeilOptimized(comptime Type: type, lhs: Type, rhs: Type) Type {5292inline fn divCeilOptimized(comptime Type: type, lhs: Type, rhs: Type) Type {
5294 @setFloatMode(.optimized);5293 @setFloatMode(.optimized);
5295 return @divCeil(lhs, select(@abs(rhs) > splat(Type, 0.0), rhs, splat(Type, 1.0)));5294 return @divCeil(lhs, select(@abs(rhs) > @as(Type, @splat(0.0)), rhs, @as(Type, @splat(1.0))));
5296}5295}
5297test divCeilOptimized {5296test divCeilOptimized {
5298 const test_div_ceil_optimized = binary(divCeilOptimized, .{ .compare = .approx_int });5297 const test_div_ceil_optimized = binary(divCeilOptimized, .{ .compare = .approx_int });
...@@ -5393,7 +5392,7 @@ test mulWithOverflow {...@@ -5393,7 +5392,7 @@ test mulWithOverflow {
5393inline fn shlWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } {5392inline fn shlWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } {
5394 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);5393 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);
5395 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);5394 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5396 return @shlWithOverflow(lhs, if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs);5395 return @shlWithOverflow(lhs, if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % @as(Log2Int(Type), @splat(bits)) else truncate_rhs);
5397}5396}
5398test shlWithOverflow {5397test shlWithOverflow {
5399 const test_shl_with_overflow = binary(shlWithOverflow, .{});5398 const test_shl_with_overflow = binary(shlWithOverflow, .{});
...@@ -5492,7 +5491,7 @@ test bitOr {...@@ -5492,7 +5491,7 @@ test bitOr {
5492inline fn shr(comptime Type: type, lhs: Type, rhs: Type) Type {5491inline fn shr(comptime Type: type, lhs: Type, rhs: Type) Type {
5493 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);5492 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);
5494 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);5493 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5495 return lhs >> if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs;5494 return lhs >> if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % @as(Log2Int(Type), @splat(bits)) else truncate_rhs;
5496}5495}
5497test shr {5496test shr {
5498 const test_shr = binary(shr, .{});5497 const test_shr = binary(shr, .{});
...@@ -5503,7 +5502,7 @@ test shr {...@@ -5503,7 +5502,7 @@ test shr {
5503inline fn shrExact(comptime Type: type, lhs: Type, rhs: Type) Type {5502inline fn shrExact(comptime Type: type, lhs: Type, rhs: Type) Type {
5504 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);5503 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);
5505 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);5504 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5506 const final_rhs = if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs;5505 const final_rhs = if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % @as(Log2Int(Type), @splat(bits)) else truncate_rhs;
5507 return @shrExact(lhs >> final_rhs << final_rhs, final_rhs);5506 return @shrExact(lhs >> final_rhs << final_rhs, final_rhs);
5508}5507}
5509test shrExact {5508test shrExact {
...@@ -5515,7 +5514,7 @@ test shrExact {...@@ -5515,7 +5514,7 @@ test shrExact {
5515inline fn shl(comptime Type: type, lhs: Type, rhs: Type) Type {5514inline fn shl(comptime Type: type, lhs: Type, rhs: Type) Type {
5516 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);5515 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);
5517 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);5516 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5518 return lhs << if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs;5517 return lhs << if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % @as(Log2Int(Type), @splat(bits)) else truncate_rhs;
5519}5518}
5520test shl {5519test shl {
5521 const test_shl = binary(shl, .{});5520 const test_shl = binary(shl, .{});
...@@ -5527,7 +5526,7 @@ inline fn shlExactUnsafe(comptime Type: type, lhs: Type, rhs: Type) Type {...@@ -5527,7 +5526,7 @@ inline fn shlExactUnsafe(comptime Type: type, lhs: Type, rhs: Type) Type {
5527 @setRuntimeSafety(false);5526 @setRuntimeSafety(false);
5528 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);5527 const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs);
5529 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);5528 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5530 const final_rhs = if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs;5529 const final_rhs = if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % @as(Log2Int(Type), @splat(bits)) else truncate_rhs;
5531 return @shlExact(lhs << final_rhs >> final_rhs, final_rhs);5530 return @shlExact(lhs << final_rhs >> final_rhs, final_rhs);
5532}5531}
5533test shlExactUnsafe {5532test shlExactUnsafe {
...@@ -5540,7 +5539,7 @@ inline fn shlSaturate(comptime Type: type, lhs: Type, rhs: Type) Type {...@@ -5540,7 +5539,7 @@ inline fn shlSaturate(comptime Type: type, lhs: Type, rhs: Type) Type {
5540 // workaround https://github.com/ziglang/zig/issues/230345539 // workaround https://github.com/ziglang/zig/issues/23034
5541 if (@inComptime()) {5540 if (@inComptime()) {
5542 // workaround https://github.com/ziglang/zig/issues/231395541 // workaround https://github.com/ziglang/zig/issues/23139
5543 return lhs <<| @min(@abs(rhs), splat(ChangeScalar(Type, u64), imax(u64)));5542 return lhs <<| @min(@abs(rhs), @as(ChangeScalar(Type, u64), @splat(imax(u64))));
5544 }5543 }
5545 return lhs <<| @abs(rhs);5544 return lhs <<| @abs(rhs);
5546}5545}
test/behavior/x86_64/cast.zig+7-8
...@@ -12,7 +12,6 @@ const math = @import("math.zig");...@@ -12,7 +12,6 @@ const math = @import("math.zig");
12const nan = math.nan;12const nan = math.nan;
13const next = math.next;13const next = math.next;
14const Scalar = math.Scalar;14const Scalar = math.Scalar;
15const splat = math.splat;
16const Sse = math.Sse;15const Sse = math.Sse;
17const tmin = math.tmin;16const tmin = math.tmin;
1817
...@@ -14508,18 +14507,18 @@ inline fn intCast(comptime Result: type, comptime Type: type, rhs: Type, comptim...@@ -14508,18 +14507,18 @@ inline fn intCast(comptime Result: type, comptime Type: type, rhs: Type, comptim
14508 rhs & imax(Type) >> bits,14507 rhs & imax(Type) >> bits,
14509 .vector => rhs | @select(14508 .vector => rhs | @select(
14510 Scalar(Type),14509 Scalar(Type),
14511 ct_rhs < splat(Type, 0),14510 ct_rhs < @as(Type, @splat(0)),
14512 splat(Type, imin(Scalar(Type)) >> bits),14511 @as(Type, @splat(imin(Scalar(Type)) >> bits)),
14513 splat(Type, 0),14512 @as(Type, @splat(0)),
14514 ) & ~@select(14513 ) & ~@select(
14515 Scalar(Type),14514 Scalar(Type),
14516 ct_rhs >= splat(Type, 0),14515 ct_rhs >= @as(Type, @splat(0)),
14517 splat(Type, imin(Scalar(Type)) >> bits),14516 @as(Type, @splat(imin(Scalar(Type)) >> bits)),
14518 splat(Type, 0),14517 @as(Type, @splat(0)),
14519 ),14518 ),
14520 else => comptime unreachable,14519 else => comptime unreachable,
14521 },14520 },
14522 .mask => |bits| if (bits == rhs_info.bits) rhs else rhs & splat(Type, (1 << bits) - 1),14521 .mask => |bits| if (bits == rhs_info.bits) rhs else rhs & @as(Type, @splat((1 << bits) - 1)),
14523 });14522 });
14524}14523}
14525test intCast {14524test intCast {
test/behavior/x86_64/math.zig+6-12
...@@ -72,19 +72,13 @@ pub fn Log2Int(comptime Type: type) type {...@@ -72,19 +72,13 @@ pub fn Log2Int(comptime Type: type) type {
72pub fn Log2IntCeil(comptime Type: type) type {72pub fn Log2IntCeil(comptime Type: type) type {
73 return ChangeScalar(Type, math.Log2IntCeil(Scalar(Type)));73 return ChangeScalar(Type, math.Log2IntCeil(Scalar(Type)));
74}74}
75pub fn splat(comptime Type: type, scalar: Scalar(Type)) Type {
76 return switch (@typeInfo(Type)) {
77 else => scalar,
78 .vector => @splat(scalar),
79 };
80}
81pub fn sign(rhs: anytype) ChangeScalar(@TypeOf(rhs), bool) {75pub fn sign(rhs: anytype) ChangeScalar(@TypeOf(rhs), bool) {
82 const Int = ChangeScalar(@TypeOf(rhs), switch (@typeInfo(Scalar(@TypeOf(rhs)))) {76 const Int = ChangeScalar(@TypeOf(rhs), switch (@typeInfo(Scalar(@TypeOf(rhs)))) {
83 .int, .comptime_int => Scalar(@TypeOf(rhs)),77 .int, .comptime_int => Scalar(@TypeOf(rhs)),
84 .float => |float| @Int(.signed, float.bits),78 .float => |float| @Int(.signed, float.bits),
85 else => @compileError(@typeName(@TypeOf(rhs))),79 else => @compileError(@typeName(@TypeOf(rhs))),
86 });80 });
87 return @as(Int, @bitCast(rhs)) < splat(Int, 0);81 return @as(Int, @bitCast(rhs)) < @as(Int, @splat(0));
88}82}
89pub fn select(cond: anytype, lhs: anytype, rhs: @TypeOf(lhs)) @TypeOf(lhs) {83pub fn select(cond: anytype, lhs: anytype, rhs: @TypeOf(lhs)) @TypeOf(lhs) {
90 return switch (@typeInfo(@TypeOf(cond))) {84 return switch (@typeInfo(@TypeOf(cond))) {
...@@ -117,19 +111,19 @@ pub noinline fn checkExpected(expected: anytype, actual: @TypeOf(expected), comp...@@ -117,19 +111,19 @@ pub noinline fn checkExpected(expected: anytype, actual: @TypeOf(expected), comp
117 .approx_or_overflow => @exp2(@log2(epsilon) * 0.4),111 .approx_or_overflow => @exp2(@log2(epsilon) * 0.4),
118 };112 };
119 const approx_unequal = @abs(expected - actual) > @max(113 const approx_unequal = @abs(expected - actual) > @max(
120 @abs(expected) * splat(Expected, tolerance),114 @abs(expected) * @as(Expected, @splat(tolerance)),
121 splat(Expected, switch (compare) {115 @as(Expected, @splat(switch (compare) {
122 .strict, .relaxed => comptime unreachable,116 .strict, .relaxed => comptime unreachable,
123 .approx, .approx_or_overflow => tolerance,117 .approx, .approx_or_overflow => tolerance,
124 .approx_int => 1,118 .approx_int => 1,
125 }),119 })),
126 );120 );
127 break :unexpected switch (compare) {121 break :unexpected switch (compare) {
128 .strict, .relaxed => comptime unreachable,122 .strict, .relaxed => comptime unreachable,
129 .approx, .approx_int => approx_unequal,123 .approx, .approx_int => approx_unequal,
130 .approx_or_overflow => approx_unequal &124 .approx_or_overflow => approx_unequal &
131 (((@abs(expected) != splat(Expected, inf(Expected))) &125 (((@abs(expected) != @as(Expected, @splat(inf(Expected)))) &
132 (@abs(actual) != splat(Expected, inf(Expected)))) |126 (@abs(actual) != @as(Expected, @splat(inf(Expected))))) |
133 (sign(expected) != sign(actual))),127 (sign(expected) != sign(actual))),
134 };128 };
135 },129 },
test/cases/compile_errors/splat_bad_result_type.zig deleted-7
...@@ -1,7 +0,0 @@
1export fn f() void {
2 _ = @as(u32, @splat(5));
3}
4
5// error
6//
7// :2:18: error: expected array or vector type, found 'u32'