| author | |
| committer | |
| log | 7f0cf395aa74eb5ea250bd28f7525b3036790a6a |
| tree | e2faf4e4a19836331d3e47180438fab4db4fb178 |
| parent | 44b5fdf3266f11607313bc9990a876b5a7f9e174 |
- Merge `floatop.zig` and `floatop_stage1.zig` since most tests now pass
on stage2.
- Add more behavior tests for a bunch of functions.15 files changed, 917 insertions(+), 494 deletions(-)
src/Air.zig+51-2| ... | @@ -237,9 +237,45 @@ pub const Inst = struct { | ... | @@ -237,9 +237,45 @@ pub const Inst = struct { |
| 237 | /// Uses the `ty_op` field. | 237 | /// Uses the `ty_op` field. |
| 238 | popcount, | 238 | popcount, |
| 239 | 239 | ||
| 240 | /// Computes the square root of a floating point number. | 240 | /// Square root of a floating point number. |
| 241 | /// Uses the `un_op` field. | 241 | /// Uses the `un_op` field. |
| 242 | sqrt, | 242 | sqrt, |
| 243 | /// Sine a floating point number. | ||
| 244 | /// Uses the `un_op` field. | ||
| 245 | sin, | ||
| 246 | /// Cosine a floating point number. | ||
| 247 | /// Uses the `un_op` field. | ||
| 248 | cos, | ||
| 249 | /// Base e exponential of a floating point number. | ||
| 250 | /// Uses the `un_op` field. | ||
| 251 | exp, | ||
| 252 | /// Base 2 exponential of a floating point number. | ||
| 253 | /// Uses the `un_op` field. | ||
| 254 | exp2, | ||
| 255 | /// Natural (base e) logarithm of a floating point number. | ||
| 256 | /// Uses the `un_op` field. | ||
| 257 | log, | ||
| 258 | /// Base 2 logarithm of a floating point number. | ||
| 259 | /// Uses the `un_op` field. | ||
| 260 | log2, | ||
| 261 | /// Base 10 logarithm of a floating point number. | ||
| 262 | /// Uses the `un_op` field. | ||
| 263 | log10, | ||
| 264 | /// Aboslute value of a floating point number. | ||
| 265 | /// Uses the `un_op` field. | ||
| 266 | fabs, | ||
| 267 | /// Floor: rounds a floating pointer number down to the nearest integer. | ||
| 268 | /// Uses the `un_op` field. | ||
| 269 | floor, | ||
| 270 | /// Ceiling: rounds a floating pointer number up to the nearest integer. | ||
| 271 | /// Uses the `un_op` field. | ||
| 272 | ceil, | ||
| 273 | /// Rounds a floating pointer number to the nearest integer. | ||
| 274 | /// Uses the `un_op` field. | ||
| 275 | round, | ||
| 276 | /// Rounds a floating pointer number to the nearest integer towards zero. | ||
| 277 | /// Uses the `un_op` field. | ||
| 278 | trunc_float, | ||
| 243 | 279 | ||
| 244 | /// `<`. Result type is always bool. | 280 | /// `<`. Result type is always bool. |
| 245 | /// Uses the `bin_op` field. | 281 | /// Uses the `bin_op` field. |
| ... | @@ -754,7 +790,20 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -754,7 +790,20 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 754 | .max, | 790 | .max, |
| 755 | => return air.typeOf(datas[inst].bin_op.lhs), | 791 | => return air.typeOf(datas[inst].bin_op.lhs), |
| 756 | 792 | ||
| 757 | .sqrt => return air.typeOf(datas[inst].un_op), | 793 | .sqrt, |
| 794 | .sin, | ||
| 795 | .cos, | ||
| 796 | .exp, | ||
| 797 | .exp2, | ||
| 798 | .log, | ||
| 799 | .log2, | ||
| 800 | .log10, | ||
| 801 | .fabs, | ||
| 802 | .floor, | ||
| 803 | .ceil, | ||
| 804 | .round, | ||
| 805 | .trunc_float, | ||
| 806 | => return air.typeOf(datas[inst].un_op), | ||
| 758 | 807 | ||
| 759 | .cmp_lt, | 808 | .cmp_lt, |
| 760 | .cmp_lte, | 809 | .cmp_lte, |
src/Liveness.zig+12| ... | @@ -339,6 +339,18 @@ fn analyzeInst( | ... | @@ -339,6 +339,18 @@ fn analyzeInst( |
| 339 | .tag_name, | 339 | .tag_name, |
| 340 | .error_name, | 340 | .error_name, |
| 341 | .sqrt, | 341 | .sqrt, |
| 342 | .sin, | ||
| 343 | .cos, | ||
| 344 | .exp, | ||
| 345 | .exp2, | ||
| 346 | .log, | ||
| 347 | .log2, | ||
| 348 | .log10, | ||
| 349 | .fabs, | ||
| 350 | .floor, | ||
| 351 | .ceil, | ||
| 352 | .round, | ||
| 353 | .trunc_float, | ||
| 342 | => { | 354 | => { |
| 343 | const operand = inst_datas[inst].un_op; | 355 | const operand = inst_datas[inst].un_op; |
| 344 | return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none }); | 356 | return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none }); |
src/Sema.zig+12-12| ... | @@ -747,18 +747,18 @@ fn analyzeBodyInner( | ... | @@ -747,18 +747,18 @@ fn analyzeBodyInner( |
| 747 | .ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz), | 747 | .ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz), |
| 748 | 748 | ||
| 749 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), | 749 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), |
| 750 | .sin => @panic("TODO"), | 750 | .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin), |
| 751 | .cos => @panic("TODO"), | 751 | .cos => try sema.zirUnaryMath(block, inst, .cos, Value.cos), |
| 752 | .exp => @panic("TODO"), | 752 | .exp => try sema.zirUnaryMath(block, inst, .exp, Value.exp), |
| 753 | .exp2 => @panic("TODO"), | 753 | .exp2 => try sema.zirUnaryMath(block, inst, .exp2, Value.exp2), |
| 754 | .log => @panic("TODO"), | 754 | .log => try sema.zirUnaryMath(block, inst, .log, Value.log), |
| 755 | .log2 => @panic("TODO"), | 755 | .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2), |
| 756 | .log10 => @panic("TODO"), | 756 | .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10), |
| 757 | .fabs => @panic("TODO"), | 757 | .fabs => try sema.zirUnaryMath(block, inst, .fabs, Value.fabs), |
| 758 | .floor => @panic("TODO"), | 758 | .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor), |
| 759 | .ceil => @panic("TODO"), | 759 | .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil), |
| 760 | .trunc => @panic("TODO"), | 760 | .round => try sema.zirUnaryMath(block, inst, .round, Value.round), |
| 761 | .round => @panic("TODO"), | 761 | .trunc => try sema.zirUnaryMath(block, inst, .trunc_float, Value.trunc), |
| 762 | 762 | ||
| 763 | .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent), | 763 | .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent), |
| 764 | .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon), | 764 | .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon), |
src/arch/aarch64/CodeGen.zig+14-1| ... | @@ -528,7 +528,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -528,7 +528,20 @@ 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), |
| 530 | 530 | ||
| 531 | .sqrt => try self.airUnaryMath(inst), | 531 | .sqrt, |
| 532 | .sin, | ||
| 533 | .cos, | ||
| 534 | .exp, | ||
| 535 | .exp2, | ||
| 536 | .log, | ||
| 537 | .log2, | ||
| 538 | .log10, | ||
| 539 | .fabs, | ||
| 540 | .floor, | ||
| 541 | .ceil, | ||
| 542 | .round, | ||
| 543 | .trunc_float | ||
| 544 | => try self.airUnaryMath(inst), | ||
| 532 | 545 | ||
| 533 | .add_with_overflow => try self.airAddWithOverflow(inst), | 546 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 534 | .sub_with_overflow => try self.airSubWithOverflow(inst), | 547 | .sub_with_overflow => try self.airSubWithOverflow(inst), |
src/arch/arm/CodeGen.zig+14-1| ... | @@ -520,7 +520,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -520,7 +520,20 @@ 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), |
| 522 | 522 | ||
| 523 | .sqrt => try self.airUnaryMath(inst), | 523 | .sqrt, |
| 524 | .sin, | ||
| 525 | .cos, | ||
| 526 | .exp, | ||
| 527 | .exp2, | ||
| 528 | .log, | ||
| 529 | .log2, | ||
| 530 | .log10, | ||
| 531 | .fabs, | ||
| 532 | .floor, | ||
| 533 | .ceil, | ||
| 534 | .round, | ||
| 535 | .trunc_float, | ||
| 536 | => try self.airUnaryMath(inst), | ||
| 524 | 537 | ||
| 525 | .add_with_overflow => try self.airAddWithOverflow(inst), | 538 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 526 | .sub_with_overflow => try self.airSubWithOverflow(inst), | 539 | .sub_with_overflow => try self.airSubWithOverflow(inst), |
src/arch/riscv64/CodeGen.zig+14-1| ... | @@ -507,7 +507,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -507,7 +507,20 @@ 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), |
| 509 | 509 | ||
| 510 | .sqrt => try self.airUnaryMath(inst), | 510 | .sqrt, |
| 511 | .sin, | ||
| 512 | .cos, | ||
| 513 | .exp, | ||
| 514 | .exp2, | ||
| 515 | .log, | ||
| 516 | .log2, | ||
| 517 | .log10, | ||
| 518 | .fabs, | ||
| 519 | .floor, | ||
| 520 | .ceil, | ||
| 521 | .round, | ||
| 522 | .trunc_float, | ||
| 523 | => try self.airUnaryMath(inst), | ||
| 511 | 524 | ||
| 512 | .add_with_overflow => try self.airAddWithOverflow(inst), | 525 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 513 | .sub_with_overflow => try self.airSubWithOverflow(inst), | 526 | .sub_with_overflow => try self.airSubWithOverflow(inst), |
src/arch/wasm/CodeGen.zig+12| ... | @@ -1679,6 +1679,18 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1679,6 +1679,18 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1679 | .unwrap_errunion_err_ptr, | 1679 | .unwrap_errunion_err_ptr, |
| 1680 | 1680 | ||
| 1681 | .sqrt, | 1681 | .sqrt, |
| 1682 | .sin, | ||
| 1683 | .cos, | ||
| 1684 | .exp, | ||
| 1685 | .exp2, | ||
| 1686 | .log, | ||
| 1687 | .log2, | ||
| 1688 | .log10, | ||
| 1689 | .fabs, | ||
| 1690 | .floor, | ||
| 1691 | .ceil, | ||
| 1692 | .round, | ||
| 1693 | .trunc_float, | ||
| 1682 | 1694 | ||
| 1683 | .ptr_slice_len_ptr, | 1695 | .ptr_slice_len_ptr, |
| 1684 | .ptr_slice_ptr_ptr, | 1696 | .ptr_slice_ptr_ptr, |
src/arch/x86_64/CodeGen.zig+14-1| ... | @@ -599,7 +599,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -599,7 +599,20 @@ 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), |
| 601 | 601 | ||
| 602 | .sqrt => try self.airUnaryMath(inst), | 602 | .sqrt, |
| 603 | .sin, | ||
| 604 | .cos, | ||
| 605 | .exp, | ||
| 606 | .exp2, | ||
| 607 | .log, | ||
| 608 | .log2, | ||
| 609 | .log10, | ||
| 610 | .fabs, | ||
| 611 | .floor, | ||
| 612 | .ceil, | ||
| 613 | .round, | ||
| 614 | .trunc_float, | ||
| 615 | => try self.airUnaryMath(inst), | ||
| 603 | 616 | ||
| 604 | .add_with_overflow => try self.airAddWithOverflow(inst), | 617 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 605 | .sub_with_overflow => try self.airSubWithOverflow(inst), | 618 | .sub_with_overflow => try self.airSubWithOverflow(inst), |
src/codegen/c.zig+14-7| ... | @@ -1446,7 +1446,20 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -1446,7 +1446,20 @@ 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_"), |
| 1448 | 1448 | ||
| 1449 | .sqrt => try airSqrt(f, inst), | 1449 | .sqrt, |
| 1450 | .sin, | ||
| 1451 | .cos, | ||
| 1452 | .exp, | ||
| 1453 | .exp2, | ||
| 1454 | .log, | ||
| 1455 | .log2, | ||
| 1456 | .log10, | ||
| 1457 | .fabs, | ||
| 1458 | .floor, | ||
| 1459 | .ceil, | ||
| 1460 | .round, | ||
| 1461 | .trunc_float, | ||
| 1462 | => |tag| return f.fail("TODO: C backend: implement unary op for tag '{s}'", .{@tagName(tag)}), | ||
| 1450 | 1463 | ||
| 1451 | .add_with_overflow => try airAddWithOverflow(f, inst), | 1464 | .add_with_overflow => try airAddWithOverflow(f, inst), |
| 1452 | .sub_with_overflow => try airSubWithOverflow(f, inst), | 1465 | .sub_with_overflow => try airSubWithOverflow(f, inst), |
| ... | @@ -3395,12 +3408,6 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3395,12 +3408,6 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3395 | return CValue.none; | 3408 | return CValue.none; |
| 3396 | } | 3409 | } |
| 3397 | 3410 | ||
| 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 | |||
| 3404 | fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 { | 3411 | fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 { |
| 3405 | return switch (order) { | 3412 | return switch (order) { |
| 3406 | .Unordered => "memory_order_relaxed", | 3413 | .Unordered => "memory_order_relaxed", |
src/codegen/llvm.zig+15-3| ... | @@ -2050,7 +2050,19 @@ pub const FuncGen = struct { | ... | @@ -2050,7 +2050,19 @@ 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), |
| 2052 | 2052 | ||
| 2053 | .sqrt => try self.airSqrt(inst), | 2053 | .sqrt => try self.airUnaryOp(inst, "llvm.sqrt"), |
| 2054 | .sin => try self.airUnaryOp(inst, "llvm.sin"), | ||
| 2055 | .cos => try self.airUnaryOp(inst, "llvm.cos"), | ||
| 2056 | .exp => try self.airUnaryOp(inst, "llvm.exp"), | ||
| 2057 | .exp2 => try self.airUnaryOp(inst, "llvm.exp2"), | ||
| 2058 | .log => try self.airUnaryOp(inst, "llvm.log"), | ||
| 2059 | .log2 => try self.airUnaryOp(inst, "llvm.log2"), | ||
| 2060 | .log10 => try self.airUnaryOp(inst, "llvm.log10"), | ||
| 2061 | .fabs => try self.airUnaryOp(inst, "llvm.fabs"), | ||
| 2062 | .floor => try self.airUnaryOp(inst, "llvm.floor"), | ||
| 2063 | .ceil => try self.airUnaryOp(inst, "llvm.ceil"), | ||
| 2064 | .round => try self.airUnaryOp(inst, "llvm.round"), | ||
| 2065 | .trunc_float => try self.airUnaryOp(inst, "llvm.trunc"), | ||
| 2054 | 2066 | ||
| 2055 | .cmp_eq => try self.airCmp(inst, .eq), | 2067 | .cmp_eq => try self.airCmp(inst, .eq), |
| 2056 | .cmp_gt => try self.airCmp(inst, .gt), | 2068 | .cmp_gt => try self.airCmp(inst, .gt), |
| ... | @@ -4213,7 +4225,7 @@ pub const FuncGen = struct { | ... | @@ -4213,7 +4225,7 @@ pub const FuncGen = struct { |
| 4213 | } | 4225 | } |
| 4214 | } | 4226 | } |
| 4215 | 4227 | ||
| 4216 | fn airSqrt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 4228 | fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value { |
| 4217 | if (self.liveness.isUnused(inst)) return null; | 4229 | if (self.liveness.isUnused(inst)) return null; |
| 4218 | 4230 | ||
| 4219 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 4231 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| ... | @@ -4221,7 +4233,7 @@ pub const FuncGen = struct { | ... | @@ -4221,7 +4233,7 @@ pub const FuncGen = struct { |
| 4221 | const operand_ty = self.air.typeOf(un_op); | 4233 | const operand_ty = self.air.typeOf(un_op); |
| 4222 | 4234 | ||
| 4223 | const operand_llvm_ty = try self.dg.llvmType(operand_ty); | 4235 | const operand_llvm_ty = try self.dg.llvmType(operand_ty); |
| 4224 | const fn_val = self.getIntrinsic("llvm.sqrt", &.{operand_llvm_ty}); | 4236 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); |
| 4225 | const params = [_]*const llvm.Value{operand}; | 4237 | const params = [_]*const llvm.Value{operand}; |
| 4226 | 4238 | ||
| 4227 | return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, ""); | 4239 | return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, ""); |
src/print_air.zig+12| ... | @@ -159,6 +159,18 @@ const Writer = struct { | ... | @@ -159,6 +159,18 @@ const Writer = struct { |
| 159 | .tag_name, | 159 | .tag_name, |
| 160 | .error_name, | 160 | .error_name, |
| 161 | .sqrt, | 161 | .sqrt, |
| 162 | .sin, | ||
| 163 | .cos, | ||
| 164 | .exp, | ||
| 165 | .exp2, | ||
| 166 | .log, | ||
| 167 | .log2, | ||
| 168 | .log10, | ||
| 169 | .fabs, | ||
| 170 | .floor, | ||
| 171 | .ceil, | ||
| 172 | .round, | ||
| 173 | .trunc_float, | ||
| 162 | => try w.writeUnOp(s, inst), | 174 | => try w.writeUnOp(s, inst), |
| 163 | 175 | ||
| 164 | .breakpoint, | 176 | .breakpoint, |
src/value.zig+384| ... | @@ -3308,6 +3308,390 @@ pub const Value = extern union { | ... | @@ -3308,6 +3308,390 @@ pub const Value = extern union { |
| 3308 | } | 3308 | } |
| 3309 | } | 3309 | } |
| 3310 | 3310 | ||
| 3311 | pub fn sin(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3312 | switch (float_type.floatBits(target)) { | ||
| 3313 | 16 => { | ||
| 3314 | const f = val.toFloat(f16); | ||
| 3315 | return Value.Tag.float_16.create(arena, @sin(f)); | ||
| 3316 | }, | ||
| 3317 | 32 => { | ||
| 3318 | const f = val.toFloat(f32); | ||
| 3319 | return Value.Tag.float_32.create(arena, @sin(f)); | ||
| 3320 | }, | ||
| 3321 | 64 => { | ||
| 3322 | const f = val.toFloat(f64); | ||
| 3323 | return Value.Tag.float_64.create(arena, @sin(f)); | ||
| 3324 | }, | ||
| 3325 | 80 => { | ||
| 3326 | if (true) { | ||
| 3327 | @panic("TODO implement compiler_rt sin for f80"); | ||
| 3328 | } | ||
| 3329 | const f = val.toFloat(f80); | ||
| 3330 | return Value.Tag.float_80.create(arena, @sin(f)); | ||
| 3331 | }, | ||
| 3332 | 128 => { | ||
| 3333 | if (true) { | ||
| 3334 | @panic("TODO implement compiler_rt sin for f128"); | ||
| 3335 | } | ||
| 3336 | const f = val.toFloat(f128); | ||
| 3337 | return Value.Tag.float_128.create(arena, @sin(f)); | ||
| 3338 | }, | ||
| 3339 | else => unreachable, | ||
| 3340 | } | ||
| 3341 | } | ||
| 3342 | |||
| 3343 | pub fn cos(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3344 | switch (float_type.floatBits(target)) { | ||
| 3345 | 16 => { | ||
| 3346 | const f = val.toFloat(f16); | ||
| 3347 | return Value.Tag.float_16.create(arena, @cos(f)); | ||
| 3348 | }, | ||
| 3349 | 32 => { | ||
| 3350 | const f = val.toFloat(f32); | ||
| 3351 | return Value.Tag.float_32.create(arena, @cos(f)); | ||
| 3352 | }, | ||
| 3353 | 64 => { | ||
| 3354 | const f = val.toFloat(f64); | ||
| 3355 | return Value.Tag.float_64.create(arena, @cos(f)); | ||
| 3356 | }, | ||
| 3357 | 80 => { | ||
| 3358 | if (true) { | ||
| 3359 | @panic("TODO implement compiler_rt cos for f80"); | ||
| 3360 | } | ||
| 3361 | const f = val.toFloat(f80); | ||
| 3362 | return Value.Tag.float_80.create(arena, @cos(f)); | ||
| 3363 | }, | ||
| 3364 | 128 => { | ||
| 3365 | if (true) { | ||
| 3366 | @panic("TODO implement compiler_rt cos for f128"); | ||
| 3367 | } | ||
| 3368 | const f = val.toFloat(f128); | ||
| 3369 | return Value.Tag.float_128.create(arena, @cos(f)); | ||
| 3370 | }, | ||
| 3371 | else => unreachable, | ||
| 3372 | } | ||
| 3373 | } | ||
| 3374 | |||
| 3375 | pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3376 | switch (float_type.floatBits(target)) { | ||
| 3377 | 16 => { | ||
| 3378 | const f = val.toFloat(f16); | ||
| 3379 | return Value.Tag.float_16.create(arena, @exp(f)); | ||
| 3380 | }, | ||
| 3381 | 32 => { | ||
| 3382 | const f = val.toFloat(f32); | ||
| 3383 | return Value.Tag.float_32.create(arena, @exp(f)); | ||
| 3384 | }, | ||
| 3385 | 64 => { | ||
| 3386 | const f = val.toFloat(f64); | ||
| 3387 | return Value.Tag.float_64.create(arena, @exp(f)); | ||
| 3388 | }, | ||
| 3389 | 80 => { | ||
| 3390 | if (true) { | ||
| 3391 | @panic("TODO implement compiler_rt exp for f80"); | ||
| 3392 | } | ||
| 3393 | const f = val.toFloat(f80); | ||
| 3394 | return Value.Tag.float_80.create(arena, @exp(f)); | ||
| 3395 | }, | ||
| 3396 | 128 => { | ||
| 3397 | if (true) { | ||
| 3398 | @panic("TODO implement compiler_rt exp for f128"); | ||
| 3399 | } | ||
| 3400 | const f = val.toFloat(f128); | ||
| 3401 | return Value.Tag.float_128.create(arena, @exp(f)); | ||
| 3402 | }, | ||
| 3403 | else => unreachable, | ||
| 3404 | } | ||
| 3405 | } | ||
| 3406 | |||
| 3407 | pub fn exp2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3408 | switch (float_type.floatBits(target)) { | ||
| 3409 | 16 => { | ||
| 3410 | const f = val.toFloat(f16); | ||
| 3411 | return Value.Tag.float_16.create(arena, @exp2(f)); | ||
| 3412 | }, | ||
| 3413 | 32 => { | ||
| 3414 | const f = val.toFloat(f32); | ||
| 3415 | return Value.Tag.float_32.create(arena, @exp2(f)); | ||
| 3416 | }, | ||
| 3417 | 64 => { | ||
| 3418 | const f = val.toFloat(f64); | ||
| 3419 | return Value.Tag.float_64.create(arena, @exp2(f)); | ||
| 3420 | }, | ||
| 3421 | 80 => { | ||
| 3422 | if (true) { | ||
| 3423 | @panic("TODO implement compiler_rt exp2 for f80"); | ||
| 3424 | } | ||
| 3425 | const f = val.toFloat(f80); | ||
| 3426 | return Value.Tag.float_80.create(arena, @exp2(f)); | ||
| 3427 | }, | ||
| 3428 | 128 => { | ||
| 3429 | if (true) { | ||
| 3430 | @panic("TODO implement compiler_rt exp2 for f128"); | ||
| 3431 | } | ||
| 3432 | const f = val.toFloat(f128); | ||
| 3433 | return Value.Tag.float_128.create(arena, @exp2(f)); | ||
| 3434 | }, | ||
| 3435 | else => unreachable, | ||
| 3436 | } | ||
| 3437 | } | ||
| 3438 | |||
| 3439 | pub fn log(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3440 | switch (float_type.floatBits(target)) { | ||
| 3441 | 16 => { | ||
| 3442 | const f = val.toFloat(f16); | ||
| 3443 | return Value.Tag.float_16.create(arena, @log(f)); | ||
| 3444 | }, | ||
| 3445 | 32 => { | ||
| 3446 | const f = val.toFloat(f32); | ||
| 3447 | return Value.Tag.float_32.create(arena, @log(f)); | ||
| 3448 | }, | ||
| 3449 | 64 => { | ||
| 3450 | const f = val.toFloat(f64); | ||
| 3451 | return Value.Tag.float_64.create(arena, @log(f)); | ||
| 3452 | }, | ||
| 3453 | 80 => { | ||
| 3454 | if (true) { | ||
| 3455 | @panic("TODO implement compiler_rt log for f80"); | ||
| 3456 | } | ||
| 3457 | const f = val.toFloat(f80); | ||
| 3458 | return Value.Tag.float_80.create(arena, @log(f)); | ||
| 3459 | }, | ||
| 3460 | 128 => { | ||
| 3461 | if (true) { | ||
| 3462 | @panic("TODO implement compiler_rt log for f128"); | ||
| 3463 | } | ||
| 3464 | const f = val.toFloat(f128); | ||
| 3465 | return Value.Tag.float_128.create(arena, @log(f)); | ||
| 3466 | }, | ||
| 3467 | else => unreachable, | ||
| 3468 | } | ||
| 3469 | } | ||
| 3470 | |||
| 3471 | pub fn log2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3472 | switch (float_type.floatBits(target)) { | ||
| 3473 | 16 => { | ||
| 3474 | const f = val.toFloat(f16); | ||
| 3475 | return Value.Tag.float_16.create(arena, @log2(f)); | ||
| 3476 | }, | ||
| 3477 | 32 => { | ||
| 3478 | const f = val.toFloat(f32); | ||
| 3479 | return Value.Tag.float_32.create(arena, @log2(f)); | ||
| 3480 | }, | ||
| 3481 | 64 => { | ||
| 3482 | const f = val.toFloat(f64); | ||
| 3483 | return Value.Tag.float_64.create(arena, @log2(f)); | ||
| 3484 | }, | ||
| 3485 | 80 => { | ||
| 3486 | if (true) { | ||
| 3487 | @panic("TODO implement compiler_rt log2 for f80"); | ||
| 3488 | } | ||
| 3489 | const f = val.toFloat(f80); | ||
| 3490 | return Value.Tag.float_80.create(arena, @log2(f)); | ||
| 3491 | }, | ||
| 3492 | 128 => { | ||
| 3493 | if (true) { | ||
| 3494 | @panic("TODO implement compiler_rt log2 for f128"); | ||
| 3495 | } | ||
| 3496 | const f = val.toFloat(f128); | ||
| 3497 | return Value.Tag.float_128.create(arena, @log2(f)); | ||
| 3498 | }, | ||
| 3499 | else => unreachable, | ||
| 3500 | } | ||
| 3501 | } | ||
| 3502 | |||
| 3503 | pub fn log10(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3504 | switch (float_type.floatBits(target)) { | ||
| 3505 | 16 => { | ||
| 3506 | const f = val.toFloat(f16); | ||
| 3507 | return Value.Tag.float_16.create(arena, @log10(f)); | ||
| 3508 | }, | ||
| 3509 | 32 => { | ||
| 3510 | const f = val.toFloat(f32); | ||
| 3511 | return Value.Tag.float_32.create(arena, @log10(f)); | ||
| 3512 | }, | ||
| 3513 | 64 => { | ||
| 3514 | const f = val.toFloat(f64); | ||
| 3515 | return Value.Tag.float_64.create(arena, @log10(f)); | ||
| 3516 | }, | ||
| 3517 | 80 => { | ||
| 3518 | if (true) { | ||
| 3519 | @panic("TODO implement compiler_rt log10 for f80"); | ||
| 3520 | } | ||
| 3521 | const f = val.toFloat(f80); | ||
| 3522 | return Value.Tag.float_80.create(arena, @log10(f)); | ||
| 3523 | }, | ||
| 3524 | 128 => { | ||
| 3525 | if (true) { | ||
| 3526 | @panic("TODO implement compiler_rt log10 for f128"); | ||
| 3527 | } | ||
| 3528 | const f = val.toFloat(f128); | ||
| 3529 | return Value.Tag.float_128.create(arena, @log10(f)); | ||
| 3530 | }, | ||
| 3531 | else => unreachable, | ||
| 3532 | } | ||
| 3533 | } | ||
| 3534 | |||
| 3535 | pub fn fabs(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3536 | switch (float_type.floatBits(target)) { | ||
| 3537 | 16 => { | ||
| 3538 | const f = val.toFloat(f16); | ||
| 3539 | return Value.Tag.float_16.create(arena, @fabs(f)); | ||
| 3540 | }, | ||
| 3541 | 32 => { | ||
| 3542 | const f = val.toFloat(f32); | ||
| 3543 | return Value.Tag.float_32.create(arena, @fabs(f)); | ||
| 3544 | }, | ||
| 3545 | 64 => { | ||
| 3546 | const f = val.toFloat(f64); | ||
| 3547 | return Value.Tag.float_64.create(arena, @fabs(f)); | ||
| 3548 | }, | ||
| 3549 | 80 => { | ||
| 3550 | if (true) { | ||
| 3551 | @panic("TODO implement compiler_rt fabs for f80"); | ||
| 3552 | } | ||
| 3553 | const f = val.toFloat(f80); | ||
| 3554 | return Value.Tag.float_80.create(arena, @fabs(f)); | ||
| 3555 | }, | ||
| 3556 | 128 => { | ||
| 3557 | if (true) { | ||
| 3558 | @panic("TODO implement compiler_rt fabs for f128"); | ||
| 3559 | } | ||
| 3560 | const f = val.toFloat(f128); | ||
| 3561 | return Value.Tag.float_128.create(arena, @fabs(f)); | ||
| 3562 | }, | ||
| 3563 | else => unreachable, | ||
| 3564 | } | ||
| 3565 | } | ||
| 3566 | |||
| 3567 | pub fn floor(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3568 | switch (float_type.floatBits(target)) { | ||
| 3569 | 16 => { | ||
| 3570 | const f = val.toFloat(f16); | ||
| 3571 | return Value.Tag.float_16.create(arena, @floor(f)); | ||
| 3572 | }, | ||
| 3573 | 32 => { | ||
| 3574 | const f = val.toFloat(f32); | ||
| 3575 | return Value.Tag.float_32.create(arena, @floor(f)); | ||
| 3576 | }, | ||
| 3577 | 64 => { | ||
| 3578 | const f = val.toFloat(f64); | ||
| 3579 | return Value.Tag.float_64.create(arena, @floor(f)); | ||
| 3580 | }, | ||
| 3581 | 80 => { | ||
| 3582 | if (true) { | ||
| 3583 | @panic("TODO implement compiler_rt floor for f80"); | ||
| 3584 | } | ||
| 3585 | const f = val.toFloat(f80); | ||
| 3586 | return Value.Tag.float_80.create(arena, @floor(f)); | ||
| 3587 | }, | ||
| 3588 | 128 => { | ||
| 3589 | if (true) { | ||
| 3590 | @panic("TODO implement compiler_rt floor for f128"); | ||
| 3591 | } | ||
| 3592 | const f = val.toFloat(f128); | ||
| 3593 | return Value.Tag.float_128.create(arena, @floor(f)); | ||
| 3594 | }, | ||
| 3595 | else => unreachable, | ||
| 3596 | } | ||
| 3597 | } | ||
| 3598 | |||
| 3599 | pub fn ceil(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3600 | switch (float_type.floatBits(target)) { | ||
| 3601 | 16 => { | ||
| 3602 | const f = val.toFloat(f16); | ||
| 3603 | return Value.Tag.float_16.create(arena, @ceil(f)); | ||
| 3604 | }, | ||
| 3605 | 32 => { | ||
| 3606 | const f = val.toFloat(f32); | ||
| 3607 | return Value.Tag.float_32.create(arena, @ceil(f)); | ||
| 3608 | }, | ||
| 3609 | 64 => { | ||
| 3610 | const f = val.toFloat(f64); | ||
| 3611 | return Value.Tag.float_64.create(arena, @ceil(f)); | ||
| 3612 | }, | ||
| 3613 | 80 => { | ||
| 3614 | if (true) { | ||
| 3615 | @panic("TODO implement compiler_rt ceil for f80"); | ||
| 3616 | } | ||
| 3617 | const f = val.toFloat(f80); | ||
| 3618 | return Value.Tag.float_80.create(arena, @ceil(f)); | ||
| 3619 | }, | ||
| 3620 | 128 => { | ||
| 3621 | if (true) { | ||
| 3622 | @panic("TODO implement compiler_rt ceil for f128"); | ||
| 3623 | } | ||
| 3624 | const f = val.toFloat(f128); | ||
| 3625 | return Value.Tag.float_128.create(arena, @ceil(f)); | ||
| 3626 | }, | ||
| 3627 | else => unreachable, | ||
| 3628 | } | ||
| 3629 | } | ||
| 3630 | |||
| 3631 | pub fn round(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3632 | switch (float_type.floatBits(target)) { | ||
| 3633 | 16 => { | ||
| 3634 | const f = val.toFloat(f16); | ||
| 3635 | return Value.Tag.float_16.create(arena, @round(f)); | ||
| 3636 | }, | ||
| 3637 | 32 => { | ||
| 3638 | const f = val.toFloat(f32); | ||
| 3639 | return Value.Tag.float_32.create(arena, @round(f)); | ||
| 3640 | }, | ||
| 3641 | 64 => { | ||
| 3642 | const f = val.toFloat(f64); | ||
| 3643 | return Value.Tag.float_64.create(arena, @round(f)); | ||
| 3644 | }, | ||
| 3645 | 80 => { | ||
| 3646 | if (true) { | ||
| 3647 | @panic("TODO implement compiler_rt round for f80"); | ||
| 3648 | } | ||
| 3649 | const f = val.toFloat(f80); | ||
| 3650 | return Value.Tag.float_80.create(arena, @round(f)); | ||
| 3651 | }, | ||
| 3652 | 128 => { | ||
| 3653 | if (true) { | ||
| 3654 | @panic("TODO implement compiler_rt round for f128"); | ||
| 3655 | } | ||
| 3656 | const f = val.toFloat(f128); | ||
| 3657 | return Value.Tag.float_128.create(arena, @round(f)); | ||
| 3658 | }, | ||
| 3659 | else => unreachable, | ||
| 3660 | } | ||
| 3661 | } | ||
| 3662 | |||
| 3663 | pub fn trunc(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 3664 | switch (float_type.floatBits(target)) { | ||
| 3665 | 16 => { | ||
| 3666 | const f = val.toFloat(f16); | ||
| 3667 | return Value.Tag.float_16.create(arena, @trunc(f)); | ||
| 3668 | }, | ||
| 3669 | 32 => { | ||
| 3670 | const f = val.toFloat(f32); | ||
| 3671 | return Value.Tag.float_32.create(arena, @trunc(f)); | ||
| 3672 | }, | ||
| 3673 | 64 => { | ||
| 3674 | const f = val.toFloat(f64); | ||
| 3675 | return Value.Tag.float_64.create(arena, @trunc(f)); | ||
| 3676 | }, | ||
| 3677 | 80 => { | ||
| 3678 | if (true) { | ||
| 3679 | @panic("TODO implement compiler_rt trunc for f80"); | ||
| 3680 | } | ||
| 3681 | const f = val.toFloat(f80); | ||
| 3682 | return Value.Tag.float_80.create(arena, @trunc(f)); | ||
| 3683 | }, | ||
| 3684 | 128 => { | ||
| 3685 | if (true) { | ||
| 3686 | @panic("TODO implement compiler_rt trunc for f128"); | ||
| 3687 | } | ||
| 3688 | const f = val.toFloat(f128); | ||
| 3689 | return Value.Tag.float_128.create(arena, @trunc(f)); | ||
| 3690 | }, | ||
| 3691 | else => unreachable, | ||
| 3692 | } | ||
| 3693 | } | ||
| 3694 | |||
| 3311 | /// This type is not copyable since it may contain pointers to its inner data. | 3695 | /// This type is not copyable since it may contain pointers to its inner data. |
| 3312 | pub const Payload = struct { | 3696 | pub const Payload = struct { |
| 3313 | tag: Tag, | 3697 | tag: Tag, |
test/behavior.zig-1| ... | @@ -150,7 +150,6 @@ test { | ... | @@ -150,7 +150,6 @@ test { |
| 150 | _ = @import("behavior/const_slice_child.zig"); | 150 | _ = @import("behavior/const_slice_child.zig"); |
| 151 | _ = @import("behavior/export_self_referential_type_info.zig"); | 151 | _ = @import("behavior/export_self_referential_type_info.zig"); |
| 152 | _ = @import("behavior/field_parent_ptr.zig"); | 152 | _ = @import("behavior/field_parent_ptr.zig"); |
| 153 | _ = @import("behavior/floatop_stage1.zig"); | ||
| 154 | _ = @import("behavior/fn_delegation.zig"); | 153 | _ = @import("behavior/fn_delegation.zig"); |
| 155 | _ = @import("behavior/ir_block_deps.zig"); | 154 | _ = @import("behavior/ir_block_deps.zig"); |
| 156 | _ = @import("behavior/misc.zig"); | 155 | _ = @import("behavior/misc.zig"); |
test/behavior/floatop.zig+349-13| ... | @@ -1,12 +1,22 @@ | ... | @@ -1,12 +1,22 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 3 | const math = std.math; | 4 | const math = std.math; |
| 4 | const pi = std.math.pi; | 5 | const pi = std.math.pi; |
| 5 | const e = std.math.e; | 6 | const e = std.math.e; |
| 6 | const Vector = std.meta.Vector; | 7 | const Vector = std.meta.Vector; |
| 8 | const has_f80_rt = @import("builtin").cpu.arch == .x86_64; | ||
| 7 | 9 | ||
| 10 | const epsilon_16 = 0.001; | ||
| 8 | const epsilon = 0.000001; | 11 | const epsilon = 0.000001; |
| 9 | 12 | ||
| 13 | fn epsForType(comptime T: type) T { | ||
| 14 | return switch (T) { | ||
| 15 | f16 => @as(f16, epsilon_16), | ||
| 16 | else => @as(T, epsilon), | ||
| 17 | }; | ||
| 18 | } | ||
| 19 | |||
| 10 | test "floating point comparisons" { | 20 | test "floating point comparisons" { |
| 11 | try testFloatComparisons(); | 21 | try testFloatComparisons(); |
| 12 | comptime try testFloatComparisons(); | 22 | comptime try testFloatComparisons(); |
| ... | @@ -79,19 +89,37 @@ test "@sqrt" { | ... | @@ -79,19 +89,37 @@ test "@sqrt" { |
| 79 | } | 89 | } |
| 80 | 90 | ||
| 81 | fn testSqrt() !void { | 91 | fn testSqrt() !void { |
| 82 | { | 92 | try expect(@sqrt(@as(f16, 4)) == 2); |
| 83 | var a: f16 = 4; | 93 | try expect(@sqrt(@as(f32, 9)) == 3); |
| 84 | try expect(@sqrt(a) == 2); | 94 | try expect(@sqrt(@as(f64, 25)) == 5); |
| 85 | } | 95 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), 1.0488088481701516, epsilon)); |
| 86 | { | 96 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.0)), 1.4142135623730950, epsilon)); |
| 87 | var a: f32 = 9; | 97 | |
| 88 | try expect(@sqrt(a) == 3); | 98 | if (builtin.zig_backend == .stage1) { |
| 89 | var b: f32 = 1.1; | 99 | if (has_f80_rt) { |
| 90 | try expect(math.approxEqAbs(f32, @sqrt(b), 1.0488088481701516, epsilon)); | 100 | var a: f80 = 25; |
| 91 | } | 101 | try expect(@sqrt(a) == 5); |
| 92 | { | 102 | } |
| 93 | var a: f64 = 25; | 103 | { |
| 94 | try expect(@sqrt(a) == 5); | 104 | const a: comptime_float = 25.0; |
| 105 | try expect(@sqrt(a) == 5.0); | ||
| 106 | } | ||
| 107 | // TODO test f128, and c_longdouble | ||
| 108 | // https://github.com/ziglang/zig/issues/4026 | ||
| 109 | //{ | ||
| 110 | // var a: f128 = 49; | ||
| 111 | //try expect(@sqrt(a) == 7); | ||
| 112 | //} | ||
| 113 | |||
| 114 | // TODO Implement Vector support for stage2 | ||
| 115 | { | ||
| 116 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; | ||
| 117 | var result = @sqrt(v); | ||
| 118 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon)); | ||
| 119 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon)); | ||
| 120 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon)); | ||
| 121 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon)); | ||
| 122 | } | ||
| 95 | } | 123 | } |
| 96 | } | 124 | } |
| 97 | 125 | ||
| ... | @@ -114,3 +142,311 @@ test "more @sqrt f16 tests" { | ... | @@ -114,3 +142,311 @@ test "more @sqrt f16 tests" { |
| 114 | try expect(math.isNan(@sqrt(@as(f16, -1.0)))); | 142 | try expect(math.isNan(@sqrt(@as(f16, -1.0)))); |
| 115 | try expect(math.isNan(@sqrt(@as(f16, math.nan(f16))))); | 143 | try expect(math.isNan(@sqrt(@as(f16, math.nan(f16))))); |
| 116 | } | 144 | } |
| 145 | |||
| 146 | test "@sin" { | ||
| 147 | comptime try testSin(); | ||
| 148 | try testSin(); | ||
| 149 | } | ||
| 150 | |||
| 151 | fn testSin() !void { | ||
| 152 | // TODO: Implement Vector support for other backends | ||
| 153 | if (builtin.zig_backend == .stage1) { | ||
| 154 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; | ||
| 155 | var result = @sin(v); | ||
| 156 | try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon)); | ||
| 157 | try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon)); | ||
| 158 | try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon)); | ||
| 159 | try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon)); | ||
| 160 | |||
| 161 | // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` | ||
| 162 | // so skip the rest of the tests. | ||
| 163 | return; | ||
| 164 | } | ||
| 165 | |||
| 166 | inline for ([_]type{ f16, f32, f64 }) |ty| { | ||
| 167 | const eps = epsForType(ty); | ||
| 168 | try expect(@sin(@as(ty, 0)) == 0); | ||
| 169 | try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps)); | ||
| 170 | try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2)), 1, eps)); | ||
| 171 | try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps)); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | test "@cos" { | ||
| 176 | comptime try testCos(); | ||
| 177 | try testCos(); | ||
| 178 | } | ||
| 179 | |||
| 180 | fn testCos() !void { | ||
| 181 | // TODO: Implement Vector support for other backends | ||
| 182 | if (builtin.zig_backend == .stage1) { | ||
| 183 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; | ||
| 184 | var result = @cos(v); | ||
| 185 | try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon)); | ||
| 186 | try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon)); | ||
| 187 | try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon)); | ||
| 188 | try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon)); | ||
| 189 | |||
| 190 | // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` | ||
| 191 | // so skip the rest of the tests. | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | |||
| 195 | inline for ([_]type{ f16, f32, f64 }) |ty| { | ||
| 196 | const eps = epsForType(ty); | ||
| 197 | try expect(@cos(@as(ty, 0)) == 1); | ||
| 198 | try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps)); | ||
| 199 | try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2)), 0, eps)); | ||
| 200 | try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps)); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | test "@exp" { | ||
| 205 | comptime try testExp(); | ||
| 206 | try testExp(); | ||
| 207 | } | ||
| 208 | |||
| 209 | fn testExp() !void { | ||
| 210 | inline for ([_]type{ f16, f32, f64 }) |ty| { | ||
| 211 | const eps = epsForType(ty); | ||
| 212 | try expect(@exp(@as(ty, 0)) == 1); | ||
| 213 | try expect(math.approxEqAbs(ty, @exp(@as(ty, 2)), 7.389056098930650, eps)); | ||
| 214 | try expect(math.approxEqAbs(ty, @exp(@as(ty, 5)), 148.4131591025766, eps)); | ||
| 215 | } | ||
| 216 | |||
| 217 | // TODO: Implement Vector support for other backends | ||
| 218 | if (builtin.zig_backend == .stage1) { | ||
| 219 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 220 | var result = @exp(v); | ||
| 221 | try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon)); | ||
| 222 | try expect(math.approxEqAbs(f32, @exp(@as(f32, 2.2)), result[1], epsilon)); | ||
| 223 | try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.3)), result[2], epsilon)); | ||
| 224 | try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon)); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | test "@exp2" { | ||
| 229 | comptime try testExp2(); | ||
| 230 | try testExp2(); | ||
| 231 | } | ||
| 232 | |||
| 233 | fn testExp2() !void { | ||
| 234 | inline for ([_]type{ f16, f32, f64 }) |ty| { | ||
| 235 | const eps = epsForType(ty); | ||
| 236 | try expect(@exp2(@as(ty, 2)) == 4); | ||
| 237 | try expect(math.approxEqAbs(ty, @exp2(@as(ty, 1.5)), 2.8284271247462, eps)); | ||
| 238 | try expect(math.approxEqAbs(ty, @exp2(@as(ty, 4.5)), 22.627416997969, eps)); | ||
| 239 | } | ||
| 240 | |||
| 241 | // TODO: Implement Vector support for other backends | ||
| 242 | if (builtin.zig_backend == .stage1) { | ||
| 243 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 244 | var result = @exp2(v); | ||
| 245 | try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon)); | ||
| 246 | try expect(math.approxEqAbs(f32, @exp2(@as(f32, 2.2)), result[1], epsilon)); | ||
| 247 | try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.3)), result[2], epsilon)); | ||
| 248 | try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon)); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | test "@log" { | ||
| 253 | // Old musl (and glibc?), and our current math.ln implementation do not return 1 | ||
| 254 | // so also accept those values. | ||
| 255 | comptime try testLog(); | ||
| 256 | try testLog(); | ||
| 257 | } | ||
| 258 | |||
| 259 | fn testLog() !void { | ||
| 260 | { | ||
| 261 | var a: f16 = e; | ||
| 262 | try expect(math.approxEqAbs(f16, @log(a), 1, epsilon)); | ||
| 263 | } | ||
| 264 | { | ||
| 265 | var a: f32 = e; | ||
| 266 | try expect(@log(a) == 1 or @log(a) == @bitCast(f32, @as(u32, 0x3f7fffff))); | ||
| 267 | } | ||
| 268 | { | ||
| 269 | var a: f64 = e; | ||
| 270 | try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000))); | ||
| 271 | } | ||
| 272 | inline for ([_]type{ f16, f32, f64 }) |ty| { | ||
| 273 | const eps = epsForType(ty); | ||
| 274 | try expect(math.approxEqAbs(ty, @log(@as(ty, 2)), 0.6931471805599, eps)); | ||
| 275 | try expect(math.approxEqAbs(ty, @log(@as(ty, 5)), 1.6094379124341, eps)); | ||
| 276 | } | ||
| 277 | |||
| 278 | // TODO: Implement Vector support for other backends | ||
| 279 | if (builtin.zig_backend == .stage1) { | ||
| 280 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 281 | var result = @log(v); | ||
| 282 | try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon)); | ||
| 283 | try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon)); | ||
| 284 | try expect(math.approxEqAbs(f32, @log(@as(f32, 0.3)), result[2], epsilon)); | ||
| 285 | try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon)); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | test "@log2" { | ||
| 290 | comptime try testLog2(); | ||
| 291 | try testLog2(); | ||
| 292 | } | ||
| 293 | |||
| 294 | fn testLog2() !void { | ||
| 295 | inline for ([_]type{ f16, f32, f64 }) |ty| { | ||
| 296 | const eps = epsForType(ty); | ||
| 297 | try expect(@log2(@as(ty, 4)) == 2); | ||
| 298 | try expect(math.approxEqAbs(ty, @log2(@as(ty, 6)), 2.5849625007212, eps)); | ||
| 299 | try expect(math.approxEqAbs(ty, @log2(@as(ty, 10)), 3.3219280948874, eps)); | ||
| 300 | } | ||
| 301 | |||
| 302 | // TODO: Implement Vector support for other backends | ||
| 303 | if (builtin.zig_backend == .stage1) { | ||
| 304 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 305 | var result = @log2(v); | ||
| 306 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon)); | ||
| 307 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon)); | ||
| 308 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon)); | ||
| 309 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon)); | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | test "@log10" { | ||
| 314 | comptime try testLog10(); | ||
| 315 | try testLog10(); | ||
| 316 | } | ||
| 317 | |||
| 318 | fn testLog10() !void { | ||
| 319 | inline for ([_]type{ f16, f32, f64 }) |ty| { | ||
| 320 | const eps = epsForType(ty); | ||
| 321 | try expect(@log10(@as(ty, 100)) == 2); | ||
| 322 | try expect(math.approxEqAbs(ty, @log10(@as(ty, 15)), 1.176091259056, eps)); | ||
| 323 | try expect(math.approxEqAbs(ty, @log10(@as(ty, 50)), 1.698970004336, eps)); | ||
| 324 | } | ||
| 325 | |||
| 326 | // TODO: Implement Vector support for other backends | ||
| 327 | if (builtin.zig_backend == .stage1) { | ||
| 328 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 329 | var result = @log10(v); | ||
| 330 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon)); | ||
| 331 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon)); | ||
| 332 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon)); | ||
| 333 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon)); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | test "@fabs" { | ||
| 338 | comptime try testFabs(); | ||
| 339 | try testFabs(); | ||
| 340 | } | ||
| 341 | |||
| 342 | fn testFabs() !void { | ||
| 343 | try expect(@fabs(@as(f16, -2.5)) == 2.5); | ||
| 344 | try expect(@fabs(@as(f16, 2.5)) == 2.5); | ||
| 345 | try expect(@fabs(@as(f32, -2.5)) == 2.5); | ||
| 346 | try expect(@fabs(@as(f32, 2.5)) == 2.5); | ||
| 347 | try expect(@fabs(@as(f64, -2.5)) == 2.5); | ||
| 348 | try expect(@fabs(@as(f64, 2.5)) == 2.5); | ||
| 349 | |||
| 350 | // TODO test f128, and c_longdouble | ||
| 351 | // https://github.com/ziglang/zig/issues/4026 | ||
| 352 | // { | ||
| 353 | // var a: f80 = -2.5; | ||
| 354 | // var b: f80 = 2.5; | ||
| 355 | // try expect(@fabs(a) == 2.5); | ||
| 356 | // try expect(@fabs(b) == 2.5); | ||
| 357 | // } | ||
| 358 | |||
| 359 | // TODO: Implement Vector support for other backends | ||
| 360 | if (builtin.zig_backend == .stage1) { | ||
| 361 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | ||
| 362 | var result = @fabs(v); | ||
| 363 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon)); | ||
| 364 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, -2.2)), result[1], epsilon)); | ||
| 365 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, 0.3)), result[2], epsilon)); | ||
| 366 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, -0.4)), result[3], epsilon)); | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 370 | test "@floor" { | ||
| 371 | comptime try testFloor(); | ||
| 372 | try testFloor(); | ||
| 373 | } | ||
| 374 | |||
| 375 | fn testFloor() !void { | ||
| 376 | try expect(@floor(@as(f16, 2.1)) == 2); | ||
| 377 | try expect(@floor(@as(f32, 2.1)) == 2); | ||
| 378 | try expect(@floor(@as(f64, 3.5)) == 3); | ||
| 379 | |||
| 380 | // TODO test f128, and c_longdouble | ||
| 381 | // https://github.com/ziglang/zig/issues/4026 | ||
| 382 | // { | ||
| 383 | // var a: f80 = 3.5; | ||
| 384 | // try expect(@floor(a) == 3); | ||
| 385 | // } | ||
| 386 | |||
| 387 | // TODO: Implement Vector support for other backends | ||
| 388 | if (builtin.zig_backend == .stage1) { | ||
| 389 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | ||
| 390 | var result = @floor(v); | ||
| 391 | try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon)); | ||
| 392 | try expect(math.approxEqAbs(f32, @floor(@as(f32, -2.2)), result[1], epsilon)); | ||
| 393 | try expect(math.approxEqAbs(f32, @floor(@as(f32, 0.3)), result[2], epsilon)); | ||
| 394 | try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon)); | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | test "@ceil" { | ||
| 399 | comptime try testCeil(); | ||
| 400 | try testCeil(); | ||
| 401 | } | ||
| 402 | |||
| 403 | fn testCeil() !void { | ||
| 404 | try expect(@ceil(@as(f16, 2.1)) == 3); | ||
| 405 | try expect(@ceil(@as(f32, 2.1)) == 3); | ||
| 406 | try expect(@ceil(@as(f64, 3.5)) == 4); | ||
| 407 | |||
| 408 | // TODO test f128, and c_longdouble | ||
| 409 | // https://github.com/ziglang/zig/issues/4026 | ||
| 410 | // { | ||
| 411 | // var a: f80 = 3.5; | ||
| 412 | // try expect(@ceil(a) == 4); | ||
| 413 | // } | ||
| 414 | |||
| 415 | // TODO: Implement Vector support for other backends | ||
| 416 | if (builtin.zig_backend == .stage1) { | ||
| 417 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | ||
| 418 | var result = @ceil(v); | ||
| 419 | try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon)); | ||
| 420 | try expect(math.approxEqAbs(f32, @ceil(@as(f32, -2.2)), result[1], epsilon)); | ||
| 421 | try expect(math.approxEqAbs(f32, @ceil(@as(f32, 0.3)), result[2], epsilon)); | ||
| 422 | try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon)); | ||
| 423 | } | ||
| 424 | } | ||
| 425 | |||
| 426 | test "@trunc" { | ||
| 427 | comptime try testTrunc(); | ||
| 428 | try testTrunc(); | ||
| 429 | } | ||
| 430 | |||
| 431 | fn testTrunc() !void { | ||
| 432 | try expect(@trunc(@as(f16, 2.1)) == 2); | ||
| 433 | try expect(@trunc(@as(f32, 2.1)) == 2); | ||
| 434 | try expect(@trunc(@as(f64, -3.5)) == -3); | ||
| 435 | |||
| 436 | // TODO test f128, and c_longdouble | ||
| 437 | // https://github.com/ziglang/zig/issues/4026 | ||
| 438 | // { | ||
| 439 | // var a: f80 = -3.5; | ||
| 440 | // try expect(@trunc(a) == -3); | ||
| 441 | // } | ||
| 442 | |||
| 443 | // TODO: Implement Vector support for other backends | ||
| 444 | if (builtin.zig_backend == .stage1) { | ||
| 445 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | ||
| 446 | var result = @trunc(v); | ||
| 447 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon)); | ||
| 448 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, -2.2)), result[1], epsilon)); | ||
| 449 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, 0.3)), result[2], epsilon)); | ||
| 450 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon)); | ||
| 451 | } | ||
| 452 | } |
test/behavior/floatop_stage1.zig deleted-452| ... | @@ -1,452 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const math = std.math; | ||
| 4 | const pi = std.math.pi; | ||
| 5 | const e = std.math.e; | ||
| 6 | const Vector = std.meta.Vector; | ||
| 7 | const has_f80_rt = @import("builtin").cpu.arch == .x86_64; | ||
| 8 | |||
| 9 | const epsilon = 0.000001; | ||
| 10 | |||
| 11 | test "@sqrt" { | ||
| 12 | comptime try testSqrt(); | ||
| 13 | try testSqrt(); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn testSqrt() !void { | ||
| 17 | if (has_f80_rt) { | ||
| 18 | var a: f80 = 25; | ||
| 19 | try expect(@sqrt(a) == 5); | ||
| 20 | } | ||
| 21 | { | ||
| 22 | const a: comptime_float = 25.0; | ||
| 23 | try expect(@sqrt(a) == 5.0); | ||
| 24 | } | ||
| 25 | // TODO https://github.com/ziglang/zig/issues/4026 | ||
| 26 | //{ | ||
| 27 | // var a: f128 = 49; | ||
| 28 | //try expect(@sqrt(a) == 7); | ||
| 29 | //} | ||
| 30 | { | ||
| 31 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; | ||
| 32 | var result = @sqrt(v); | ||
| 33 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon)); | ||
| 34 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon)); | ||
| 35 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon)); | ||
| 36 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon)); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | test "@sin" { | ||
| 41 | comptime try testSin(); | ||
| 42 | try testSin(); | ||
| 43 | } | ||
| 44 | |||
| 45 | fn testSin() !void { | ||
| 46 | // TODO test f128, and c_longdouble | ||
| 47 | // https://github.com/ziglang/zig/issues/4026 | ||
| 48 | { | ||
| 49 | var a: f16 = 0; | ||
| 50 | try expect(@sin(a) == 0); | ||
| 51 | } | ||
| 52 | { | ||
| 53 | var a: f32 = 0; | ||
| 54 | try expect(@sin(a) == 0); | ||
| 55 | } | ||
| 56 | { | ||
| 57 | var a: f64 = 0; | ||
| 58 | try expect(@sin(a) == 0); | ||
| 59 | } | ||
| 60 | // { | ||
| 61 | // var a: f80 = 0; | ||
| 62 | // try expect(@sin(a) == 0); | ||
| 63 | // } | ||
| 64 | { | ||
| 65 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; | ||
| 66 | var result = @sin(v); | ||
| 67 | try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon)); | ||
| 68 | try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon)); | ||
| 69 | try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon)); | ||
| 70 | try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon)); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | test "@cos" { | ||
| 75 | comptime try testCos(); | ||
| 76 | try testCos(); | ||
| 77 | } | ||
| 78 | |||
| 79 | fn testCos() !void { | ||
| 80 | // TODO test f128, and c_longdouble | ||
| 81 | // https://github.com/ziglang/zig/issues/4026 | ||
| 82 | { | ||
| 83 | var a: f16 = 0; | ||
| 84 | try expect(@cos(a) == 1); | ||
| 85 | } | ||
| 86 | { | ||
| 87 | var a: f32 = 0; | ||
| 88 | try expect(@cos(a) == 1); | ||
| 89 | } | ||
| 90 | { | ||
| 91 | var a: f64 = 0; | ||
| 92 | try expect(@cos(a) == 1); | ||
| 93 | } | ||
| 94 | // { | ||
| 95 | // var a: f80 = 0; | ||
| 96 | // try expect(@cos(a) == 1); | ||
| 97 | // } | ||
| 98 | { | ||
| 99 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; | ||
| 100 | var result = @cos(v); | ||
| 101 | try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon)); | ||
| 102 | try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon)); | ||
| 103 | try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon)); | ||
| 104 | try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon)); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | test "@exp" { | ||
| 109 | comptime try testExp(); | ||
| 110 | try testExp(); | ||
| 111 | } | ||
| 112 | |||
| 113 | fn testExp() !void { | ||
| 114 | // TODO test f128, and c_longdouble | ||
| 115 | // https://github.com/ziglang/zig/issues/4026 | ||
| 116 | { | ||
| 117 | var a: f16 = 0; | ||
| 118 | try expect(@exp(a) == 1); | ||
| 119 | } | ||
| 120 | { | ||
| 121 | var a: f32 = 0; | ||
| 122 | try expect(@exp(a) == 1); | ||
| 123 | } | ||
| 124 | { | ||
| 125 | var a: f64 = 0; | ||
| 126 | try expect(@exp(a) == 1); | ||
| 127 | } | ||
| 128 | // { | ||
| 129 | // var a: f80 = 0; | ||
| 130 | // try expect(@exp(a) == 1); | ||
| 131 | // } | ||
| 132 | { | ||
| 133 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 134 | var result = @exp(v); | ||
| 135 | try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon)); | ||
| 136 | try expect(math.approxEqAbs(f32, @exp(@as(f32, 2.2)), result[1], epsilon)); | ||
| 137 | try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.3)), result[2], epsilon)); | ||
| 138 | try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon)); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | test "@exp2" { | ||
| 143 | comptime try testExp2(); | ||
| 144 | try testExp2(); | ||
| 145 | } | ||
| 146 | |||
| 147 | fn testExp2() !void { | ||
| 148 | // TODO test f128, and c_longdouble | ||
| 149 | // https://github.com/ziglang/zig/issues/4026 | ||
| 150 | { | ||
| 151 | var a: f16 = 2; | ||
| 152 | try expect(@exp2(a) == 4); | ||
| 153 | } | ||
| 154 | { | ||
| 155 | var a: f32 = 2; | ||
| 156 | try expect(@exp2(a) == 4); | ||
| 157 | } | ||
| 158 | { | ||
| 159 | var a: f64 = 2; | ||
| 160 | try expect(@exp2(a) == 4); | ||
| 161 | } | ||
| 162 | // { | ||
| 163 | // var a: f80 = 2; | ||
| 164 | // try expect(@exp2(a) == 4); | ||
| 165 | // } | ||
| 166 | { | ||
| 167 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 168 | var result = @exp2(v); | ||
| 169 | try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon)); | ||
| 170 | try expect(math.approxEqAbs(f32, @exp2(@as(f32, 2.2)), result[1], epsilon)); | ||
| 171 | try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.3)), result[2], epsilon)); | ||
| 172 | try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon)); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | test "@log" { | ||
| 177 | // Old musl (and glibc?), and our current math.ln implementation do not return 1 | ||
| 178 | // so also accept those values. | ||
| 179 | comptime try testLog(); | ||
| 180 | try testLog(); | ||
| 181 | } | ||
| 182 | |||
| 183 | fn testLog() !void { | ||
| 184 | // TODO test f128, and c_longdouble | ||
| 185 | // https://github.com/ziglang/zig/issues/4026 | ||
| 186 | { | ||
| 187 | var a: f16 = e; | ||
| 188 | try expect(math.approxEqAbs(f16, @log(a), 1, epsilon)); | ||
| 189 | } | ||
| 190 | { | ||
| 191 | var a: f32 = e; | ||
| 192 | try expect(@log(a) == 1 or @log(a) == @bitCast(f32, @as(u32, 0x3f7fffff))); | ||
| 193 | } | ||
| 194 | { | ||
| 195 | var a: f64 = e; | ||
| 196 | try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000))); | ||
| 197 | } | ||
| 198 | // { | ||
| 199 | // var a: f80 = e; | ||
| 200 | // try expect(@log(a) == 1); | ||
| 201 | // } | ||
| 202 | { | ||
| 203 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 204 | var result = @log(v); | ||
| 205 | try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon)); | ||
| 206 | try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon)); | ||
| 207 | try expect(math.approxEqAbs(f32, @log(@as(f32, 0.3)), result[2], epsilon)); | ||
| 208 | try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon)); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | test "@log2" { | ||
| 213 | comptime try testLog2(); | ||
| 214 | try testLog2(); | ||
| 215 | } | ||
| 216 | |||
| 217 | fn testLog2() !void { | ||
| 218 | // TODO test f128, and c_longdouble | ||
| 219 | // https://github.com/ziglang/zig/issues/4026 | ||
| 220 | { | ||
| 221 | var a: f16 = 4; | ||
| 222 | try expect(@log2(a) == 2); | ||
| 223 | } | ||
| 224 | { | ||
| 225 | var a: f32 = 4; | ||
| 226 | try expect(@log2(a) == 2); | ||
| 227 | } | ||
| 228 | { | ||
| 229 | var a: f64 = 4; | ||
| 230 | try expect(@log2(a) == 2); | ||
| 231 | } | ||
| 232 | // { | ||
| 233 | // var a: f80 = 4; | ||
| 234 | // try expect(@log2(a) == 2); | ||
| 235 | // } | ||
| 236 | { | ||
| 237 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 238 | var result = @log2(v); | ||
| 239 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon)); | ||
| 240 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon)); | ||
| 241 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon)); | ||
| 242 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon)); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | test "@log10" { | ||
| 247 | comptime try testLog10(); | ||
| 248 | try testLog10(); | ||
| 249 | } | ||
| 250 | |||
| 251 | fn testLog10() !void { | ||
| 252 | // TODO test f128, and c_longdouble | ||
| 253 | // https://github.com/ziglang/zig/issues/4026 | ||
| 254 | { | ||
| 255 | var a: f16 = 100; | ||
| 256 | try expect(@log10(a) == 2); | ||
| 257 | } | ||
| 258 | { | ||
| 259 | var a: f32 = 100; | ||
| 260 | try expect(@log10(a) == 2); | ||
| 261 | } | ||
| 262 | { | ||
| 263 | var a: f64 = 1000; | ||
| 264 | try expect(@log10(a) == 3); | ||
| 265 | } | ||
| 266 | // { | ||
| 267 | // var a: f80 = 1000; | ||
| 268 | // try expect(@log10(a) == 3); | ||
| 269 | // } | ||
| 270 | { | ||
| 271 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | ||
| 272 | var result = @log10(v); | ||
| 273 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon)); | ||
| 274 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon)); | ||
| 275 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon)); | ||
| 276 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon)); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | test "@fabs" { | ||
| 281 | comptime try testFabs(); | ||
| 282 | try testFabs(); | ||
| 283 | } | ||
| 284 | |||
| 285 | fn testFabs() !void { | ||
| 286 | // TODO test f128, and c_longdouble | ||
| 287 | // https://github.com/ziglang/zig/issues/4026 | ||
| 288 | { | ||
| 289 | var a: f16 = -2.5; | ||
| 290 | var b: f16 = 2.5; | ||
| 291 | try expect(@fabs(a) == 2.5); | ||
| 292 | try expect(@fabs(b) == 2.5); | ||
| 293 | } | ||
| 294 | { | ||
| 295 | var a: f32 = -2.5; | ||
| 296 | var b: f32 = 2.5; | ||
| 297 | try expect(@fabs(a) == 2.5); | ||
| 298 | try expect(@fabs(b) == 2.5); | ||
| 299 | } | ||
| 300 | { | ||
| 301 | var a: f64 = -2.5; | ||
| 302 | var b: f64 = 2.5; | ||
| 303 | try expect(@fabs(a) == 2.5); | ||
| 304 | try expect(@fabs(b) == 2.5); | ||
| 305 | } | ||
| 306 | // { | ||
| 307 | // var a: f80 = -2.5; | ||
| 308 | // var b: f80 = 2.5; | ||
| 309 | // try expect(@fabs(a) == 2.5); | ||
| 310 | // try expect(@fabs(b) == 2.5); | ||
| 311 | // } | ||
| 312 | { | ||
| 313 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | ||
| 314 | var result = @fabs(v); | ||
| 315 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon)); | ||
| 316 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, -2.2)), result[1], epsilon)); | ||
| 317 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, 0.3)), result[2], epsilon)); | ||
| 318 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, -0.4)), result[3], epsilon)); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | test "@floor" { | ||
| 323 | comptime try testFloor(); | ||
| 324 | try testFloor(); | ||
| 325 | } | ||
| 326 | |||
| 327 | fn testFloor() !void { | ||
| 328 | // TODO test f128, and c_longdouble | ||
| 329 | // https://github.com/ziglang/zig/issues/4026 | ||
| 330 | { | ||
| 331 | var a: f16 = 2.1; | ||
| 332 | try expect(@floor(a) == 2); | ||
| 333 | } | ||
| 334 | { | ||
| 335 | var a: f32 = 2.1; | ||
| 336 | try expect(@floor(a) == 2); | ||
| 337 | } | ||
| 338 | { | ||
| 339 | var a: f64 = 3.5; | ||
| 340 | try expect(@floor(a) == 3); | ||
| 341 | } | ||
| 342 | // { | ||
| 343 | // var a: f80 = 3.5; | ||
| 344 | // try expect(@floor(a) == 3); | ||
| 345 | // } | ||
| 346 | { | ||
| 347 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | ||
| 348 | var result = @floor(v); | ||
| 349 | try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon)); | ||
| 350 | try expect(math.approxEqAbs(f32, @floor(@as(f32, -2.2)), result[1], epsilon)); | ||
| 351 | try expect(math.approxEqAbs(f32, @floor(@as(f32, 0.3)), result[2], epsilon)); | ||
| 352 | try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon)); | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | test "@ceil" { | ||
| 357 | comptime try testCeil(); | ||
| 358 | try testCeil(); | ||
| 359 | } | ||
| 360 | |||
| 361 | fn testCeil() !void { | ||
| 362 | // TODO test f128, and c_longdouble | ||
| 363 | // https://github.com/ziglang/zig/issues/4026 | ||
| 364 | { | ||
| 365 | var a: f16 = 2.1; | ||
| 366 | try expect(@ceil(a) == 3); | ||
| 367 | } | ||
| 368 | { | ||
| 369 | var a: f32 = 2.1; | ||
| 370 | try expect(@ceil(a) == 3); | ||
| 371 | } | ||
| 372 | { | ||
| 373 | var a: f64 = 3.5; | ||
| 374 | try expect(@ceil(a) == 4); | ||
| 375 | } | ||
| 376 | // { | ||
| 377 | // var a: f80 = 3.5; | ||
| 378 | // try expect(@ceil(a) == 4); | ||
| 379 | // } | ||
| 380 | { | ||
| 381 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | ||
| 382 | var result = @ceil(v); | ||
| 383 | try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon)); | ||
| 384 | try expect(math.approxEqAbs(f32, @ceil(@as(f32, -2.2)), result[1], epsilon)); | ||
| 385 | try expect(math.approxEqAbs(f32, @ceil(@as(f32, 0.3)), result[2], epsilon)); | ||
| 386 | try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon)); | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | test "@trunc" { | ||
| 391 | comptime try testTrunc(); | ||
| 392 | try testTrunc(); | ||
| 393 | } | ||
| 394 | |||
| 395 | fn testTrunc() !void { | ||
| 396 | // TODO test f128, and c_longdouble | ||
| 397 | // https://github.com/ziglang/zig/issues/4026 | ||
| 398 | { | ||
| 399 | var a: f16 = 2.1; | ||
| 400 | try expect(@trunc(a) == 2); | ||
| 401 | } | ||
| 402 | { | ||
| 403 | var a: f32 = 2.1; | ||
| 404 | try expect(@trunc(a) == 2); | ||
| 405 | } | ||
| 406 | { | ||
| 407 | var a: f64 = -3.5; | ||
| 408 | try expect(@trunc(a) == -3); | ||
| 409 | } | ||
| 410 | // { | ||
| 411 | // var a: f80 = -3.5; | ||
| 412 | // try expect(@trunc(a) == -3); | ||
| 413 | // } | ||
| 414 | { | ||
| 415 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | ||
| 416 | var result = @trunc(v); | ||
| 417 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon)); | ||
| 418 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, -2.2)), result[1], epsilon)); | ||
| 419 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, 0.3)), result[2], epsilon)); | ||
| 420 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon)); | ||
| 421 | } | ||
| 422 | } | ||
| 423 | |||
| 424 | test "floating point comparisons" { | ||
| 425 | if (has_f80_rt) try testFloatComparisons(); | ||
| 426 | comptime try testFloatComparisons(); | ||
| 427 | } | ||
| 428 | |||
| 429 | fn testFloatComparisons() !void { | ||
| 430 | inline for ([_]type{ f16, f32, f64, f80, f128 }) |ty| { | ||
| 431 | // No decimal part | ||
| 432 | { | ||
| 433 | const x: ty = 1.0; | ||
| 434 | try expect(x == 1); | ||
| 435 | try expect(x != 0); | ||
| 436 | try expect(x > 0); | ||
| 437 | try expect(x < 2); | ||
| 438 | try expect(x >= 1); | ||
| 439 | try expect(x <= 1); | ||
| 440 | } | ||
| 441 | // Non-zero decimal part | ||
| 442 | { | ||
| 443 | const x: ty = 1.5; | ||
| 444 | try expect(x != 1); | ||
| 445 | try expect(x != 2); | ||
| 446 | try expect(x > 1); | ||
| 447 | try expect(x < 2); | ||
| 448 | try expect(x >= 1); | ||
| 449 | try expect(x <= 2); | ||
| 450 | } | ||
| 451 | } | ||
| 452 | } | ||