diff options
| author | John Schmidt <john.schmidt.h@gmail.com> | 2022-02-13 18:15:13 +0100 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-02-17 14:47:21 +0200 |
| commit | e2ad95c0883bfaacba7377fdf3e037d9fecd4940 (patch) | |
| tree | 79ad699fd00d543bf861768a933d5f5bb3361a9f | |
| parent | 755d116ecf2d221e2ad8b572c58a7d4f99163ff9 (diff) | |
| download | zig-e2ad95c0883bfaacba7377fdf3e037d9fecd4940.tar.gz zig-e2ad95c0883bfaacba7377fdf3e037d9fecd4940.zip | |
stage2: implement vector floatops
| -rw-r--r-- | src/Sema.zig | 56 | ||||
| -rw-r--r-- | test/behavior/floatop.zig | 100 |
2 files changed, 92 insertions, 64 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 480a6a1ca2..35cf750fd5 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -11086,17 +11086,57 @@ fn zirUnaryMath( const operand = sema.resolveInst(inst_data.operand); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand_ty = sema.typeOf(operand); - try sema.checkFloatType(block, operand_src, operand_ty); - if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { - if (operand_val.isUndef()) return sema.addConstUndef(operand_ty); - const target = sema.mod.getTarget(); - const result_val = try eval(operand_val, operand_ty, sema.arena, target); - return sema.addConstant(operand_ty, result_val); + switch (operand_ty.zigTypeTag()) { + .ComptimeFloat, .Float => {}, + .Vector => { + const scalar_ty = operand_ty.scalarType(); + switch (scalar_ty.zigTypeTag()) { + .ComptimeFloat, .Float => {}, + else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty}), + } + }, + else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty}), } - try sema.requireRuntimeBlock(block, operand_src); - return block.addUnOp(air_tag, operand); + const target = sema.mod.getTarget(); + switch (operand_ty.zigTypeTag()) { + .Vector => { + const scalar_ty = operand_ty.scalarType(); + const vec_len = operand_ty.vectorLen(); + const result_ty = try Type.vector(sema.arena, vec_len, scalar_ty); + if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { + if (val.isUndef()) + return sema.addConstUndef(result_ty); + + var elem_buf: Value.ElemValueBuffer = undefined; + const elems = try sema.arena.alloc(Value, vec_len); + for (elems) |*elem, i| { + const elem_val = val.elemValueBuffer(i, &elem_buf); + elem.* = try eval(elem_val, scalar_ty, sema.arena, target); + } + return sema.addConstant( + result_ty, + try Value.Tag.array.create(sema.arena, elems), + ); + } + + try sema.requireRuntimeBlock(block, operand_src); + return block.addUnOp(air_tag, operand); + }, + .ComptimeFloat, .Float => { + if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { + if (operand_val.isUndef()) + return sema.addConstUndef(operand_ty); + const result_val = try eval(operand_val, operand_ty, sema.arena, target); + return sema.addConstant(operand_ty, result_val); + } + + try sema.requireRuntimeBlock(block, operand_src); + return block.addUnOp(air_tag, operand); + }, + else => unreachable, + } } fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 4de8f5a5fc..3e7d3875ea 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -98,6 +98,15 @@ fn testSqrt() !void { try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), 1.0488088481701516, epsilon)); try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.0)), 1.4142135623730950, epsilon)); + { + var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; + var result = @sqrt(v); + try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon)); + try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon)); + try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon)); + try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon)); + } + if (builtin.zig_backend == .stage1) { if (has_f80_rt) { // TODO https://github.com/ziglang/zig/issues/10875 @@ -116,16 +125,6 @@ fn testSqrt() !void { // var a: f128 = 49; //try expect(@sqrt(a) == 7); //} - - // TODO Implement Vector support for stage2 - { - var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; - var result = @sqrt(v); - try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon)); - try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon)); - try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon)); - try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon)); - } } } @@ -155,26 +154,25 @@ test "@sin" { } fn testSin() !void { - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` + // so skip the rest of the tests. + if (builtin.zig_backend != .stage1) { + inline for ([_]type{ f16, f32, f64 }) |ty| { + const eps = epsForType(ty); + try expect(@sin(@as(ty, 0)) == 0); + try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps)); + try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2)), 1, eps)); + try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps)); + } + } + + { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; var result = @sin(v); try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon)); try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon)); try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon)); try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon)); - - // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` - // so skip the rest of the tests. - return; - } - - inline for ([_]type{ f16, f32, f64 }) |ty| { - const eps = epsForType(ty); - try expect(@sin(@as(ty, 0)) == 0); - try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps)); - try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2)), 1, eps)); - try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps)); } } @@ -184,26 +182,25 @@ test "@cos" { } fn testCos() !void { - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` + // so skip the rest of the tests. + if (builtin.zig_backend != .stage1) { + inline for ([_]type{ f16, f32, f64 }) |ty| { + const eps = epsForType(ty); + try expect(@cos(@as(ty, 0)) == 1); + try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps)); + try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2)), 0, eps)); + try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps)); + } + } + + { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; var result = @cos(v); try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon)); try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon)); try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon)); try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon)); - - // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` - // so skip the rest of the tests. - return; - } - - inline for ([_]type{ f16, f32, f64 }) |ty| { - const eps = epsForType(ty); - try expect(@cos(@as(ty, 0)) == 1); - try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps)); - try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2)), 0, eps)); - try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps)); } } @@ -220,8 +217,7 @@ fn testExp() !void { try expect(math.approxEqAbs(ty, @exp(@as(ty, 5)), 148.4131591025766, eps)); } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; var result = @exp(v); try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon)); @@ -244,8 +240,7 @@ fn testExp2() !void { try expect(math.approxEqAbs(ty, @exp2(@as(ty, 4.5)), 22.627416997969, eps)); } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; var result = @exp2(v); try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon)); @@ -281,8 +276,7 @@ fn testLog() !void { try expect(math.approxEqAbs(ty, @log(@as(ty, 5)), 1.6094379124341, eps)); } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; var result = @log(v); try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon)); @@ -305,8 +299,7 @@ fn testLog2() !void { try expect(math.approxEqAbs(ty, @log2(@as(ty, 10)), 3.3219280948874, eps)); } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; var result = @log2(v); try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon)); @@ -329,8 +322,7 @@ fn testLog10() !void { try expect(math.approxEqAbs(ty, @log10(@as(ty, 50)), 1.698970004336, eps)); } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; var result = @log10(v); try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon)); @@ -362,8 +354,7 @@ fn testFabs() !void { // try expect(@fabs(b) == 2.5); // } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; var result = @fabs(v); try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon)); @@ -390,8 +381,7 @@ fn testFloor() !void { // try expect(@floor(a) == 3); // } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; var result = @floor(v); try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon)); @@ -418,8 +408,7 @@ fn testCeil() !void { // try expect(@ceil(a) == 4); // } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; var result = @ceil(v); try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon)); @@ -446,8 +435,7 @@ fn testTrunc() !void { // try expect(@trunc(a) == -3); // } - // TODO: Implement Vector support for other backends - if (builtin.zig_backend == .stage1) { + { var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; var result = @trunc(v); try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon)); |
