| author | |
| committer | |
| log | 61ebfe6603c8fef26008683f96b62dab2c502429 |
| tree | 397a5336e57495628c363c8ee1e87b5522d9aea9 |
| parent | c32b2e45efb0d0ced14c76d5221b2db636e40246 |
5 files changed, 121 insertions(+), 2 deletions(-)
std/special/compiler_rt/floatunditf.zig created+28| ... | @@ -0,0 +1,28 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const is_test = builtin.is_test; | ||
| 3 | const std = @import("../../index.zig"); | ||
| 4 | |||
| 5 | pub extern fn __floatunditf(a: u128) f128 { | ||
| 6 | @setRuntimeSafety(is_test); | ||
| 7 | |||
| 8 | if (a == 0) { | ||
| 9 | return 0; | ||
| 10 | } | ||
| 11 | |||
| 12 | const mantissa_bits = std.math.floatMantissaBits(f128); | ||
| 13 | const exponent_bits = std.math.floatExponentBits(f128); | ||
| 14 | const exponent_bias = (1 << (exponent_bits - 1)) - 1; | ||
| 15 | const implicit_bit = 1 << mantissa_bits; | ||
| 16 | |||
| 17 | const exp = (u128.bit_count - 1) - @clz(a); | ||
| 18 | const shift = mantissa_bits - @intCast(u7, exp); | ||
| 19 | |||
| 20 | var result: u128 = (a << shift) ^ implicit_bit; | ||
| 21 | result += (@intCast(u128, exp) + exponent_bias) << mantissa_bits; | ||
| 22 | |||
| 23 | return @bitCast(f128, result); | ||
| 24 | } | ||
| 25 | |||
| 26 | test "import floatunditf" { | ||
| 27 | _ = @import("floatunditf_test.zig"); | ||
| 28 | } | ||
std/special/compiler_rt/floatunditf_test.zig created+33| ... | @@ -0,0 +1,33 @@ | ||
| 1 | const __floatunditf = @import("floatunditf.zig").__floatunditf; | ||
| 2 | const assert = @import("std").debug.assert; | ||
| 3 | |||
| 4 | fn test__floatunditf(a: u128, expected_hi: u64, expected_lo: u64) void { | ||
| 5 | const x = __floatunditf(a); | ||
| 6 | |||
| 7 | const x_repr = @bitCast(u128, x); | ||
| 8 | const x_hi = @intCast(u64, x_repr >> 64); | ||
| 9 | const x_lo = @truncate(u64, x_repr); | ||
| 10 | |||
| 11 | if (x_hi == expected_hi and x_lo == expected_lo) { | ||
| 12 | return; | ||
| 13 | } | ||
| 14 | // nan repr | ||
| 15 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | ||
| 16 | if ((x_hi & 0x7fff000000000000) == 0x7fff000000000000 and ((x_hi & 0xffffffffffff) > 0 or x_lo > 0)) { | ||
| 17 | return; | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | @panic("__floatunditf test failure"); | ||
| 22 | } | ||
| 23 | |||
| 24 | test "floatunditf" { | ||
| 25 | test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); | ||
| 26 | test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); | ||
| 27 | test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0); | ||
| 28 | test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); | ||
| 29 | test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); | ||
| 30 | test__floatunditf(0x2, 0x4000000000000000, 0x0); | ||
| 31 | test__floatunditf(0x1, 0x3fff000000000000, 0x0); | ||
| 32 | test__floatunditf(0x0, 0x0, 0x0); | ||
| 33 | } | ||
std/special/compiler_rt/floatunsitf.zig created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const is_test = builtin.is_test; | ||
| 3 | const std = @import("../../index.zig"); | ||
| 4 | |||
| 5 | pub extern fn __floatunsitf(a: u64) f128 { | ||
| 6 | @setRuntimeSafety(is_test); | ||
| 7 | |||
| 8 | if (a == 0) { | ||
| 9 | return 0; | ||
| 10 | } | ||
| 11 | |||
| 12 | const mantissa_bits = std.math.floatMantissaBits(f128); | ||
| 13 | const exponent_bits = std.math.floatExponentBits(f128); | ||
| 14 | const exponent_bias = (1 << (exponent_bits - 1)) - 1; | ||
| 15 | const implicit_bit = 1 << mantissa_bits; | ||
| 16 | |||
| 17 | const exp = (u64.bit_count - 1) - @clz(a); | ||
| 18 | const shift = mantissa_bits - @intCast(u7, exp); | ||
| 19 | |||
| 20 | // TODO: @bitCast alignment error | ||
| 21 | var result align(16) = (@intCast(u128, a) << shift) ^ implicit_bit; | ||
| 22 | result += (@intCast(u128, exp) + exponent_bias) << mantissa_bits; | ||
| 23 | |||
| 24 | return @bitCast(f128, result); | ||
| 25 | } | ||
| 26 | |||
| 27 | test "import floatunsitf" { | ||
| 28 | _ = @import("floatunsitf_test.zig"); | ||
| 29 | } | ||
std/special/compiler_rt/floatunsitf_test.zig created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; | ||
| 2 | const assert = @import("std").debug.assert; | ||
| 3 | |||
| 4 | fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void { | ||
| 5 | const x = __floatunsitf(a); | ||
| 6 | |||
| 7 | const x_repr = @bitCast(u128, x); | ||
| 8 | const x_hi = @intCast(u64, x_repr >> 64); | ||
| 9 | const x_lo = @truncate(u64, x_repr); | ||
| 10 | |||
| 11 | if (x_hi == expected_hi and x_lo == expected_lo) { | ||
| 12 | return; | ||
| 13 | } | ||
| 14 | // nan repr | ||
| 15 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | ||
| 16 | if ((x_hi & 0x7fff000000000000) == 0x7fff000000000000 and ((x_hi & 0xffffffffffff) > 0 or x_lo > 0)) { | ||
| 17 | return; | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | @panic("__floatunsitf test failure"); | ||
| 22 | } | ||
| 23 | |||
| 24 | test "floatunsitf" { | ||
| 25 | test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0); | ||
| 26 | test__floatunsitf(0, 0x0, 0x0); | ||
| 27 | test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0); | ||
| 28 | test__floatunsitf(0x12345678, 0x401b234567800000, 0x0); | ||
| 29 | } | ||
std/special/compiler_rt/truncXfYf2.zig+2-2| ... | @@ -85,8 +85,8 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t | ... | @@ -85,8 +85,8 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t |
| 85 | // a underflows on conversion to the destination type or is an exact | 85 | // a underflows on conversion to the destination type or is an exact |
| 86 | // zero. The result may be a denormal or zero. Extract the exponent | 86 | // zero. The result may be a denormal or zero. Extract the exponent |
| 87 | // to get the shift amount for the denormalization. | 87 | // to get the shift amount for the denormalization. |
| 88 | const aExp = aAbs >> srcSigBits; | 88 | const aExp = @intCast(u32, aAbs >> srcSigBits); |
| 89 | const shift = srcExpBias - dstExpBias - aExp + 1; | 89 | const shift = @intCast(u32, srcExpBias - dstExpBias - aExp + 1); |
| 90 | 90 | ||
| 91 | const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal; | 91 | const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal; |
| 92 | 92 |