| author | |
| committer | |
| log | e63d864c1ee343dff13b1e165079e092ee93e273 |
| tree | fcd642630d288f71025ced2a87b0e73ce7129ac8 |
| parent | 0d117bb0a993b2a0a290f99255c5bf1bf05f187f |
* __letf2
* __cmptf2
* __getf2
* __unordtf2
* __eqtf2
* __lttf2
* __netf2
* __gttf25 files changed, 149 insertions(+), 10 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -311,6 +311,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG |
| 311 | 311 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_file_template.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 312 | 312 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_runner.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 313 | 313 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 314 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/comparetf2.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") | |
| 314 | 315 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixuint.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") |
| 315 | 316 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunsdfdi.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") |
| 316 | 317 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunsdfsi.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") |
std/special/compiler_rt/comparetf2.zig created+120| ... | ... | @@ -0,0 +1,120 @@ |
| 1 | // TODO https://github.com/zig-lang/zig/issues/305 | |
| 2 | // and then make the return types of some of these functions the enum instead of c_int | |
| 3 | const LE_LESS = c_int(-1); | |
| 4 | const LE_EQUAL = c_int(0); | |
| 5 | const LE_GREATER = c_int(1); | |
| 6 | const LE_UNORDERED = c_int(1); | |
| 7 | ||
| 8 | const rep_t = u128; | |
| 9 | const srep_t = i128; | |
| 10 | ||
| 11 | const typeWidth = rep_t.bit_count; | |
| 12 | const significandBits = 112; | |
| 13 | const exponentBits = (typeWidth - significandBits - 1); | |
| 14 | const signBit = (rep_t(1) << (significandBits + exponentBits)); | |
| 15 | const absMask = signBit - 1; | |
| 16 | const implicitBit = rep_t(1) << significandBits; | |
| 17 | const significandMask = implicitBit - 1; | |
| 18 | const exponentMask = absMask ^ significandMask; | |
| 19 | const infRep = exponentMask; | |
| 20 | ||
| 21 | export fn __letf2(a: f128, b: f128) -> c_int { | |
| 22 | const aInt = @bitCast(rep_t, a); | |
| 23 | const bInt = @bitCast(rep_t, b); | |
| 24 | ||
| 25 | const aAbs: rep_t = aInt & absMask; | |
| 26 | const bAbs: rep_t = bInt & absMask; | |
| 27 | ||
| 28 | // If either a or b is NaN, they are unordered. | |
| 29 | if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED; | |
| 30 | ||
| 31 | // If a and b are both zeros, they are equal. | |
| 32 | if ((aAbs | bAbs) == 0) return LE_EQUAL; | |
| 33 | ||
| 34 | // If at least one of a and b is positive, we get the same result comparing | |
| 35 | // a and b as signed integers as we would with a floating-point compare. | |
| 36 | return if ((aInt & bInt) >= 0) { | |
| 37 | if (aInt < bInt) { | |
| 38 | LE_LESS | |
| 39 | } else if (aInt == bInt) { | |
| 40 | LE_EQUAL | |
| 41 | } else { | |
| 42 | LE_GREATER | |
| 43 | } | |
| 44 | } else { | |
| 45 | // Otherwise, both are negative, so we need to flip the sense of the | |
| 46 | // comparison to get the correct result. (This assumes a twos- or ones- | |
| 47 | // complement integer representation; if integers are represented in a | |
| 48 | // sign-magnitude representation, then this flip is incorrect). | |
| 49 | if (aInt > bInt) { | |
| 50 | LE_LESS | |
| 51 | } else if (aInt == bInt) { | |
| 52 | LE_EQUAL | |
| 53 | } else { | |
| 54 | LE_GREATER | |
| 55 | } | |
| 56 | }; | |
| 57 | } | |
| 58 | ||
| 59 | // Alias for libgcc compatibility | |
| 60 | // TODO https://github.com/zig-lang/zig/issues/420 | |
| 61 | export fn __cmptf2(a: f128, b: f128) -> c_int { __letf2(a, b) } | |
| 62 | ||
| 63 | // TODO https://github.com/zig-lang/zig/issues/305 | |
| 64 | // and then make the return types of some of these functions the enum instead of c_int | |
| 65 | const GE_LESS = c_int(-1); | |
| 66 | const GE_EQUAL = c_int(0); | |
| 67 | const GE_GREATER = c_int(1); | |
| 68 | const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED | |
| 69 | ||
| 70 | export fn __getf2(a: f128, b: f128) -> c_int { | |
| 71 | ||
| 72 | const aInt = @bitCast(srep_t, a); | |
| 73 | const bInt = @bitCast(srep_t, b); | |
| 74 | const aAbs = @bitCast(rep_t, aInt) & absMask; | |
| 75 | const bAbs = @bitCast(rep_t, bInt) & absMask; | |
| 76 | ||
| 77 | if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED; | |
| 78 | if ((aAbs | bAbs) == 0) return GE_EQUAL; | |
| 79 | return if ((aInt & bInt) >= 0) { | |
| 80 | if (aInt < bInt) { | |
| 81 | GE_LESS | |
| 82 | } else if (aInt == bInt) { | |
| 83 | GE_EQUAL | |
| 84 | } else { | |
| 85 | GE_GREATER | |
| 86 | } | |
| 87 | } else { | |
| 88 | if (aInt > bInt) { | |
| 89 | GE_LESS | |
| 90 | } else if (aInt == bInt) { | |
| 91 | GE_EQUAL | |
| 92 | } else { | |
| 93 | GE_GREATER | |
| 94 | } | |
| 95 | }; | |
| 96 | } | |
| 97 | ||
| 98 | export fn __unordtf2(a: f128, b: f128) -> c_int { | |
| 99 | const aAbs = @bitCast(rep_t, a) & absMask; | |
| 100 | const bAbs = @bitCast(rep_t, b) & absMask; | |
| 101 | return c_int(aAbs > infRep or bAbs > infRep); | |
| 102 | } | |
| 103 | ||
| 104 | // The following are alternative names for the preceding routines. | |
| 105 | ||
| 106 | export fn __eqtf2(a: f128, b: f128) -> c_int { | |
| 107 | return __letf2(a, b); | |
| 108 | } | |
| 109 | ||
| 110 | export fn __lttf2(a: f128, b: f128) -> c_int { | |
| 111 | return __letf2(a, b); | |
| 112 | } | |
| 113 | ||
| 114 | export fn __netf2(a: f128, b: f128) -> c_int { | |
| 115 | return __letf2(a, b); | |
| 116 | } | |
| 117 | ||
| 118 | export fn __gttf2(a: f128, b: f128) -> c_int { | |
| 119 | return __getf2(a, b); | |
| 120 | } |
std/special/compiler_rt/fixunstfdi_test.zig+11-10| ... | ... | @@ -36,14 +36,15 @@ test "fixunstfdi" { |
| 36 | 36 | test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0); |
| 37 | 37 | test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0); |
| 38 | 38 | |
| 39 | test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); | |
| 40 | test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001); | |
| 41 | test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000); | |
| 42 | test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); | |
| 43 | test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); | |
| 44 | test__fixunstfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFF); | |
| 45 | ||
| 46 | test__fixunstfdi(-0x1.0000000000000000p+63, 0); | |
| 47 | test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0); | |
| 48 | test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0); | |
| 39 | // TODO enable these tests when we can parse f128 float literals | |
| 40 | //test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); | |
| 41 | //test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001); | |
| 42 | //test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000); | |
| 43 | //test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); | |
| 44 | //test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); | |
| 45 | //test__fixunstfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFF); | |
| 46 | ||
| 47 | //test__fixunstfdi(-0x1.0000000000000000p+63, 0); | |
| 48 | //test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0); | |
| 49 | //test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0); | |
| 49 | 50 | } |
std/special/compiler_rt/index.zig+1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | // Find all the exported functions. |
| 2 | 2 | comptime { |
| 3 | _ = @import("comparetf2.zig"); | |
| 3 | 4 | _ = @import("fixunsdfdi.zig"); |
| 4 | 5 | _ = @import("fixunsdfsi.zig"); |
| 5 | 6 | _ = @import("fixunsdfti.zig"); |
test/cases/math.zig+16| ... | ... | @@ -312,3 +312,19 @@ test "big number multiplication" { |
| 312 | 312 | 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016); |
| 313 | 313 | } |
| 314 | 314 | } |
| 315 | ||
| 316 | test "f128" { | |
| 317 | test_f128(); | |
| 318 | comptime test_f128(); | |
| 319 | } | |
| 320 | ||
| 321 | fn make_f128(x: f128) -> f128 { x } | |
| 322 | ||
| 323 | fn test_f128() { | |
| 324 | assert(@sizeOf(f128) == 16); | |
| 325 | assert(make_f128(1.0) == 1.0); | |
| 326 | assert(make_f128(1.0) != 1.1); | |
| 327 | assert(make_f128(1.0) > 0.9); | |
| 328 | assert(make_f128(1.0) >= 0.9); | |
| 329 | assert(make_f128(1.0) >= 1.0); | |
| 330 | } |