| author | |
| committer | |
| log | 9bbfbacae0707cf0712e4d6b227b17d097708c7e |
| tree | d61c60e53f167ecb3c5b24235f5fa30f01fd8c23 |
| parent | dd49ed1c642d917af40bf4a0e03d013f40b3903b |
| parent | a028488384c599aa997ba04bbd5ed98f2172630c |
| signature |
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 | 237 | /// Uses the `ty_op` field. |
| 238 | 238 | popcount, |
| 239 | 239 | |
| 240 | /// Computes the square root of a floating point number. | |
| 241 | /// Uses the `un_op` field. | |
| 242 | sqrt, | |
| 243 | ||
| 240 | 244 | /// `<`. Result type is always bool. |
| 241 | 245 | /// Uses the `bin_op` field. |
| 242 | 246 | cmp_lt, |
| ... | ... | @@ -749,6 +753,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 749 | 753 | .max, |
| 750 | 754 | => return air.typeOf(datas[inst].bin_op.lhs), |
| 751 | 755 | |
| 756 | .sqrt => return air.typeOf(datas[inst].un_op), | |
| 757 | ||
| 752 | 758 | .cmp_lt, |
| 753 | 759 | .cmp_lte, |
| 754 | 760 | .cmp_eq, |
src/Liveness.zig+1| ... | ... | @@ -338,6 +338,7 @@ fn analyzeInst( |
| 338 | 338 | .ret_load, |
| 339 | 339 | .tag_name, |
| 340 | 340 | .error_name, |
| 341 | .sqrt, | |
| 341 | 342 | => { |
| 342 | 343 | const operand = inst_datas[inst].un_op; |
| 343 | 344 | return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none }); |
src/Sema.zig+37-16| ... | ... | @@ -745,19 +745,19 @@ fn analyzeBodyInner( |
| 745 | 745 | .clz => try sema.zirClzCtz(block, inst, .clz, Value.clz), |
| 746 | 746 | .ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz), |
| 747 | 747 | |
| 748 | .sqrt => try sema.zirUnaryMath(block, inst), | |
| 749 | .sin => try sema.zirUnaryMath(block, inst), | |
| 750 | .cos => try sema.zirUnaryMath(block, inst), | |
| 751 | .exp => try sema.zirUnaryMath(block, inst), | |
| 752 | .exp2 => try sema.zirUnaryMath(block, inst), | |
| 753 | .log => try sema.zirUnaryMath(block, inst), | |
| 754 | .log2 => try sema.zirUnaryMath(block, inst), | |
| 755 | .log10 => try sema.zirUnaryMath(block, inst), | |
| 756 | .fabs => try sema.zirUnaryMath(block, inst), | |
| 757 | .floor => try sema.zirUnaryMath(block, inst), | |
| 758 | .ceil => try sema.zirUnaryMath(block, inst), | |
| 759 | .trunc => try sema.zirUnaryMath(block, inst), | |
| 760 | .round => try sema.zirUnaryMath(block, inst), | |
| 748 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), | |
| 749 | .sin => @panic("TODO"), | |
| 750 | .cos => @panic("TODO"), | |
| 751 | .exp => @panic("TODO"), | |
| 752 | .exp2 => @panic("TODO"), | |
| 753 | .log => @panic("TODO"), | |
| 754 | .log2 => @panic("TODO"), | |
| 755 | .log10 => @panic("TODO"), | |
| 756 | .fabs => @panic("TODO"), | |
| 757 | .floor => @panic("TODO"), | |
| 758 | .ceil => @panic("TODO"), | |
| 759 | .trunc => @panic("TODO"), | |
| 760 | .round => @panic("TODO"), | |
| 761 | 761 | |
| 762 | 762 | .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent), |
| 763 | 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 | 11010 | return block.addUnOp(.error_name, operand); |
| 11011 | 11011 | } |
| 11012 | 11012 | |
| 11013 | fn zirUnaryMath(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 11013 | fn 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 | 11023 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 11015 | const src = inst_data.src(); | |
| 11016 | return sema.fail(block, src, "TODO: Sema.zirUnaryMath", .{}); | |
| 11024 | const operand = sema.resolveInst(inst_data.operand); | |
| 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 | } |
| 11018 | 11039 | |
| 11019 | 11040 | fn 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 | 528 | .max => try self.airMax(inst), |
| 529 | 529 | .slice => try self.airSlice(inst), |
| 530 | 530 | |
| 531 | .sqrt => try self.airUnaryMath(inst), | |
| 532 | ||
| 531 | 533 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 532 | 534 | .sub_with_overflow => try self.airSubWithOverflow(inst), |
| 533 | 535 | .mul_with_overflow => try self.airMulWithOverflow(inst), |
| ... | ... | @@ -1223,6 +1225,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 1223 | 1225 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1224 | 1226 | } |
| 1225 | 1227 | |
| 1228 | fn 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 | ||
| 1226 | 1237 | fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool { |
| 1227 | 1238 | if (!self.liveness.operandDies(inst, op_index)) |
| 1228 | 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 | 520 | .max => try self.airMax(inst), |
| 521 | 521 | .slice => try self.airSlice(inst), |
| 522 | 522 | |
| 523 | .sqrt => try self.airUnaryMath(inst), | |
| 524 | ||
| 523 | 525 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 524 | 526 | .sub_with_overflow => try self.airSubWithOverflow(inst), |
| 525 | 527 | .mul_with_overflow => try self.airMulWithOverflow(inst), |
| ... | ... | @@ -1377,6 +1379,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 1377 | 1379 | // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1378 | 1380 | } |
| 1379 | 1381 | |
| 1382 | fn 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 | ||
| 1380 | 1391 | fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool { |
| 1381 | 1392 | if (!self.liveness.operandDies(inst, op_index)) |
| 1382 | 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 | 507 | .max => try self.airMax(inst), |
| 508 | 508 | .slice => try self.airSlice(inst), |
| 509 | 509 | |
| 510 | .sqrt => try self.airUnaryMath(inst), | |
| 511 | ||
| 510 | 512 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 511 | 513 | .sub_with_overflow => try self.airSubWithOverflow(inst), |
| 512 | 514 | .mul_with_overflow => try self.airMulWithOverflow(inst), |
| ... | ... | @@ -1166,6 +1168,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 1166 | 1168 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1167 | 1169 | } |
| 1168 | 1170 | |
| 1171 | fn 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 | ||
| 1169 | 1180 | fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool { |
| 1170 | 1181 | if (!self.liveness.operandDies(inst, op_index)) |
| 1171 | 1182 | return false; |
src/arch/wasm/CodeGen.zig+2| ... | ... | @@ -1681,6 +1681,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1681 | 1681 | .unwrap_errunion_payload_ptr, |
| 1682 | 1682 | .unwrap_errunion_err_ptr, |
| 1683 | 1683 | |
| 1684 | .sqrt, | |
| 1685 | ||
| 1684 | 1686 | .ptr_slice_len_ptr, |
| 1685 | 1687 | .ptr_slice_ptr_ptr, |
| 1686 | 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 | 599 | .max => try self.airMax(inst), |
| 600 | 600 | .slice => try self.airSlice(inst), |
| 601 | 601 | |
| 602 | .sqrt => try self.airUnaryMath(inst), | |
| 603 | ||
| 602 | 604 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 603 | 605 | .sub_with_overflow => try self.airSubWithOverflow(inst), |
| 604 | 606 | .mul_with_overflow => try self.airMulWithOverflow(inst), |
| ... | ... | @@ -1578,6 +1580,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 1578 | 1580 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1579 | 1581 | } |
| 1580 | 1582 | |
| 1583 | fn 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 | ||
| 1581 | 1592 | fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool { |
| 1582 | 1593 | if (!self.liveness.operandDies(inst, op_index)) |
| 1583 | 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 | 1446 | .mul_sat => try airSatOp(f, inst, "muls_"), |
| 1447 | 1447 | .shl_sat => try airSatOp(f, inst, "shls_"), |
| 1448 | 1448 | |
| 1449 | .sqrt => try airSqrt(f, inst), | |
| 1450 | ||
| 1449 | 1451 | .add_with_overflow => try airAddWithOverflow(f, inst), |
| 1450 | 1452 | .sub_with_overflow => try airSubWithOverflow(f, inst), |
| 1451 | 1453 | .mul_with_overflow => try airMulWithOverflow(f, inst), |
| ... | ... | @@ -3393,6 +3395,12 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3393 | 3395 | return CValue.none; |
| 3394 | 3396 | } |
| 3395 | 3397 | |
| 3398 | fn airSqrt(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 3399 | _ = f; | |
| 3400 | _ = inst; | |
| 3401 | return f.fail("TODO: C backend: implement sqrt", .{}); | |
| 3402 | } | |
| 3403 | ||
| 3396 | 3404 | fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 { |
| 3397 | 3405 | return switch (order) { |
| 3398 | 3406 | .Unordered => "memory_order_relaxed", |
src/codegen/llvm.zig+16| ... | ... | @@ -2050,6 +2050,8 @@ pub const FuncGen = struct { |
| 2050 | 2050 | .shr => try self.airShr(inst, false), |
| 2051 | 2051 | .shr_exact => try self.airShr(inst, true), |
| 2052 | 2052 | |
| 2053 | .sqrt => try self.airSqrt(inst), | |
| 2054 | ||
| 2053 | 2055 | .cmp_eq => try self.airCmp(inst, .eq), |
| 2054 | 2056 | .cmp_gt => try self.airCmp(inst, .gt), |
| 2055 | 2057 | .cmp_gte => try self.airCmp(inst, .gte), |
| ... | ... | @@ -4211,6 +4213,20 @@ pub const FuncGen = struct { |
| 4211 | 4213 | } |
| 4212 | 4214 | } |
| 4213 | 4215 | |
| 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 | 4230 | fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, prefix: [*:0]const u8) !?*const llvm.Value { |
| 4215 | 4231 | if (self.liveness.isUnused(inst)) return null; |
| 4216 | 4232 |
src/print_air.zig+1| ... | ... | @@ -158,6 +158,7 @@ const Writer = struct { |
| 158 | 158 | .ret_load, |
| 159 | 159 | .tag_name, |
| 160 | 160 | .error_name, |
| 161 | .sqrt, | |
| 161 | 162 | => try w.writeUnOp(s, inst), |
| 162 | 163 | |
| 163 | 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 | 6996 | const char *func_name; |
| 6997 | 6997 | switch (instruction->fn_id) { |
| 6998 | 6998 | case BuiltinFnIdSqrt: |
| 6999 | func_name = "__sqrt"; | |
| 6999 | func_name = "__sqrtx"; | |
| 7000 | 7000 | break; |
| 7001 | 7001 | case BuiltinFnIdSin: |
| 7002 | 7002 | func_name = "__sinx"; |
src/value.zig+32| ... | ... | @@ -3265,6 +3265,38 @@ pub const Value = extern union { |
| 3265 | 3265 | } |
| 3266 | 3266 | } |
| 3267 | 3267 | |
| 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 | 3300 | /// This type is not copyable since it may contain pointers to its inner data. |
| 3269 | 3301 | pub const Payload = struct { |
| 3270 | 3302 | tag: Tag, |
test/behavior/floatop.zig+42| ... | ... | @@ -72,3 +72,45 @@ test "negative f128 floatToInt at compile-time" { |
| 72 | 72 | var b = @floatToInt(i64, a); |
| 73 | 73 | try expect(@as(i64, -2) == b); |
| 74 | 74 | } |
| 75 | ||
| 76 | test "@sqrt" { | |
| 77 | comptime try testSqrt(); | |
| 78 | try testSqrt(); | |
| 79 | } | |
| 80 | ||
| 81 | fn 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 | ||
| 98 | test "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 | 14 | } |
| 15 | 15 | |
| 16 | 16 | fn 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 | 17 | if (has_f80_rt) { |
| 32 | 18 | var a: f80 = 25; |
| 33 | 19 | try expect(@sqrt(a) == 5); |
| ... | ... | @@ -51,26 +37,6 @@ fn testSqrt() !void { |
| 51 | 37 | } |
| 52 | 38 | } |
| 53 | 39 | |
| 54 | test "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 | ||
| 74 | 40 | test "@sin" { |
| 75 | 41 | comptime try testSin(); |
| 76 | 42 | try testSin(); |
test/behavior/math.zig+6-6| ... | ... | @@ -792,8 +792,6 @@ fn remdiv(comptime T: type) !void { |
| 792 | 792 | } |
| 793 | 793 | |
| 794 | 794 | test "@sqrt" { |
| 795 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 796 | ||
| 797 | 795 | try testSqrt(f64, 12.0); |
| 798 | 796 | comptime try testSqrt(f64, 12.0); |
| 799 | 797 | try testSqrt(f32, 13.0); |
| ... | ... | @@ -801,10 +799,12 @@ test "@sqrt" { |
| 801 | 799 | try testSqrt(f16, 13.0); |
| 802 | 800 | comptime try testSqrt(f16, 13.0); |
| 803 | 801 | |
| 804 | const x = 14.0; | |
| 805 | const y = x * x; | |
| 806 | const z = @sqrt(y); | |
| 807 | comptime try expect(z == x); | |
| 802 | if (builtin.zig_backend == .stage1) { | |
| 803 | const x = 14.0; | |
| 804 | const y = x * x; | |
| 805 | const z = @sqrt(y); | |
| 806 | comptime try expect(z == x); | |
| 807 | } | |
| 808 | 808 | } |
| 809 | 809 | |
| 810 | 810 | fn testSqrt(comptime T: type, x: T) !void { |