| author | |
| committer | |
| log | 1157ee130732449811294d70021aaafa588d3048 |
| tree | 442f27ca03ff3e1240b1cf9a572343d8c0a6f11e |
| parent | f595545c10a35b85879edfa3c002ce308ffeb6c2 |
* Add support for fabs, floor, ceil, trunc and round
* Add behavior tests5 files changed, 173 insertions(+), 5 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -288,6 +288,7 @@ set(ZIG_SOURCES |
| 288 | 288 | "${CMAKE_SOURCE_DIR}/src/target.cpp" |
| 289 | 289 | "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" |
| 290 | 290 | "${CMAKE_SOURCE_DIR}/src/util.cpp" |
| 291 | "${CMAKE_SOURCE_DIR}/src/softfloat_ext.cpp" | |
| 291 | 292 | "${ZIG_SOURCES_MEM_PROFILE}" |
| 292 | 293 | ) |
| 293 | 294 | set(OPTIMIZED_C_SOURCES |
src/ir.cpp+16-5| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | #include "os.hpp" |
| 14 | 14 | #include "range_set.hpp" |
| 15 | 15 | #include "softfloat.hpp" |
| 16 | #include "softfloat_ext.hpp" | |
| 16 | 17 | #include "util.hpp" |
| 17 | 18 | #include "mem_list.hpp" |
| 18 | 19 | #include "all_types.hpp" |
| ... | ... | @@ -30303,6 +30304,21 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF |
| 30303 | 30304 | case BuiltinFnIdSqrt: |
| 30304 | 30305 | f128M_sqrt(in, out); |
| 30305 | 30306 | break; |
| 30307 | case BuiltinFnIdFabs: | |
| 30308 | f128M_abs(in, out); | |
| 30309 | break; | |
| 30310 | case BuiltinFnIdFloor: | |
| 30311 | f128M_roundToInt(in, softfloat_round_min, false, out); | |
| 30312 | break; | |
| 30313 | case BuiltinFnIdCeil: | |
| 30314 | f128M_roundToInt(in, softfloat_round_max, false, out); | |
| 30315 | break; | |
| 30316 | case BuiltinFnIdTrunc: | |
| 30317 | f128M_trunc(in, out); | |
| 30318 | break; | |
| 30319 | case BuiltinFnIdRound: | |
| 30320 | f128M_roundToInt(in, softfloat_round_near_maxMag, false, out); | |
| 30321 | break; | |
| 30306 | 30322 | case BuiltinFnIdNearbyInt: |
| 30307 | 30323 | case BuiltinFnIdSin: |
| 30308 | 30324 | case BuiltinFnIdCos: |
| ... | ... | @@ -30311,11 +30327,6 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF |
| 30311 | 30327 | case BuiltinFnIdLog: |
| 30312 | 30328 | case BuiltinFnIdLog10: |
| 30313 | 30329 | case BuiltinFnIdLog2: |
| 30314 | case BuiltinFnIdFabs: | |
| 30315 | case BuiltinFnIdFloor: | |
| 30316 | case BuiltinFnIdCeil: | |
| 30317 | case BuiltinFnIdTrunc: | |
| 30318 | case BuiltinFnIdRound: | |
| 30319 | 30330 | return ir_add_error(ira, source_instr, |
| 30320 | 30331 | buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026", |
| 30321 | 30332 | float_op_to_name(fop), buf_ptr(&float_type->name))); |
src/softfloat_ext.cpp created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | #include "softfloat_ext.hpp" | |
| 2 | ||
| 3 | extern "C" { | |
| 4 | #include "softfloat.h" | |
| 5 | } | |
| 6 | ||
| 7 | void f128M_abs(const float128_t *aPtr, float128_t *zPtr) { | |
| 8 | float128_t zero_float; | |
| 9 | ui32_to_f128M(0, &zero_float); | |
| 10 | if (f128M_lt(aPtr, &zero_float)) { | |
| 11 | f128M_sub(&zero_float, aPtr, zPtr); | |
| 12 | } else { | |
| 13 | *zPtr = *aPtr; | |
| 14 | } | |
| 15 | } | |
| 16 | ||
| 17 | void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) { | |
| 18 | float128_t zero_float; | |
| 19 | ui32_to_f128M(0, &zero_float); | |
| 20 | if (f128M_lt(aPtr, &zero_float)) { | |
| 21 | f128M_roundToInt(aPtr, softfloat_round_max, false, zPtr); | |
| 22 | } else { | |
| 23 | f128M_roundToInt(aPtr, softfloat_round_min, false, zPtr); | |
| 24 | } | |
| 25 | } | |
| \ No newline at end of file |
src/softfloat_ext.hpp created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | #ifndef ZIG_SOFTFLOAT_EXT_HPP | |
| 2 | #define ZIG_SOFTFLOAT_EXT_HPP | |
| 3 | ||
| 4 | #include "softfloat_types.h" | |
| 5 | ||
| 6 | void f128M_abs(const float128_t *aPtr, float128_t *zPtr); | |
| 7 | void f128M_trunc(const float128_t *aPtr, float128_t *zPtr); | |
| 8 | ||
| 9 | #endif | |
| \ No newline at end of file |
test/stage1/behavior/math.zig+122| ... | ... | @@ -634,6 +634,128 @@ fn testSqrt(comptime T: type, x: T) void { |
| 634 | 634 | expect(@sqrt(x * x) == x); |
| 635 | 635 | } |
| 636 | 636 | |
| 637 | test "@fabs" { | |
| 638 | testFabs(f128, 12.0); | |
| 639 | comptime testFabs(f128, 12.0); | |
| 640 | testFabs(f64, 12.0); | |
| 641 | comptime testFabs(f64, 12.0); | |
| 642 | testFabs(f32, 12.0); | |
| 643 | comptime testFabs(f32, 12.0); | |
| 644 | testFabs(f16, 12.0); | |
| 645 | comptime testFabs(f16, 12.0); | |
| 646 | ||
| 647 | const x = 14.0; | |
| 648 | const y = -x; | |
| 649 | const z = @fabs(y); | |
| 650 | comptime expectEqual(x, z); | |
| 651 | } | |
| 652 | ||
| 653 | fn testFabs(comptime T: type, x: T) void { | |
| 654 | const y = -x; | |
| 655 | const z = @fabs(y); | |
| 656 | expectEqual(x, z); | |
| 657 | } | |
| 658 | ||
| 659 | test "@floor" { | |
| 660 | // FIXME: Generates a floorl function call | |
| 661 | // testFloor(f128, 12.0); | |
| 662 | comptime testFloor(f128, 12.0); | |
| 663 | testFloor(f64, 12.0); | |
| 664 | comptime testFloor(f64, 12.0); | |
| 665 | testFloor(f32, 12.0); | |
| 666 | comptime testFloor(f32, 12.0); | |
| 667 | testFloor(f16, 12.0); | |
| 668 | comptime testFloor(f16, 12.0); | |
| 669 | ||
| 670 | const x = 14.0; | |
| 671 | const y = x + 0.7; | |
| 672 | const z = @floor(y); | |
| 673 | comptime expectEqual(x, z); | |
| 674 | } | |
| 675 | ||
| 676 | fn testFloor(comptime T: type, x: T) void { | |
| 677 | const y = x + 0.6; | |
| 678 | const z = @floor(y); | |
| 679 | expectEqual(x, z); | |
| 680 | } | |
| 681 | ||
| 682 | test "@ceil" { | |
| 683 | // FIXME: Generates a ceill function call | |
| 684 | //testCeil(f128, 12.0); | |
| 685 | comptime testCeil(f128, 12.0); | |
| 686 | testCeil(f64, 12.0); | |
| 687 | comptime testCeil(f64, 12.0); | |
| 688 | testCeil(f32, 12.0); | |
| 689 | comptime testCeil(f32, 12.0); | |
| 690 | testCeil(f16, 12.0); | |
| 691 | comptime testCeil(f16, 12.0); | |
| 692 | ||
| 693 | const x = 14.0; | |
| 694 | const y = x - 0.7; | |
| 695 | const z = @ceil(y); | |
| 696 | comptime expectEqual(x, z); | |
| 697 | } | |
| 698 | ||
| 699 | fn testCeil(comptime T: type, x: T) void { | |
| 700 | const y = x - 0.8; | |
| 701 | const z = @ceil(y); | |
| 702 | expectEqual(x, z); | |
| 703 | } | |
| 704 | ||
| 705 | test "@trunc" { | |
| 706 | // FIXME: Generates a truncl function call | |
| 707 | //testTrunc(f128, 12.0); | |
| 708 | comptime testTrunc(f128, 12.0); | |
| 709 | testTrunc(f64, 12.0); | |
| 710 | comptime testTrunc(f64, 12.0); | |
| 711 | testTrunc(f32, 12.0); | |
| 712 | comptime testTrunc(f32, 12.0); | |
| 713 | testTrunc(f16, 12.0); | |
| 714 | comptime testTrunc(f16, 12.0); | |
| 715 | ||
| 716 | const x = 14.0; | |
| 717 | const y = x + 0.7; | |
| 718 | const z = @trunc(y); | |
| 719 | comptime expectEqual(x, z); | |
| 720 | } | |
| 721 | ||
| 722 | fn testTrunc(comptime T: type, x: T) void { | |
| 723 | { | |
| 724 | const y = x + 0.8; | |
| 725 | const z = @trunc(y); | |
| 726 | expectEqual(x, z); | |
| 727 | } | |
| 728 | ||
| 729 | { | |
| 730 | const y = -x - 0.8; | |
| 731 | const z = @trunc(y); | |
| 732 | expectEqual(-x, z); | |
| 733 | } | |
| 734 | } | |
| 735 | ||
| 736 | test "@round" { | |
| 737 | // FIXME: Generates a roundl function call | |
| 738 | //testRound(f128, 12.0); | |
| 739 | comptime testRound(f128, 12.0); | |
| 740 | testRound(f64, 12.0); | |
| 741 | comptime testRound(f64, 12.0); | |
| 742 | testRound(f32, 12.0); | |
| 743 | comptime testRound(f32, 12.0); | |
| 744 | testRound(f16, 12.0); | |
| 745 | comptime testRound(f16, 12.0); | |
| 746 | ||
| 747 | const x = 14.0; | |
| 748 | const y = x + 0.4; | |
| 749 | const z = @round(y); | |
| 750 | comptime expectEqual(x, z); | |
| 751 | } | |
| 752 | ||
| 753 | fn testRound(comptime T: type, x: T) void { | |
| 754 | const y = x - 0.5; | |
| 755 | const z = @round(y); | |
| 756 | expectEqual(x, z); | |
| 757 | } | |
| 758 | ||
| 637 | 759 | test "comptime_int param and return" { |
| 638 | 760 | const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702); |
| 639 | 761 | expect(a == 137114567242441932203689521744947848950); |