authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-07 18:52:57-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-07 18:52:57-05:00
log9bbfbacae0707cf0712e4d6b227b17d097708c7e
treed61c60e53f167ecb3c5b24235f5fa30f01fd8c23
parentdd49ed1c642d917af40bf4a0e03d013f40b3903b
parenta028488384c599aa997ba04bbd5ed98f2172630c
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10801 from schmee/stage2-sqrt

stage2: implement @sqrt for f{16,32,64}

16 files changed, 196 insertions(+), 57 deletions(-)

src/Air.zig+6
...@@ -237,6 +237,10 @@ pub const Inst = struct {...@@ -237,6 +237,10 @@ pub const Inst = struct {
237 /// Uses the `ty_op` field.237 /// Uses the `ty_op` field.
238 popcount,238 popcount,
239239
240 /// Computes the square root of a floating point number.
241 /// Uses the `un_op` field.
242 sqrt,
243
240 /// `<`. Result type is always bool.244 /// `<`. Result type is always bool.
241 /// Uses the `bin_op` field.245 /// Uses the `bin_op` field.
242 cmp_lt,246 cmp_lt,
...@@ -749,6 +753,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -749,6 +753,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
749 .max,753 .max,
750 => return air.typeOf(datas[inst].bin_op.lhs),754 => return air.typeOf(datas[inst].bin_op.lhs),
751755
756 .sqrt => return air.typeOf(datas[inst].un_op),
757
752 .cmp_lt,758 .cmp_lt,
753 .cmp_lte,759 .cmp_lte,
754 .cmp_eq,760 .cmp_eq,
src/Liveness.zig+1
...@@ -338,6 +338,7 @@ fn analyzeInst(...@@ -338,6 +338,7 @@ fn analyzeInst(
338 .ret_load,338 .ret_load,
339 .tag_name,339 .tag_name,
340 .error_name,340 .error_name,
341 .sqrt,
341 => {342 => {
342 const operand = inst_datas[inst].un_op;343 const operand = inst_datas[inst].un_op;
343 return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });344 return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });
src/Sema.zig+37-16
...@@ -745,19 +745,19 @@ fn analyzeBodyInner(...@@ -745,19 +745,19 @@ fn analyzeBodyInner(
745 .clz => try sema.zirClzCtz(block, inst, .clz, Value.clz),745 .clz => try sema.zirClzCtz(block, inst, .clz, Value.clz),
746 .ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz),746 .ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz),
747747
748 .sqrt => try sema.zirUnaryMath(block, inst),748 .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt),
749 .sin => try sema.zirUnaryMath(block, inst),749 .sin => @panic("TODO"),
750 .cos => try sema.zirUnaryMath(block, inst),750 .cos => @panic("TODO"),
751 .exp => try sema.zirUnaryMath(block, inst),751 .exp => @panic("TODO"),
752 .exp2 => try sema.zirUnaryMath(block, inst),752 .exp2 => @panic("TODO"),
753 .log => try sema.zirUnaryMath(block, inst),753 .log => @panic("TODO"),
754 .log2 => try sema.zirUnaryMath(block, inst),754 .log2 => @panic("TODO"),
755 .log10 => try sema.zirUnaryMath(block, inst),755 .log10 => @panic("TODO"),
756 .fabs => try sema.zirUnaryMath(block, inst),756 .fabs => @panic("TODO"),
757 .floor => try sema.zirUnaryMath(block, inst),757 .floor => @panic("TODO"),
758 .ceil => try sema.zirUnaryMath(block, inst),758 .ceil => @panic("TODO"),
759 .trunc => try sema.zirUnaryMath(block, inst),759 .trunc => @panic("TODO"),
760 .round => try sema.zirUnaryMath(block, inst),760 .round => @panic("TODO"),
761761
762 .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent),762 .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent),
763 .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),763 .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),
...@@ -11010,10 +11010,31 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -11010,10 +11010,31 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
11010 return block.addUnOp(.error_name, operand);11010 return block.addUnOp(.error_name, operand);
11011}11011}
1101211012
11013fn zirUnaryMath(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {11013fn zirUnaryMath(
11014 sema: *Sema,
11015 block: *Block,
11016 inst: Zir.Inst.Index,
11017 air_tag: Air.Inst.Tag,
11018 eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value,
11019) CompileError!Air.Inst.Ref {
11020 const tracy = trace(@src());
11021 defer tracy.end();
11022
11014 const inst_data = sema.code.instructions.items(.data)[inst].un_node;11023 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
11015 const src = inst_data.src();11024 const operand = sema.resolveInst(inst_data.operand);
11016 return sema.fail(block, src, "TODO: Sema.zirUnaryMath", .{});11025 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
11026 const operand_ty = sema.typeOf(operand);
11027 try sema.checkFloatType(block, operand_src, operand_ty);
11028
11029 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| {
11030 if (operand_val.isUndef()) return sema.addConstUndef(operand_ty);
11031 const target = sema.mod.getTarget();
11032 const result_val = try eval(operand_val, operand_ty, sema.arena, target);
11033 return sema.addConstant(operand_ty, result_val);
11034 }
11035
11036 try sema.requireRuntimeBlock(block, operand_src);
11037 return block.addUnOp(air_tag, operand);
11017}11038}
1101811039
11019fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {11040fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
src/arch/aarch64/CodeGen.zig+11
...@@ -528,6 +528,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -528,6 +528,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
528 .max => try self.airMax(inst),528 .max => try self.airMax(inst),
529 .slice => try self.airSlice(inst),529 .slice => try self.airSlice(inst),
530530
531 .sqrt => try self.airUnaryMath(inst),
532
531 .add_with_overflow => try self.airAddWithOverflow(inst),533 .add_with_overflow => try self.airAddWithOverflow(inst),
532 .sub_with_overflow => try self.airSubWithOverflow(inst),534 .sub_with_overflow => try self.airSubWithOverflow(inst),
533 .mul_with_overflow => try self.airMulWithOverflow(inst),535 .mul_with_overflow => try self.airMulWithOverflow(inst),
...@@ -1223,6 +1225,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -1223,6 +1225,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
1223 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1225 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1224}1226}
12251227
1228fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
1229 const un_op = self.air.instructions.items(.data)[inst].un_op;
1230 const result: MCValue = if (self.liveness.isUnused(inst))
1231 .dead
1232 else
1233 return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
1234 return self.finishAir(inst, result, .{ un_op, .none, .none });
1235}
1236
1226fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {1237fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
1227 if (!self.liveness.operandDies(inst, op_index))1238 if (!self.liveness.operandDies(inst, op_index))
1228 return false;1239 return false;
src/arch/arm/CodeGen.zig+11
...@@ -520,6 +520,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -520,6 +520,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
520 .max => try self.airMax(inst),520 .max => try self.airMax(inst),
521 .slice => try self.airSlice(inst),521 .slice => try self.airSlice(inst),
522522
523 .sqrt => try self.airUnaryMath(inst),
524
523 .add_with_overflow => try self.airAddWithOverflow(inst),525 .add_with_overflow => try self.airAddWithOverflow(inst),
524 .sub_with_overflow => try self.airSubWithOverflow(inst),526 .sub_with_overflow => try self.airSubWithOverflow(inst),
525 .mul_with_overflow => try self.airMulWithOverflow(inst),527 .mul_with_overflow => try self.airMulWithOverflow(inst),
...@@ -1377,6 +1379,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -1377,6 +1379,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
1377 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1379 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1378}1380}
13791381
1382fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
1383 const un_op = self.air.instructions.items(.data)[inst].un_op;
1384 const result: MCValue = if (self.liveness.isUnused(inst))
1385 .dead
1386 else
1387 return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
1388 return self.finishAir(inst, result, .{ un_op, .none, .none });
1389}
1390
1380fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {1391fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
1381 if (!self.liveness.operandDies(inst, op_index))1392 if (!self.liveness.operandDies(inst, op_index))
1382 return false;1393 return false;
src/arch/riscv64/CodeGen.zig+11
...@@ -507,6 +507,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -507,6 +507,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
507 .max => try self.airMax(inst),507 .max => try self.airMax(inst),
508 .slice => try self.airSlice(inst),508 .slice => try self.airSlice(inst),
509509
510 .sqrt => try self.airUnaryMath(inst),
511
510 .add_with_overflow => try self.airAddWithOverflow(inst),512 .add_with_overflow => try self.airAddWithOverflow(inst),
511 .sub_with_overflow => try self.airSubWithOverflow(inst),513 .sub_with_overflow => try self.airSubWithOverflow(inst),
512 .mul_with_overflow => try self.airMulWithOverflow(inst),514 .mul_with_overflow => try self.airMulWithOverflow(inst),
...@@ -1166,6 +1168,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -1166,6 +1168,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
1166 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1168 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1167}1169}
11681170
1171fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
1172 const un_op = self.air.instructions.items(.data)[inst].un_op;
1173 const result: MCValue = if (self.liveness.isUnused(inst))
1174 .dead
1175 else
1176 return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
1177 return self.finishAir(inst, result, .{ un_op, .none, .none });
1178}
1179
1169fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {1180fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
1170 if (!self.liveness.operandDies(inst, op_index))1181 if (!self.liveness.operandDies(inst, op_index))
1171 return false;1182 return false;
src/arch/wasm/CodeGen.zig+2
...@@ -1681,6 +1681,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1681,6 +1681,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1681 .unwrap_errunion_payload_ptr,1681 .unwrap_errunion_payload_ptr,
1682 .unwrap_errunion_err_ptr,1682 .unwrap_errunion_err_ptr,
16831683
1684 .sqrt,
1685
1684 .ptr_slice_len_ptr,1686 .ptr_slice_len_ptr,
1685 .ptr_slice_ptr_ptr,1687 .ptr_slice_ptr_ptr,
1686 .int_to_float,1688 .int_to_float,
src/arch/x86_64/CodeGen.zig+11
...@@ -599,6 +599,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -599,6 +599,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
599 .max => try self.airMax(inst),599 .max => try self.airMax(inst),
600 .slice => try self.airSlice(inst),600 .slice => try self.airSlice(inst),
601601
602 .sqrt => try self.airUnaryMath(inst),
603
602 .add_with_overflow => try self.airAddWithOverflow(inst),604 .add_with_overflow => try self.airAddWithOverflow(inst),
603 .sub_with_overflow => try self.airSubWithOverflow(inst),605 .sub_with_overflow => try self.airSubWithOverflow(inst),
604 .mul_with_overflow => try self.airMulWithOverflow(inst),606 .mul_with_overflow => try self.airMulWithOverflow(inst),
...@@ -1578,6 +1580,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -1578,6 +1580,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
1578 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1580 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1579}1581}
15801582
1583fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
1584 const un_op = self.air.instructions.items(.data)[inst].un_op;
1585 const result: MCValue = if (self.liveness.isUnused(inst))
1586 .dead
1587 else
1588 return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
1589 return self.finishAir(inst, result, .{ un_op, .none, .none });
1590}
1591
1581fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {1592fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
1582 if (!self.liveness.operandDies(inst, op_index))1593 if (!self.liveness.operandDies(inst, op_index))
1583 return false;1594 return false;
src/codegen/c.zig+8
...@@ -1446,6 +1446,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1446,6 +1446,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1446 .mul_sat => try airSatOp(f, inst, "muls_"),1446 .mul_sat => try airSatOp(f, inst, "muls_"),
1447 .shl_sat => try airSatOp(f, inst, "shls_"),1447 .shl_sat => try airSatOp(f, inst, "shls_"),
14481448
1449 .sqrt => try airSqrt(f, inst),
1450
1449 .add_with_overflow => try airAddWithOverflow(f, inst),1451 .add_with_overflow => try airAddWithOverflow(f, inst),
1450 .sub_with_overflow => try airSubWithOverflow(f, inst),1452 .sub_with_overflow => try airSubWithOverflow(f, inst),
1451 .mul_with_overflow => try airMulWithOverflow(f, inst),1453 .mul_with_overflow => try airMulWithOverflow(f, inst),
...@@ -3393,6 +3395,12 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3393,6 +3395,12 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
3393 return CValue.none;3395 return CValue.none;
3394}3396}
33953397
3398fn airSqrt(f: *Function, inst: Air.Inst.Index) !CValue {
3399 _ = f;
3400 _ = inst;
3401 return f.fail("TODO: C backend: implement sqrt", .{});
3402}
3403
3396fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {3404fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
3397 return switch (order) {3405 return switch (order) {
3398 .Unordered => "memory_order_relaxed",3406 .Unordered => "memory_order_relaxed",
src/codegen/llvm.zig+16
...@@ -2050,6 +2050,8 @@ pub const FuncGen = struct {...@@ -2050,6 +2050,8 @@ pub const FuncGen = struct {
2050 .shr => try self.airShr(inst, false),2050 .shr => try self.airShr(inst, false),
2051 .shr_exact => try self.airShr(inst, true),2051 .shr_exact => try self.airShr(inst, true),
20522052
2053 .sqrt => try self.airSqrt(inst),
2054
2053 .cmp_eq => try self.airCmp(inst, .eq),2055 .cmp_eq => try self.airCmp(inst, .eq),
2054 .cmp_gt => try self.airCmp(inst, .gt),2056 .cmp_gt => try self.airCmp(inst, .gt),
2055 .cmp_gte => try self.airCmp(inst, .gte),2057 .cmp_gte => try self.airCmp(inst, .gte),
...@@ -4211,6 +4213,20 @@ pub const FuncGen = struct {...@@ -4211,6 +4213,20 @@ pub const FuncGen = struct {
4211 }4213 }
4212 }4214 }
42134215
4216 fn airSqrt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4217 if (self.liveness.isUnused(inst)) return null;
4218
4219 const un_op = self.air.instructions.items(.data)[inst].un_op;
4220 const operand = try self.resolveInst(un_op);
4221 const operand_ty = self.air.typeOf(un_op);
4222
4223 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
4224 const fn_val = self.getIntrinsic("llvm.sqrt", &.{operand_llvm_ty});
4225 const params = [_]*const llvm.Value{operand};
4226
4227 return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
4228 }
4229
4214 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, prefix: [*:0]const u8) !?*const llvm.Value {4230 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, prefix: [*:0]const u8) !?*const llvm.Value {
4215 if (self.liveness.isUnused(inst)) return null;4231 if (self.liveness.isUnused(inst)) return null;
42164232
src/print_air.zig+1
...@@ -158,6 +158,7 @@ const Writer = struct {...@@ -158,6 +158,7 @@ const Writer = struct {
158 .ret_load,158 .ret_load,
159 .tag_name,159 .tag_name,
160 .error_name,160 .error_name,
161 .sqrt,
161 => try w.writeUnOp(s, inst),162 => try w.writeUnOp(s, inst),
162163
163 .breakpoint,164 .breakpoint,
src/stage1/codegen.cpp+1-1
...@@ -6996,7 +6996,7 @@ static LLVMValueRef ir_render_soft_f80_float_op(CodeGen *g, Stage1Air *executabl...@@ -6996,7 +6996,7 @@ static LLVMValueRef ir_render_soft_f80_float_op(CodeGen *g, Stage1Air *executabl
6996 const char *func_name;6996 const char *func_name;
6997 switch (instruction->fn_id) {6997 switch (instruction->fn_id) {
6998 case BuiltinFnIdSqrt:6998 case BuiltinFnIdSqrt:
6999 func_name = "__sqrt";6999 func_name = "__sqrtx";
7000 break;7000 break;
7001 case BuiltinFnIdSin:7001 case BuiltinFnIdSin:
7002 func_name = "__sinx";7002 func_name = "__sinx";
src/value.zig+32
...@@ -3265,6 +3265,38 @@ pub const Value = extern union {...@@ -3265,6 +3265,38 @@ pub const Value = extern union {
3265 }3265 }
3266 }3266 }
32673267
3268 pub fn sqrt(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
3269 switch (float_type.floatBits(target)) {
3270 16 => {
3271 const f = val.toFloat(f16);
3272 return Value.Tag.float_16.create(arena, @sqrt(f));
3273 },
3274 32 => {
3275 const f = val.toFloat(f32);
3276 return Value.Tag.float_32.create(arena, @sqrt(f));
3277 },
3278 64 => {
3279 const f = val.toFloat(f64);
3280 return Value.Tag.float_64.create(arena, @sqrt(f));
3281 },
3282 80 => {
3283 if (true) {
3284 @panic("TODO implement compiler_rt __sqrtx");
3285 }
3286 const f = val.toFloat(f80);
3287 return Value.Tag.float_80.create(arena, @sqrt(f));
3288 },
3289 128 => {
3290 if (true) {
3291 @panic("TODO implement compiler_rt sqrtq");
3292 }
3293 const f = val.toFloat(f128);
3294 return Value.Tag.float_128.create(arena, @sqrt(f));
3295 },
3296 else => unreachable,
3297 }
3298 }
3299
3268 /// This type is not copyable since it may contain pointers to its inner data.3300 /// This type is not copyable since it may contain pointers to its inner data.
3269 pub const Payload = struct {3301 pub const Payload = struct {
3270 tag: Tag,3302 tag: Tag,
test/behavior/floatop.zig+42
...@@ -72,3 +72,45 @@ test "negative f128 floatToInt at compile-time" {...@@ -72,3 +72,45 @@ test "negative f128 floatToInt at compile-time" {
72 var b = @floatToInt(i64, a);72 var b = @floatToInt(i64, a);
73 try expect(@as(i64, -2) == b);73 try expect(@as(i64, -2) == b);
74}74}
75
76test "@sqrt" {
77 comptime try testSqrt();
78 try testSqrt();
79}
80
81fn testSqrt() !void {
82 {
83 var a: f16 = 4;
84 try expect(@sqrt(a) == 2);
85 }
86 {
87 var a: f32 = 9;
88 try expect(@sqrt(a) == 3);
89 var b: f32 = 1.1;
90 try expect(math.approxEqAbs(f32, @sqrt(b), 1.0488088481701516, epsilon));
91 }
92 {
93 var a: f64 = 25;
94 try expect(@sqrt(a) == 5);
95 }
96}
97
98test "more @sqrt f16 tests" {
99 // TODO these are not all passing at comptime
100 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
101 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 2.0)), 1.414214, epsilon));
102 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 3.6)), 1.897367, epsilon));
103 try expect(@sqrt(@as(f16, 4.0)) == 2.0);
104 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 7.539840)), 2.745877, epsilon));
105 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 19.230934)), 4.385309, epsilon));
106 try expect(@sqrt(@as(f16, 64.0)) == 8.0);
107 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 64.1)), 8.006248, epsilon));
108 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 8942.230469)), 94.563370, epsilon));
109
110 // special cases
111 try expect(math.isPositiveInf(@sqrt(@as(f16, math.inf(f16)))));
112 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
113 try expect(@sqrt(@as(f16, -0.0)) == -0.0);
114 try expect(math.isNan(@sqrt(@as(f16, -1.0))));
115 try expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
116}
test/behavior/floatop_stage1.zig-34
...@@ -14,20 +14,6 @@ test "@sqrt" {...@@ -14,20 +14,6 @@ test "@sqrt" {
14}14}
1515
16fn testSqrt() !void {16fn testSqrt() !void {
17 {
18 var a: f16 = 4;
19 try expect(@sqrt(a) == 2);
20 }
21 {
22 var a: f32 = 9;
23 try expect(@sqrt(a) == 3);
24 var b: f32 = 1.1;
25 try expect(math.approxEqAbs(f32, @sqrt(b), 1.0488088481701516, epsilon));
26 }
27 {
28 var a: f64 = 25;
29 try expect(@sqrt(a) == 5);
30 }
31 if (has_f80_rt) {17 if (has_f80_rt) {
32 var a: f80 = 25;18 var a: f80 = 25;
33 try expect(@sqrt(a) == 5);19 try expect(@sqrt(a) == 5);
...@@ -51,26 +37,6 @@ fn testSqrt() !void {...@@ -51,26 +37,6 @@ fn testSqrt() !void {
51 }37 }
52}38}
5339
54test "more @sqrt f16 tests" {
55 // TODO these are not all passing at comptime
56 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
57 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 2.0)), 1.414214, epsilon));
58 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 3.6)), 1.897367, epsilon));
59 try expect(@sqrt(@as(f16, 4.0)) == 2.0);
60 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 7.539840)), 2.745877, epsilon));
61 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 19.230934)), 4.385309, epsilon));
62 try expect(@sqrt(@as(f16, 64.0)) == 8.0);
63 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 64.1)), 8.006248, epsilon));
64 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 8942.230469)), 94.563370, epsilon));
65
66 // special cases
67 try expect(math.isPositiveInf(@sqrt(@as(f16, math.inf(f16)))));
68 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
69 try expect(@sqrt(@as(f16, -0.0)) == -0.0);
70 try expect(math.isNan(@sqrt(@as(f16, -1.0))));
71 try expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
72}
73
74test "@sin" {40test "@sin" {
75 comptime try testSin();41 comptime try testSin();
76 try testSin();42 try testSin();
test/behavior/math.zig+6-6
...@@ -792,8 +792,6 @@ fn remdiv(comptime T: type) !void {...@@ -792,8 +792,6 @@ fn remdiv(comptime T: type) !void {
792}792}
793793
794test "@sqrt" {794test "@sqrt" {
795 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
796
797 try testSqrt(f64, 12.0);795 try testSqrt(f64, 12.0);
798 comptime try testSqrt(f64, 12.0);796 comptime try testSqrt(f64, 12.0);
799 try testSqrt(f32, 13.0);797 try testSqrt(f32, 13.0);
...@@ -801,10 +799,12 @@ test "@sqrt" {...@@ -801,10 +799,12 @@ test "@sqrt" {
801 try testSqrt(f16, 13.0);799 try testSqrt(f16, 13.0);
802 comptime try testSqrt(f16, 13.0);800 comptime try testSqrt(f16, 13.0);
803801
804 const x = 14.0;802 if (builtin.zig_backend == .stage1) {
805 const y = x * x;803 const x = 14.0;
806 const z = @sqrt(y);804 const y = x * x;
807 comptime try expect(z == x);805 const z = @sqrt(y);
806 comptime try expect(z == x);
807 }
808}808}
809809
810fn testSqrt(comptime T: type, x: T) !void {810fn testSqrt(comptime T: type, x: T) !void {