| author | |
| committer | |
| log | f8e418c47d13189674bdf5f131c19fd811964579 |
| tree | 7695c4d6ef606bae5f58c6a978b2f5642b298078 |
| parent | 5e60ee41272579bc5fef3d95c59180df6ab824c1 |
* comptime known 0 as a numerator returns comptime 0 independent of
denominator.
* negative numerator and denominator are allowed when the remainder is
zero because that means the modulus would be also zero.
* organize math behavior tests4 files changed, 467 insertions(+), 422 deletions(-)
src/Sema.zig+19-10| ... | @@ -8674,7 +8674,6 @@ fn analyzeArithmetic( | ... | @@ -8674,7 +8674,6 @@ fn analyzeArithmetic( |
| 8674 | // For integers: | 8674 | // For integers: |
| 8675 | // Either operand being undef is a compile error because there exists | 8675 | // Either operand being undef is a compile error because there exists |
| 8676 | // a possible value (TODO what is it?) that would invoke illegal behavior. | 8676 | // a possible value (TODO what is it?) that would invoke illegal behavior. |
| 8677 | // TODO: can lhs zero be handled better? | ||
| 8678 | // TODO: can lhs undef be handled better? | 8677 | // TODO: can lhs undef be handled better? |
| 8679 | // | 8678 | // |
| 8680 | // For floats: | 8679 | // For floats: |
| ... | @@ -8690,8 +8689,8 @@ fn analyzeArithmetic( | ... | @@ -8690,8 +8689,8 @@ fn analyzeArithmetic( |
| 8690 | if (lhs_val.isUndef()) { | 8689 | if (lhs_val.isUndef()) { |
| 8691 | return sema.failWithUseOfUndef(block, lhs_src); | 8690 | return sema.failWithUseOfUndef(block, lhs_src); |
| 8692 | } | 8691 | } |
| 8693 | if (lhs_val.compareWithZero(.lt)) { | 8692 | if (lhs_val.compareWithZero(.eq)) { |
| 8694 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); | 8693 | return sema.addConstant(scalar_type, Value.zero); |
| 8695 | } | 8694 | } |
| 8696 | } else if (lhs_ty.isSignedInt()) { | 8695 | } else if (lhs_ty.isSignedInt()) { |
| 8697 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); | 8696 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| ... | @@ -8703,14 +8702,24 @@ fn analyzeArithmetic( | ... | @@ -8703,14 +8702,24 @@ fn analyzeArithmetic( |
| 8703 | if (rhs_val.compareWithZero(.eq)) { | 8702 | if (rhs_val.compareWithZero(.eq)) { |
| 8704 | return sema.failWithDivideByZero(block, rhs_src); | 8703 | return sema.failWithDivideByZero(block, rhs_src); |
| 8705 | } | 8704 | } |
| 8706 | if (rhs_val.compareWithZero(.lt)) { | ||
| 8707 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); | ||
| 8708 | } | ||
| 8709 | if (maybe_lhs_val) |lhs_val| { | 8705 | if (maybe_lhs_val) |lhs_val| { |
| 8710 | return sema.addConstant( | 8706 | const rem_result = try lhs_val.intRem(rhs_val, sema.arena); |
| 8711 | scalar_type, | 8707 | // If this answer could possibly be different by doing `intMod`, |
| 8712 | try lhs_val.intRem(rhs_val, sema.arena), | 8708 | // we must emit a compile error. Otherwise, it's OK. |
| 8713 | ); | 8709 | if (rhs_val.compareWithZero(.lt) != lhs_val.compareWithZero(.lt) and |
| 8710 | !rem_result.compareWithZero(.eq)) | ||
| 8711 | { | ||
| 8712 | const bad_src = if (lhs_val.compareWithZero(.lt)) | ||
| 8713 | lhs_src | ||
| 8714 | else | ||
| 8715 | rhs_src; | ||
| 8716 | return sema.failWithModRemNegative(block, bad_src, lhs_ty, rhs_ty); | ||
| 8717 | } | ||
| 8718 | if (lhs_val.compareWithZero(.lt)) { | ||
| 8719 | // Negative | ||
| 8720 | return sema.addConstant(scalar_type, Value.zero); | ||
| 8721 | } | ||
| 8722 | return sema.addConstant(scalar_type, rem_result); | ||
| 8714 | } | 8723 | } |
| 8715 | break :rs .{ .src = lhs_src, .air_tag = .rem }; | 8724 | break :rs .{ .src = lhs_src, .air_tag = .rem }; |
| 8716 | } else if (rhs_ty.isSignedInt()) { | 8725 | } else if (rhs_ty.isSignedInt()) { |
test/behavior.zig-1| ... | @@ -153,7 +153,6 @@ test { | ... | @@ -153,7 +153,6 @@ test { |
| 153 | _ = @import("behavior/floatop_stage1.zig"); | 153 | _ = @import("behavior/floatop_stage1.zig"); |
| 154 | _ = @import("behavior/fn_delegation.zig"); | 154 | _ = @import("behavior/fn_delegation.zig"); |
| 155 | _ = @import("behavior/ir_block_deps.zig"); | 155 | _ = @import("behavior/ir_block_deps.zig"); |
| 156 | _ = @import("behavior/math_stage1.zig"); | ||
| 157 | _ = @import("behavior/misc.zig"); | 156 | _ = @import("behavior/misc.zig"); |
| 158 | _ = @import("behavior/muladd.zig"); | 157 | _ = @import("behavior/muladd.zig"); |
| 159 | _ = @import("behavior/null_stage1.zig"); | 158 | _ = @import("behavior/null_stage1.zig"); |
test/behavior/math.zig+448| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 1 | const std = @import("std"); | 2 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | 4 | const expectEqual = std.testing.expectEqual; |
| ... | @@ -5,6 +6,7 @@ const expectEqualSlices = std.testing.expectEqualSlices; | ... | @@ -5,6 +6,7 @@ const expectEqualSlices = std.testing.expectEqualSlices; |
| 5 | const maxInt = std.math.maxInt; | 6 | const maxInt = std.math.maxInt; |
| 6 | const minInt = std.math.minInt; | 7 | const minInt = std.math.minInt; |
| 7 | const mem = std.mem; | 8 | const mem = std.mem; |
| 9 | const has_f80_rt = builtin.cpu.arch == .x86_64; | ||
| 8 | 10 | ||
| 9 | test "assignment operators" { | 11 | test "assignment operators" { |
| 10 | var i: u32 = 0; | 12 | var i: u32 = 0; |
| ... | @@ -612,3 +614,449 @@ test "overflow arithmetic with u0 values" { | ... | @@ -612,3 +614,449 @@ test "overflow arithmetic with u0 values" { |
| 612 | try expect(!@shlWithOverflow(u0, 0, 0, &result)); | 614 | try expect(!@shlWithOverflow(u0, 0, 0, &result)); |
| 613 | try expect(result == 0); | 615 | try expect(result == 0); |
| 614 | } | 616 | } |
| 617 | |||
| 618 | test "allow signed integer division/remainder when values are comptime known and positive or exact" { | ||
| 619 | try expect(5 / 3 == 1); | ||
| 620 | try expect(-5 / -3 == 1); | ||
| 621 | try expect(-6 / 3 == -2); | ||
| 622 | |||
| 623 | try expect(5 % 3 == 2); | ||
| 624 | try expect(-6 % 3 == 0); | ||
| 625 | |||
| 626 | if (builtin.zig_backend != .stage1) { | ||
| 627 | var undef: i32 = undefined; | ||
| 628 | if (0 % undef != 0) { | ||
| 629 | @compileError("0 as numerator should return comptime zero independent of denominator"); | ||
| 630 | } | ||
| 631 | } | ||
| 632 | } | ||
| 633 | |||
| 634 | test "quad hex float literal parsing accurate" { | ||
| 635 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 636 | |||
| 637 | const a: f128 = 0x1.1111222233334444555566667777p+0; | ||
| 638 | |||
| 639 | // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing. | ||
| 640 | const expected: u128 = 0x3fff1111222233334444555566667777; | ||
| 641 | try expect(@bitCast(u128, a) == expected); | ||
| 642 | |||
| 643 | // non-normalized | ||
| 644 | const b: f128 = 0x11.111222233334444555566667777p-4; | ||
| 645 | try expect(@bitCast(u128, b) == expected); | ||
| 646 | |||
| 647 | const S = struct { | ||
| 648 | fn doTheTest() !void { | ||
| 649 | { | ||
| 650 | var f: f128 = 0x1.2eab345678439abcdefea56782346p+5; | ||
| 651 | try expect(@bitCast(u128, f) == 0x40042eab345678439abcdefea5678234); | ||
| 652 | } | ||
| 653 | { | ||
| 654 | var f: f128 = 0x1.edcb34a235253948765432134674fp-1; | ||
| 655 | try expect(@bitCast(u128, f) == 0x3ffeedcb34a235253948765432134674); | ||
| 656 | } | ||
| 657 | { | ||
| 658 | var f: f128 = 0x1.353e45674d89abacc3a2ebf3ff4ffp-50; | ||
| 659 | try expect(@bitCast(u128, f) == 0x3fcd353e45674d89abacc3a2ebf3ff50); | ||
| 660 | } | ||
| 661 | { | ||
| 662 | var f: f128 = 0x1.ed8764648369535adf4be3214567fp-9; | ||
| 663 | try expect(@bitCast(u128, f) == 0x3ff6ed8764648369535adf4be3214568); | ||
| 664 | } | ||
| 665 | const exp2ft = [_]f64{ | ||
| 666 | 0x1.6a09e667f3bcdp-1, | ||
| 667 | 0x1.7a11473eb0187p-1, | ||
| 668 | 0x1.8ace5422aa0dbp-1, | ||
| 669 | 0x1.9c49182a3f090p-1, | ||
| 670 | 0x1.ae89f995ad3adp-1, | ||
| 671 | 0x1.c199bdd85529cp-1, | ||
| 672 | 0x1.d5818dcfba487p-1, | ||
| 673 | 0x1.ea4afa2a490dap-1, | ||
| 674 | 0x1.0000000000000p+0, | ||
| 675 | 0x1.0b5586cf9890fp+0, | ||
| 676 | 0x1.172b83c7d517bp+0, | ||
| 677 | 0x1.2387a6e756238p+0, | ||
| 678 | 0x1.306fe0a31b715p+0, | ||
| 679 | 0x1.3dea64c123422p+0, | ||
| 680 | 0x1.4bfdad5362a27p+0, | ||
| 681 | 0x1.5ab07dd485429p+0, | ||
| 682 | 0x1.8p23, | ||
| 683 | 0x1.62e430p-1, | ||
| 684 | 0x1.ebfbe0p-3, | ||
| 685 | 0x1.c6b348p-5, | ||
| 686 | 0x1.3b2c9cp-7, | ||
| 687 | 0x1.0p127, | ||
| 688 | -0x1.0p-149, | ||
| 689 | }; | ||
| 690 | |||
| 691 | const answers = [_]u64{ | ||
| 692 | 0x3fe6a09e667f3bcd, | ||
| 693 | 0x3fe7a11473eb0187, | ||
| 694 | 0x3fe8ace5422aa0db, | ||
| 695 | 0x3fe9c49182a3f090, | ||
| 696 | 0x3feae89f995ad3ad, | ||
| 697 | 0x3fec199bdd85529c, | ||
| 698 | 0x3fed5818dcfba487, | ||
| 699 | 0x3feea4afa2a490da, | ||
| 700 | 0x3ff0000000000000, | ||
| 701 | 0x3ff0b5586cf9890f, | ||
| 702 | 0x3ff172b83c7d517b, | ||
| 703 | 0x3ff2387a6e756238, | ||
| 704 | 0x3ff306fe0a31b715, | ||
| 705 | 0x3ff3dea64c123422, | ||
| 706 | 0x3ff4bfdad5362a27, | ||
| 707 | 0x3ff5ab07dd485429, | ||
| 708 | 0x4168000000000000, | ||
| 709 | 0x3fe62e4300000000, | ||
| 710 | 0x3fcebfbe00000000, | ||
| 711 | 0x3fac6b3480000000, | ||
| 712 | 0x3f83b2c9c0000000, | ||
| 713 | 0x47e0000000000000, | ||
| 714 | 0xb6a0000000000000, | ||
| 715 | }; | ||
| 716 | |||
| 717 | for (exp2ft) |x, i| { | ||
| 718 | try expect(@bitCast(u64, x) == answers[i]); | ||
| 719 | } | ||
| 720 | } | ||
| 721 | }; | ||
| 722 | try S.doTheTest(); | ||
| 723 | comptime try S.doTheTest(); | ||
| 724 | } | ||
| 725 | |||
| 726 | test "truncating shift left" { | ||
| 727 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 728 | |||
| 729 | try testShlTrunc(maxInt(u16)); | ||
| 730 | comptime try testShlTrunc(maxInt(u16)); | ||
| 731 | } | ||
| 732 | fn testShlTrunc(x: u16) !void { | ||
| 733 | const shifted = x << 1; | ||
| 734 | try expect(shifted == 65534); | ||
| 735 | } | ||
| 736 | |||
| 737 | test "exact shift left" { | ||
| 738 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 739 | |||
| 740 | try testShlExact(0b00110101); | ||
| 741 | comptime try testShlExact(0b00110101); | ||
| 742 | } | ||
| 743 | fn testShlExact(x: u8) !void { | ||
| 744 | const shifted = @shlExact(x, 2); | ||
| 745 | try expect(shifted == 0b11010100); | ||
| 746 | } | ||
| 747 | |||
| 748 | test "exact shift right" { | ||
| 749 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 750 | |||
| 751 | try testShrExact(0b10110100); | ||
| 752 | comptime try testShrExact(0b10110100); | ||
| 753 | } | ||
| 754 | fn testShrExact(x: u8) !void { | ||
| 755 | const shifted = @shrExact(x, 2); | ||
| 756 | try expect(shifted == 0b00101101); | ||
| 757 | } | ||
| 758 | |||
| 759 | test "shift left/right on u0 operand" { | ||
| 760 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 761 | |||
| 762 | const S = struct { | ||
| 763 | fn doTheTest() !void { | ||
| 764 | var x: u0 = 0; | ||
| 765 | var y: u0 = 0; | ||
| 766 | try expectEqual(@as(u0, 0), x << 0); | ||
| 767 | try expectEqual(@as(u0, 0), x >> 0); | ||
| 768 | try expectEqual(@as(u0, 0), x << y); | ||
| 769 | try expectEqual(@as(u0, 0), x >> y); | ||
| 770 | try expectEqual(@as(u0, 0), @shlExact(x, 0)); | ||
| 771 | try expectEqual(@as(u0, 0), @shrExact(x, 0)); | ||
| 772 | try expectEqual(@as(u0, 0), @shlExact(x, y)); | ||
| 773 | try expectEqual(@as(u0, 0), @shrExact(x, y)); | ||
| 774 | } | ||
| 775 | }; | ||
| 776 | try S.doTheTest(); | ||
| 777 | comptime try S.doTheTest(); | ||
| 778 | } | ||
| 779 | |||
| 780 | test "comptime float rem int" { | ||
| 781 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 782 | |||
| 783 | comptime { | ||
| 784 | var x = @as(f32, 1) % 2; | ||
| 785 | try expect(x == 1.0); | ||
| 786 | } | ||
| 787 | } | ||
| 788 | |||
| 789 | test "remainder division" { | ||
| 790 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 791 | |||
| 792 | comptime try remdiv(f16); | ||
| 793 | comptime try remdiv(f32); | ||
| 794 | comptime try remdiv(f64); | ||
| 795 | comptime try remdiv(f128); | ||
| 796 | try remdiv(f16); | ||
| 797 | try remdiv(f64); | ||
| 798 | try remdiv(f128); | ||
| 799 | } | ||
| 800 | |||
| 801 | fn remdiv(comptime T: type) !void { | ||
| 802 | try expect(@as(T, 1) == @as(T, 1) % @as(T, 2)); | ||
| 803 | try expect(@as(T, 1) == @as(T, 7) % @as(T, 3)); | ||
| 804 | } | ||
| 805 | |||
| 806 | test "@sqrt" { | ||
| 807 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 808 | |||
| 809 | try testSqrt(f64, 12.0); | ||
| 810 | comptime try testSqrt(f64, 12.0); | ||
| 811 | try testSqrt(f32, 13.0); | ||
| 812 | comptime try testSqrt(f32, 13.0); | ||
| 813 | try testSqrt(f16, 13.0); | ||
| 814 | comptime try testSqrt(f16, 13.0); | ||
| 815 | |||
| 816 | const x = 14.0; | ||
| 817 | const y = x * x; | ||
| 818 | const z = @sqrt(y); | ||
| 819 | comptime try expect(z == x); | ||
| 820 | } | ||
| 821 | |||
| 822 | fn testSqrt(comptime T: type, x: T) !void { | ||
| 823 | try expect(@sqrt(x * x) == x); | ||
| 824 | } | ||
| 825 | |||
| 826 | test "@fabs" { | ||
| 827 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 828 | |||
| 829 | try testFabs(f128, 12.0); | ||
| 830 | comptime try testFabs(f128, 12.0); | ||
| 831 | if (has_f80_rt) try testFabs(f80, 12.0); | ||
| 832 | // comptime try testFabs(f80, 12.0); | ||
| 833 | try testFabs(f64, 12.0); | ||
| 834 | comptime try testFabs(f64, 12.0); | ||
| 835 | try testFabs(f32, 12.0); | ||
| 836 | comptime try testFabs(f32, 12.0); | ||
| 837 | try testFabs(f16, 12.0); | ||
| 838 | comptime try testFabs(f16, 12.0); | ||
| 839 | |||
| 840 | const x = 14.0; | ||
| 841 | const y = -x; | ||
| 842 | const z = @fabs(y); | ||
| 843 | comptime try expectEqual(x, z); | ||
| 844 | } | ||
| 845 | |||
| 846 | fn testFabs(comptime T: type, x: T) !void { | ||
| 847 | const y = -x; | ||
| 848 | const z = @fabs(y); | ||
| 849 | try expectEqual(x, z); | ||
| 850 | } | ||
| 851 | |||
| 852 | test "@floor" { | ||
| 853 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 854 | |||
| 855 | // FIXME: Generates a floorl function call | ||
| 856 | // testFloor(f128, 12.0); | ||
| 857 | comptime try testFloor(f128, 12.0); | ||
| 858 | // try testFloor(f80, 12.0); | ||
| 859 | comptime try testFloor(f80, 12.0); | ||
| 860 | try testFloor(f64, 12.0); | ||
| 861 | comptime try testFloor(f64, 12.0); | ||
| 862 | try testFloor(f32, 12.0); | ||
| 863 | comptime try testFloor(f32, 12.0); | ||
| 864 | try testFloor(f16, 12.0); | ||
| 865 | comptime try testFloor(f16, 12.0); | ||
| 866 | |||
| 867 | const x = 14.0; | ||
| 868 | const y = x + 0.7; | ||
| 869 | const z = @floor(y); | ||
| 870 | comptime try expectEqual(x, z); | ||
| 871 | } | ||
| 872 | |||
| 873 | fn testFloor(comptime T: type, x: T) !void { | ||
| 874 | const y = x + 0.6; | ||
| 875 | const z = @floor(y); | ||
| 876 | try expectEqual(x, z); | ||
| 877 | } | ||
| 878 | |||
| 879 | test "@ceil" { | ||
| 880 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 881 | |||
| 882 | // FIXME: Generates a ceill function call | ||
| 883 | //testCeil(f128, 12.0); | ||
| 884 | comptime try testCeil(f128, 12.0); | ||
| 885 | // try testCeil(f80, 12.0); | ||
| 886 | comptime try testCeil(f80, 12.0); | ||
| 887 | try testCeil(f64, 12.0); | ||
| 888 | comptime try testCeil(f64, 12.0); | ||
| 889 | try testCeil(f32, 12.0); | ||
| 890 | comptime try testCeil(f32, 12.0); | ||
| 891 | try testCeil(f16, 12.0); | ||
| 892 | comptime try testCeil(f16, 12.0); | ||
| 893 | |||
| 894 | const x = 14.0; | ||
| 895 | const y = x - 0.7; | ||
| 896 | const z = @ceil(y); | ||
| 897 | comptime try expectEqual(x, z); | ||
| 898 | } | ||
| 899 | |||
| 900 | fn testCeil(comptime T: type, x: T) !void { | ||
| 901 | const y = x - 0.8; | ||
| 902 | const z = @ceil(y); | ||
| 903 | try expectEqual(x, z); | ||
| 904 | } | ||
| 905 | |||
| 906 | test "@trunc" { | ||
| 907 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 908 | |||
| 909 | // FIXME: Generates a truncl function call | ||
| 910 | //testTrunc(f128, 12.0); | ||
| 911 | comptime try testTrunc(f128, 12.0); | ||
| 912 | // try testTrunc(f80, 12.0); | ||
| 913 | // comptime try testTrunc(f80, 12.0); | ||
| 914 | comptime { | ||
| 915 | const x: f80 = 12.0; | ||
| 916 | const y = x + 0.8; | ||
| 917 | const z = @trunc(y); | ||
| 918 | try expectEqual(x, z); | ||
| 919 | } | ||
| 920 | try testTrunc(f64, 12.0); | ||
| 921 | comptime try testTrunc(f64, 12.0); | ||
| 922 | try testTrunc(f32, 12.0); | ||
| 923 | comptime try testTrunc(f32, 12.0); | ||
| 924 | try testTrunc(f16, 12.0); | ||
| 925 | comptime try testTrunc(f16, 12.0); | ||
| 926 | |||
| 927 | const x = 14.0; | ||
| 928 | const y = x + 0.7; | ||
| 929 | const z = @trunc(y); | ||
| 930 | comptime try expectEqual(x, z); | ||
| 931 | } | ||
| 932 | |||
| 933 | fn testTrunc(comptime T: type, x: T) !void { | ||
| 934 | { | ||
| 935 | const y = x + 0.8; | ||
| 936 | const z = @trunc(y); | ||
| 937 | try expectEqual(x, z); | ||
| 938 | } | ||
| 939 | |||
| 940 | { | ||
| 941 | const y = -x - 0.8; | ||
| 942 | const z = @trunc(y); | ||
| 943 | try expectEqual(-x, z); | ||
| 944 | } | ||
| 945 | } | ||
| 946 | |||
| 947 | test "@round" { | ||
| 948 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 949 | |||
| 950 | // FIXME: Generates a roundl function call | ||
| 951 | //testRound(f128, 12.0); | ||
| 952 | comptime try testRound(f128, 12.0); | ||
| 953 | // try testRound(f80, 12.0); | ||
| 954 | comptime try testRound(f80, 12.0); | ||
| 955 | try testRound(f64, 12.0); | ||
| 956 | comptime try testRound(f64, 12.0); | ||
| 957 | try testRound(f32, 12.0); | ||
| 958 | comptime try testRound(f32, 12.0); | ||
| 959 | try testRound(f16, 12.0); | ||
| 960 | comptime try testRound(f16, 12.0); | ||
| 961 | |||
| 962 | const x = 14.0; | ||
| 963 | const y = x + 0.4; | ||
| 964 | const z = @round(y); | ||
| 965 | comptime try expectEqual(x, z); | ||
| 966 | } | ||
| 967 | |||
| 968 | fn testRound(comptime T: type, x: T) !void { | ||
| 969 | const y = x - 0.5; | ||
| 970 | const z = @round(y); | ||
| 971 | try expectEqual(x, z); | ||
| 972 | } | ||
| 973 | |||
| 974 | test "vector integer addition" { | ||
| 975 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 976 | |||
| 977 | const S = struct { | ||
| 978 | fn doTheTest() !void { | ||
| 979 | var a: std.meta.Vector(4, i32) = [_]i32{ 1, 2, 3, 4 }; | ||
| 980 | var b: std.meta.Vector(4, i32) = [_]i32{ 5, 6, 7, 8 }; | ||
| 981 | var result = a + b; | ||
| 982 | var result_array: [4]i32 = result; | ||
| 983 | const expected = [_]i32{ 6, 8, 10, 12 }; | ||
| 984 | try expectEqualSlices(i32, &expected, &result_array); | ||
| 985 | } | ||
| 986 | }; | ||
| 987 | try S.doTheTest(); | ||
| 988 | comptime try S.doTheTest(); | ||
| 989 | } | ||
| 990 | |||
| 991 | test "NaN comparison" { | ||
| 992 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 993 | |||
| 994 | try testNanEqNan(f16); | ||
| 995 | try testNanEqNan(f32); | ||
| 996 | try testNanEqNan(f64); | ||
| 997 | try testNanEqNan(f128); | ||
| 998 | if (has_f80_rt) try testNanEqNan(f80); | ||
| 999 | comptime try testNanEqNan(f16); | ||
| 1000 | comptime try testNanEqNan(f32); | ||
| 1001 | comptime try testNanEqNan(f64); | ||
| 1002 | comptime try testNanEqNan(f128); | ||
| 1003 | // comptime try testNanEqNan(f80); | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | fn testNanEqNan(comptime F: type) !void { | ||
| 1007 | var nan1 = std.math.nan(F); | ||
| 1008 | var nan2 = std.math.nan(F); | ||
| 1009 | try expect(nan1 != nan2); | ||
| 1010 | try expect(!(nan1 == nan2)); | ||
| 1011 | try expect(!(nan1 > nan2)); | ||
| 1012 | try expect(!(nan1 >= nan2)); | ||
| 1013 | try expect(!(nan1 < nan2)); | ||
| 1014 | try expect(!(nan1 <= nan2)); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | test "vector comparison" { | ||
| 1018 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 1019 | |||
| 1020 | const S = struct { | ||
| 1021 | fn doTheTest() !void { | ||
| 1022 | var a: std.meta.Vector(6, i32) = [_]i32{ 1, 3, -1, 5, 7, 9 }; | ||
| 1023 | var b: std.meta.Vector(6, i32) = [_]i32{ -1, 3, 0, 6, 10, -10 }; | ||
| 1024 | try expect(mem.eql(bool, &@as([6]bool, a < b), &[_]bool{ false, false, true, true, true, false })); | ||
| 1025 | try expect(mem.eql(bool, &@as([6]bool, a <= b), &[_]bool{ false, true, true, true, true, false })); | ||
| 1026 | try expect(mem.eql(bool, &@as([6]bool, a == b), &[_]bool{ false, true, false, false, false, false })); | ||
| 1027 | try expect(mem.eql(bool, &@as([6]bool, a != b), &[_]bool{ true, false, true, true, true, true })); | ||
| 1028 | try expect(mem.eql(bool, &@as([6]bool, a > b), &[_]bool{ true, false, false, false, false, true })); | ||
| 1029 | try expect(mem.eql(bool, &@as([6]bool, a >= b), &[_]bool{ true, true, false, false, false, true })); | ||
| 1030 | } | ||
| 1031 | }; | ||
| 1032 | try S.doTheTest(); | ||
| 1033 | comptime try S.doTheTest(); | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | test "compare undefined literal with comptime_int" { | ||
| 1037 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 1038 | |||
| 1039 | var x = undefined == 1; | ||
| 1040 | // x is now undefined with type bool | ||
| 1041 | x = true; | ||
| 1042 | try expect(x); | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | test "signed zeros are represented properly" { | ||
| 1046 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 1047 | |||
| 1048 | const S = struct { | ||
| 1049 | fn doTheTest() !void { | ||
| 1050 | inline for ([_]type{ f16, f32, f64, f128 }) |T| { | ||
| 1051 | const ST = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | ||
| 1052 | var as_fp_val = -@as(T, 0.0); | ||
| 1053 | var as_uint_val = @bitCast(ST, as_fp_val); | ||
| 1054 | // Ensure the sign bit is set. | ||
| 1055 | try expect(as_uint_val >> (@typeInfo(T).Float.bits - 1) == 1); | ||
| 1056 | } | ||
| 1057 | } | ||
| 1058 | }; | ||
| 1059 | |||
| 1060 | try S.doTheTest(); | ||
| 1061 | comptime try S.doTheTest(); | ||
| 1062 | } |
test/behavior/math_stage1.zig deleted-411| ... | @@ -1,411 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const expectEqual = std.testing.expectEqual; | ||
| 4 | const expectEqualSlices = std.testing.expectEqualSlices; | ||
| 5 | const maxInt = std.math.maxInt; | ||
| 6 | const minInt = std.math.minInt; | ||
| 7 | const mem = std.mem; | ||
| 8 | const has_f80_rt = @import("builtin").cpu.arch == .x86_64; | ||
| 9 | |||
| 10 | test "allow signed integer division/remainder when values are comptime known and positive or exact" { | ||
| 11 | try expect(5 / 3 == 1); | ||
| 12 | try expect(-5 / -3 == 1); | ||
| 13 | try expect(-6 / 3 == -2); | ||
| 14 | |||
| 15 | try expect(5 % 3 == 2); | ||
| 16 | try expect(-6 % 3 == 0); | ||
| 17 | } | ||
| 18 | |||
| 19 | test "quad hex float literal parsing accurate" { | ||
| 20 | const a: f128 = 0x1.1111222233334444555566667777p+0; | ||
| 21 | |||
| 22 | // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing. | ||
| 23 | const expected: u128 = 0x3fff1111222233334444555566667777; | ||
| 24 | try expect(@bitCast(u128, a) == expected); | ||
| 25 | |||
| 26 | // non-normalized | ||
| 27 | const b: f128 = 0x11.111222233334444555566667777p-4; | ||
| 28 | try expect(@bitCast(u128, b) == expected); | ||
| 29 | |||
| 30 | const S = struct { | ||
| 31 | fn doTheTest() !void { | ||
| 32 | { | ||
| 33 | var f: f128 = 0x1.2eab345678439abcdefea56782346p+5; | ||
| 34 | try expect(@bitCast(u128, f) == 0x40042eab345678439abcdefea5678234); | ||
| 35 | } | ||
| 36 | { | ||
| 37 | var f: f128 = 0x1.edcb34a235253948765432134674fp-1; | ||
| 38 | try expect(@bitCast(u128, f) == 0x3ffeedcb34a235253948765432134674); | ||
| 39 | } | ||
| 40 | { | ||
| 41 | var f: f128 = 0x1.353e45674d89abacc3a2ebf3ff4ffp-50; | ||
| 42 | try expect(@bitCast(u128, f) == 0x3fcd353e45674d89abacc3a2ebf3ff50); | ||
| 43 | } | ||
| 44 | { | ||
| 45 | var f: f128 = 0x1.ed8764648369535adf4be3214567fp-9; | ||
| 46 | try expect(@bitCast(u128, f) == 0x3ff6ed8764648369535adf4be3214568); | ||
| 47 | } | ||
| 48 | const exp2ft = [_]f64{ | ||
| 49 | 0x1.6a09e667f3bcdp-1, | ||
| 50 | 0x1.7a11473eb0187p-1, | ||
| 51 | 0x1.8ace5422aa0dbp-1, | ||
| 52 | 0x1.9c49182a3f090p-1, | ||
| 53 | 0x1.ae89f995ad3adp-1, | ||
| 54 | 0x1.c199bdd85529cp-1, | ||
| 55 | 0x1.d5818dcfba487p-1, | ||
| 56 | 0x1.ea4afa2a490dap-1, | ||
| 57 | 0x1.0000000000000p+0, | ||
| 58 | 0x1.0b5586cf9890fp+0, | ||
| 59 | 0x1.172b83c7d517bp+0, | ||
| 60 | 0x1.2387a6e756238p+0, | ||
| 61 | 0x1.306fe0a31b715p+0, | ||
| 62 | 0x1.3dea64c123422p+0, | ||
| 63 | 0x1.4bfdad5362a27p+0, | ||
| 64 | 0x1.5ab07dd485429p+0, | ||
| 65 | 0x1.8p23, | ||
| 66 | 0x1.62e430p-1, | ||
| 67 | 0x1.ebfbe0p-3, | ||
| 68 | 0x1.c6b348p-5, | ||
| 69 | 0x1.3b2c9cp-7, | ||
| 70 | 0x1.0p127, | ||
| 71 | -0x1.0p-149, | ||
| 72 | }; | ||
| 73 | |||
| 74 | const answers = [_]u64{ | ||
| 75 | 0x3fe6a09e667f3bcd, | ||
| 76 | 0x3fe7a11473eb0187, | ||
| 77 | 0x3fe8ace5422aa0db, | ||
| 78 | 0x3fe9c49182a3f090, | ||
| 79 | 0x3feae89f995ad3ad, | ||
| 80 | 0x3fec199bdd85529c, | ||
| 81 | 0x3fed5818dcfba487, | ||
| 82 | 0x3feea4afa2a490da, | ||
| 83 | 0x3ff0000000000000, | ||
| 84 | 0x3ff0b5586cf9890f, | ||
| 85 | 0x3ff172b83c7d517b, | ||
| 86 | 0x3ff2387a6e756238, | ||
| 87 | 0x3ff306fe0a31b715, | ||
| 88 | 0x3ff3dea64c123422, | ||
| 89 | 0x3ff4bfdad5362a27, | ||
| 90 | 0x3ff5ab07dd485429, | ||
| 91 | 0x4168000000000000, | ||
| 92 | 0x3fe62e4300000000, | ||
| 93 | 0x3fcebfbe00000000, | ||
| 94 | 0x3fac6b3480000000, | ||
| 95 | 0x3f83b2c9c0000000, | ||
| 96 | 0x47e0000000000000, | ||
| 97 | 0xb6a0000000000000, | ||
| 98 | }; | ||
| 99 | |||
| 100 | for (exp2ft) |x, i| { | ||
| 101 | try expect(@bitCast(u64, x) == answers[i]); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | }; | ||
| 105 | try S.doTheTest(); | ||
| 106 | comptime try S.doTheTest(); | ||
| 107 | } | ||
| 108 | |||
| 109 | test "truncating shift left" { | ||
| 110 | try testShlTrunc(maxInt(u16)); | ||
| 111 | comptime try testShlTrunc(maxInt(u16)); | ||
| 112 | } | ||
| 113 | fn testShlTrunc(x: u16) !void { | ||
| 114 | const shifted = x << 1; | ||
| 115 | try expect(shifted == 65534); | ||
| 116 | } | ||
| 117 | |||
| 118 | test "exact shift left" { | ||
| 119 | try testShlExact(0b00110101); | ||
| 120 | comptime try testShlExact(0b00110101); | ||
| 121 | } | ||
| 122 | fn testShlExact(x: u8) !void { | ||
| 123 | const shifted = @shlExact(x, 2); | ||
| 124 | try expect(shifted == 0b11010100); | ||
| 125 | } | ||
| 126 | |||
| 127 | test "exact shift right" { | ||
| 128 | try testShrExact(0b10110100); | ||
| 129 | comptime try testShrExact(0b10110100); | ||
| 130 | } | ||
| 131 | fn testShrExact(x: u8) !void { | ||
| 132 | const shifted = @shrExact(x, 2); | ||
| 133 | try expect(shifted == 0b00101101); | ||
| 134 | } | ||
| 135 | |||
| 136 | test "shift left/right on u0 operand" { | ||
| 137 | const S = struct { | ||
| 138 | fn doTheTest() !void { | ||
| 139 | var x: u0 = 0; | ||
| 140 | var y: u0 = 0; | ||
| 141 | try expectEqual(@as(u0, 0), x << 0); | ||
| 142 | try expectEqual(@as(u0, 0), x >> 0); | ||
| 143 | try expectEqual(@as(u0, 0), x << y); | ||
| 144 | try expectEqual(@as(u0, 0), x >> y); | ||
| 145 | try expectEqual(@as(u0, 0), @shlExact(x, 0)); | ||
| 146 | try expectEqual(@as(u0, 0), @shrExact(x, 0)); | ||
| 147 | try expectEqual(@as(u0, 0), @shlExact(x, y)); | ||
| 148 | try expectEqual(@as(u0, 0), @shrExact(x, y)); | ||
| 149 | } | ||
| 150 | }; | ||
| 151 | try S.doTheTest(); | ||
| 152 | comptime try S.doTheTest(); | ||
| 153 | } | ||
| 154 | |||
| 155 | test "comptime float rem int" { | ||
| 156 | comptime { | ||
| 157 | var x = @as(f32, 1) % 2; | ||
| 158 | try expect(x == 1.0); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | test "remainder division" { | ||
| 163 | comptime try remdiv(f16); | ||
| 164 | comptime try remdiv(f32); | ||
| 165 | comptime try remdiv(f64); | ||
| 166 | comptime try remdiv(f128); | ||
| 167 | try remdiv(f16); | ||
| 168 | try remdiv(f64); | ||
| 169 | try remdiv(f128); | ||
| 170 | } | ||
| 171 | |||
| 172 | fn remdiv(comptime T: type) !void { | ||
| 173 | try expect(@as(T, 1) == @as(T, 1) % @as(T, 2)); | ||
| 174 | try expect(@as(T, 1) == @as(T, 7) % @as(T, 3)); | ||
| 175 | } | ||
| 176 | |||
| 177 | test "@sqrt" { | ||
| 178 | try testSqrt(f64, 12.0); | ||
| 179 | comptime try testSqrt(f64, 12.0); | ||
| 180 | try testSqrt(f32, 13.0); | ||
| 181 | comptime try testSqrt(f32, 13.0); | ||
| 182 | try testSqrt(f16, 13.0); | ||
| 183 | comptime try testSqrt(f16, 13.0); | ||
| 184 | |||
| 185 | const x = 14.0; | ||
| 186 | const y = x * x; | ||
| 187 | const z = @sqrt(y); | ||
| 188 | comptime try expect(z == x); | ||
| 189 | } | ||
| 190 | |||
| 191 | fn testSqrt(comptime T: type, x: T) !void { | ||
| 192 | try expect(@sqrt(x * x) == x); | ||
| 193 | } | ||
| 194 | |||
| 195 | test "@fabs" { | ||
| 196 | try testFabs(f128, 12.0); | ||
| 197 | comptime try testFabs(f128, 12.0); | ||
| 198 | if (has_f80_rt) try testFabs(f80, 12.0); | ||
| 199 | // comptime try testFabs(f80, 12.0); | ||
| 200 | try testFabs(f64, 12.0); | ||
| 201 | comptime try testFabs(f64, 12.0); | ||
| 202 | try testFabs(f32, 12.0); | ||
| 203 | comptime try testFabs(f32, 12.0); | ||
| 204 | try testFabs(f16, 12.0); | ||
| 205 | comptime try testFabs(f16, 12.0); | ||
| 206 | |||
| 207 | const x = 14.0; | ||
| 208 | const y = -x; | ||
| 209 | const z = @fabs(y); | ||
| 210 | comptime try expectEqual(x, z); | ||
| 211 | } | ||
| 212 | |||
| 213 | fn testFabs(comptime T: type, x: T) !void { | ||
| 214 | const y = -x; | ||
| 215 | const z = @fabs(y); | ||
| 216 | try expectEqual(x, z); | ||
| 217 | } | ||
| 218 | |||
| 219 | test "@floor" { | ||
| 220 | // FIXME: Generates a floorl function call | ||
| 221 | // testFloor(f128, 12.0); | ||
| 222 | comptime try testFloor(f128, 12.0); | ||
| 223 | // try testFloor(f80, 12.0); | ||
| 224 | comptime try testFloor(f80, 12.0); | ||
| 225 | try testFloor(f64, 12.0); | ||
| 226 | comptime try testFloor(f64, 12.0); | ||
| 227 | try testFloor(f32, 12.0); | ||
| 228 | comptime try testFloor(f32, 12.0); | ||
| 229 | try testFloor(f16, 12.0); | ||
| 230 | comptime try testFloor(f16, 12.0); | ||
| 231 | |||
| 232 | const x = 14.0; | ||
| 233 | const y = x + 0.7; | ||
| 234 | const z = @floor(y); | ||
| 235 | comptime try expectEqual(x, z); | ||
| 236 | } | ||
| 237 | |||
| 238 | fn testFloor(comptime T: type, x: T) !void { | ||
| 239 | const y = x + 0.6; | ||
| 240 | const z = @floor(y); | ||
| 241 | try expectEqual(x, z); | ||
| 242 | } | ||
| 243 | |||
| 244 | test "@ceil" { | ||
| 245 | // FIXME: Generates a ceill function call | ||
| 246 | //testCeil(f128, 12.0); | ||
| 247 | comptime try testCeil(f128, 12.0); | ||
| 248 | // try testCeil(f80, 12.0); | ||
| 249 | comptime try testCeil(f80, 12.0); | ||
| 250 | try testCeil(f64, 12.0); | ||
| 251 | comptime try testCeil(f64, 12.0); | ||
| 252 | try testCeil(f32, 12.0); | ||
| 253 | comptime try testCeil(f32, 12.0); | ||
| 254 | try testCeil(f16, 12.0); | ||
| 255 | comptime try testCeil(f16, 12.0); | ||
| 256 | |||
| 257 | const x = 14.0; | ||
| 258 | const y = x - 0.7; | ||
| 259 | const z = @ceil(y); | ||
| 260 | comptime try expectEqual(x, z); | ||
| 261 | } | ||
| 262 | |||
| 263 | fn testCeil(comptime T: type, x: T) !void { | ||
| 264 | const y = x - 0.8; | ||
| 265 | const z = @ceil(y); | ||
| 266 | try expectEqual(x, z); | ||
| 267 | } | ||
| 268 | |||
| 269 | test "@trunc" { | ||
| 270 | // FIXME: Generates a truncl function call | ||
| 271 | //testTrunc(f128, 12.0); | ||
| 272 | comptime try testTrunc(f128, 12.0); | ||
| 273 | // try testTrunc(f80, 12.0); | ||
| 274 | // comptime try testTrunc(f80, 12.0); | ||
| 275 | comptime { | ||
| 276 | const x: f80 = 12.0; | ||
| 277 | const y = x + 0.8; | ||
| 278 | const z = @trunc(y); | ||
| 279 | try expectEqual(x, z); | ||
| 280 | } | ||
| 281 | try testTrunc(f64, 12.0); | ||
| 282 | comptime try testTrunc(f64, 12.0); | ||
| 283 | try testTrunc(f32, 12.0); | ||
| 284 | comptime try testTrunc(f32, 12.0); | ||
| 285 | try testTrunc(f16, 12.0); | ||
| 286 | comptime try testTrunc(f16, 12.0); | ||
| 287 | |||
| 288 | const x = 14.0; | ||
| 289 | const y = x + 0.7; | ||
| 290 | const z = @trunc(y); | ||
| 291 | comptime try expectEqual(x, z); | ||
| 292 | } | ||
| 293 | |||
| 294 | fn testTrunc(comptime T: type, x: T) !void { | ||
| 295 | { | ||
| 296 | const y = x + 0.8; | ||
| 297 | const z = @trunc(y); | ||
| 298 | try expectEqual(x, z); | ||
| 299 | } | ||
| 300 | |||
| 301 | { | ||
| 302 | const y = -x - 0.8; | ||
| 303 | const z = @trunc(y); | ||
| 304 | try expectEqual(-x, z); | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | test "@round" { | ||
| 309 | // FIXME: Generates a roundl function call | ||
| 310 | //testRound(f128, 12.0); | ||
| 311 | comptime try testRound(f128, 12.0); | ||
| 312 | // try testRound(f80, 12.0); | ||
| 313 | comptime try testRound(f80, 12.0); | ||
| 314 | try testRound(f64, 12.0); | ||
| 315 | comptime try testRound(f64, 12.0); | ||
| 316 | try testRound(f32, 12.0); | ||
| 317 | comptime try testRound(f32, 12.0); | ||
| 318 | try testRound(f16, 12.0); | ||
| 319 | comptime try testRound(f16, 12.0); | ||
| 320 | |||
| 321 | const x = 14.0; | ||
| 322 | const y = x + 0.4; | ||
| 323 | const z = @round(y); | ||
| 324 | comptime try expectEqual(x, z); | ||
| 325 | } | ||
| 326 | |||
| 327 | fn testRound(comptime T: type, x: T) !void { | ||
| 328 | const y = x - 0.5; | ||
| 329 | const z = @round(y); | ||
| 330 | try expectEqual(x, z); | ||
| 331 | } | ||
| 332 | |||
| 333 | test "vector integer addition" { | ||
| 334 | const S = struct { | ||
| 335 | fn doTheTest() !void { | ||
| 336 | var a: std.meta.Vector(4, i32) = [_]i32{ 1, 2, 3, 4 }; | ||
| 337 | var b: std.meta.Vector(4, i32) = [_]i32{ 5, 6, 7, 8 }; | ||
| 338 | var result = a + b; | ||
| 339 | var result_array: [4]i32 = result; | ||
| 340 | const expected = [_]i32{ 6, 8, 10, 12 }; | ||
| 341 | try expectEqualSlices(i32, &expected, &result_array); | ||
| 342 | } | ||
| 343 | }; | ||
| 344 | try S.doTheTest(); | ||
| 345 | comptime try S.doTheTest(); | ||
| 346 | } | ||
| 347 | |||
| 348 | test "NaN comparison" { | ||
| 349 | try testNanEqNan(f16); | ||
| 350 | try testNanEqNan(f32); | ||
| 351 | try testNanEqNan(f64); | ||
| 352 | try testNanEqNan(f128); | ||
| 353 | if (has_f80_rt) try testNanEqNan(f80); | ||
| 354 | comptime try testNanEqNan(f16); | ||
| 355 | comptime try testNanEqNan(f32); | ||
| 356 | comptime try testNanEqNan(f64); | ||
| 357 | comptime try testNanEqNan(f128); | ||
| 358 | // comptime try testNanEqNan(f80); | ||
| 359 | } | ||
| 360 | |||
| 361 | fn testNanEqNan(comptime F: type) !void { | ||
| 362 | var nan1 = std.math.nan(F); | ||
| 363 | var nan2 = std.math.nan(F); | ||
| 364 | try expect(nan1 != nan2); | ||
| 365 | try expect(!(nan1 == nan2)); | ||
| 366 | try expect(!(nan1 > nan2)); | ||
| 367 | try expect(!(nan1 >= nan2)); | ||
| 368 | try expect(!(nan1 < nan2)); | ||
| 369 | try expect(!(nan1 <= nan2)); | ||
| 370 | } | ||
| 371 | |||
| 372 | test "vector comparison" { | ||
| 373 | const S = struct { | ||
| 374 | fn doTheTest() !void { | ||
| 375 | var a: std.meta.Vector(6, i32) = [_]i32{ 1, 3, -1, 5, 7, 9 }; | ||
| 376 | var b: std.meta.Vector(6, i32) = [_]i32{ -1, 3, 0, 6, 10, -10 }; | ||
| 377 | try expect(mem.eql(bool, &@as([6]bool, a < b), &[_]bool{ false, false, true, true, true, false })); | ||
| 378 | try expect(mem.eql(bool, &@as([6]bool, a <= b), &[_]bool{ false, true, true, true, true, false })); | ||
| 379 | try expect(mem.eql(bool, &@as([6]bool, a == b), &[_]bool{ false, true, false, false, false, false })); | ||
| 380 | try expect(mem.eql(bool, &@as([6]bool, a != b), &[_]bool{ true, false, true, true, true, true })); | ||
| 381 | try expect(mem.eql(bool, &@as([6]bool, a > b), &[_]bool{ true, false, false, false, false, true })); | ||
| 382 | try expect(mem.eql(bool, &@as([6]bool, a >= b), &[_]bool{ true, true, false, false, false, true })); | ||
| 383 | } | ||
| 384 | }; | ||
| 385 | try S.doTheTest(); | ||
| 386 | comptime try S.doTheTest(); | ||
| 387 | } | ||
| 388 | |||
| 389 | test "compare undefined literal with comptime_int" { | ||
| 390 | var x = undefined == 1; | ||
| 391 | // x is now undefined with type bool | ||
| 392 | x = true; | ||
| 393 | try expect(x); | ||
| 394 | } | ||
| 395 | |||
| 396 | test "signed zeros are represented properly" { | ||
| 397 | const S = struct { | ||
| 398 | fn doTheTest() !void { | ||
| 399 | inline for ([_]type{ f16, f32, f64, f128 }) |T| { | ||
| 400 | const ST = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | ||
| 401 | var as_fp_val = -@as(T, 0.0); | ||
| 402 | var as_uint_val = @bitCast(ST, as_fp_val); | ||
| 403 | // Ensure the sign bit is set. | ||
| 404 | try expect(as_uint_val >> (@typeInfo(T).Float.bits - 1) == 1); | ||
| 405 | } | ||
| 406 | } | ||
| 407 | }; | ||
| 408 | |||
| 409 | try S.doTheTest(); | ||
| 410 | comptime try S.doTheTest(); | ||
| 411 | } | ||