| 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 | 237 | /// Uses the `ty_op` field. |
| 238 | 238 | popcount, |
| 239 | 239 | |
| 240 | /// Computes the square root of a floating point number. | |
| 240 | /// Square root of a floating point number. | |
| 241 | 241 | /// Uses the `un_op` field. |
| 242 | 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 | 280 | /// `<`. Result type is always bool. |
| 245 | 281 | /// Uses the `bin_op` field. |
| ... | ... | @@ -754,7 +790,20 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 754 | 790 | .max, |
| 755 | 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 | 808 | .cmp_lt, |
| 760 | 809 | .cmp_lte, |
src/Liveness.zig+12| ... | ... | @@ -339,6 +339,18 @@ fn analyzeInst( |
| 339 | 339 | .tag_name, |
| 340 | 340 | .error_name, |
| 341 | 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 | 355 | const operand = inst_datas[inst].un_op; |
| 344 | 356 | return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none }); |
src/Sema.zig+12-12| ... | ... | @@ -747,18 +747,18 @@ fn analyzeBodyInner( |
| 747 | 747 | .ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz), |
| 748 | 748 | |
| 749 | 749 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), |
| 750 | .sin => @panic("TODO"), | |
| 751 | .cos => @panic("TODO"), | |
| 752 | .exp => @panic("TODO"), | |
| 753 | .exp2 => @panic("TODO"), | |
| 754 | .log => @panic("TODO"), | |
| 755 | .log2 => @panic("TODO"), | |
| 756 | .log10 => @panic("TODO"), | |
| 757 | .fabs => @panic("TODO"), | |
| 758 | .floor => @panic("TODO"), | |
| 759 | .ceil => @panic("TODO"), | |
| 760 | .trunc => @panic("TODO"), | |
| 761 | .round => @panic("TODO"), | |
| 750 | .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin), | |
| 751 | .cos => try sema.zirUnaryMath(block, inst, .cos, Value.cos), | |
| 752 | .exp => try sema.zirUnaryMath(block, inst, .exp, Value.exp), | |
| 753 | .exp2 => try sema.zirUnaryMath(block, inst, .exp2, Value.exp2), | |
| 754 | .log => try sema.zirUnaryMath(block, inst, .log, Value.log), | |
| 755 | .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2), | |
| 756 | .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10), | |
| 757 | .fabs => try sema.zirUnaryMath(block, inst, .fabs, Value.fabs), | |
| 758 | .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor), | |
| 759 | .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil), | |
| 760 | .round => try sema.zirUnaryMath(block, inst, .round, Value.round), | |
| 761 | .trunc => try sema.zirUnaryMath(block, inst, .trunc_float, Value.trunc), | |
| 762 | 762 | |
| 763 | 763 | .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent), |
| 764 | 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 | 528 | .max => try self.airMax(inst), |
| 529 | 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 | 546 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 534 | 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 | 520 | .max => try self.airMax(inst), |
| 521 | 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 | 538 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 526 | 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 | 507 | .max => try self.airMax(inst), |
| 508 | 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 | 525 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 513 | 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 | 1679 | .unwrap_errunion_err_ptr, |
| 1680 | 1680 | |
| 1681 | 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 | 1695 | .ptr_slice_len_ptr, |
| 1684 | 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 | 599 | .max => try self.airMax(inst), |
| 600 | 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 | 617 | .add_with_overflow => try self.airAddWithOverflow(inst), |
| 605 | 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 | 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), | |
| 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 | 1464 | .add_with_overflow => try airAddWithOverflow(f, inst), |
| 1452 | 1465 | .sub_with_overflow => try airSubWithOverflow(f, inst), |
| ... | ... | @@ -3395,12 +3408,6 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3395 | 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 | 3411 | fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 { |
| 3405 | 3412 | return switch (order) { |
| 3406 | 3413 | .Unordered => "memory_order_relaxed", |
src/codegen/llvm.zig+15-3| ... | ... | @@ -2050,7 +2050,19 @@ 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), | |
| 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 | 2067 | .cmp_eq => try self.airCmp(inst, .eq), |
| 2056 | 2068 | .cmp_gt => try self.airCmp(inst, .gt), |
| ... | ... | @@ -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 | 4229 | if (self.liveness.isUnused(inst)) return null; |
| 4218 | 4230 | |
| 4219 | 4231 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| ... | ... | @@ -4221,7 +4233,7 @@ pub const FuncGen = struct { |
| 4221 | 4233 | const operand_ty = self.air.typeOf(un_op); |
| 4222 | 4234 | |
| 4223 | 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 | 4237 | const params = [_]*const llvm.Value{operand}; |
| 4226 | 4238 | |
| 4227 | 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 | 159 | .tag_name, |
| 160 | 160 | .error_name, |
| 161 | 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 | 174 | => try w.writeUnOp(s, inst), |
| 163 | 175 | |
| 164 | 176 | .breakpoint, |
src/value.zig+384| ... | ... | @@ -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 | 3695 | /// This type is not copyable since it may contain pointers to its inner data. |
| 3312 | 3696 | pub const Payload = struct { |
| 3313 | 3697 | tag: Tag, |
test/behavior.zig-1| ... | ... | @@ -150,7 +150,6 @@ test { |
| 150 | 150 | _ = @import("behavior/const_slice_child.zig"); |
| 151 | 151 | _ = @import("behavior/export_self_referential_type_info.zig"); |
| 152 | 152 | _ = @import("behavior/field_parent_ptr.zig"); |
| 153 | _ = @import("behavior/floatop_stage1.zig"); | |
| 154 | 153 | _ = @import("behavior/fn_delegation.zig"); |
| 155 | 154 | _ = @import("behavior/ir_block_deps.zig"); |
| 156 | 155 | _ = @import("behavior/misc.zig"); |
test/behavior/floatop.zig+349-13| ... | ... | @@ -1,12 +1,22 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const expect = std.testing.expect; |
| 3 | 4 | const math = std.math; |
| 4 | 5 | const pi = std.math.pi; |
| 5 | 6 | const e = std.math.e; |
| 6 | 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 | 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 | 20 | test "floating point comparisons" { |
| 11 | 21 | try testFloatComparisons(); |
| 12 | 22 | comptime try testFloatComparisons(); |
| ... | ... | @@ -79,19 +89,37 @@ test "@sqrt" { |
| 79 | 89 | } |
| 80 | 90 | |
| 81 | 91 | 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); | |
| 92 | try expect(@sqrt(@as(f16, 4)) == 2); | |
| 93 | try expect(@sqrt(@as(f32, 9)) == 3); | |
| 94 | try expect(@sqrt(@as(f64, 25)) == 5); | |
| 95 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), 1.0488088481701516, epsilon)); | |
| 96 | try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.0)), 1.4142135623730950, epsilon)); | |
| 97 | ||
| 98 | if (builtin.zig_backend == .stage1) { | |
| 99 | if (has_f80_rt) { | |
| 100 | var a: f80 = 25; | |
| 101 | try expect(@sqrt(a) == 5); | |
| 102 | } | |
| 103 | { | |
| 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 | 142 | try expect(math.isNan(@sqrt(@as(f16, -1.0)))); |
| 115 | 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 | } |