mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
compiler_rt: Add floatunditf and floatunsitf
This commit is contained in:
parent
c32b2e45ef
commit
61ebfe6603
28
std/special/compiler_rt/floatunditf.zig
Normal file
28
std/special/compiler_rt/floatunditf.zig
Normal file
@ -0,0 +1,28 @@
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
const std = @import("../../index.zig");
|
||||
|
||||
pub extern fn __floatunditf(a: u128) f128 {
|
||||
@setRuntimeSafety(is_test);
|
||||
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const mantissa_bits = std.math.floatMantissaBits(f128);
|
||||
const exponent_bits = std.math.floatExponentBits(f128);
|
||||
const exponent_bias = (1 << (exponent_bits - 1)) - 1;
|
||||
const implicit_bit = 1 << mantissa_bits;
|
||||
|
||||
const exp = (u128.bit_count - 1) - @clz(a);
|
||||
const shift = mantissa_bits - @intCast(u7, exp);
|
||||
|
||||
var result: u128 = (a << shift) ^ implicit_bit;
|
||||
result += (@intCast(u128, exp) + exponent_bias) << mantissa_bits;
|
||||
|
||||
return @bitCast(f128, result);
|
||||
}
|
||||
|
||||
test "import floatunditf" {
|
||||
_ = @import("floatunditf_test.zig");
|
||||
}
|
||||
33
std/special/compiler_rt/floatunditf_test.zig
Normal file
33
std/special/compiler_rt/floatunditf_test.zig
Normal file
@ -0,0 +1,33 @@
|
||||
const __floatunditf = @import("floatunditf.zig").__floatunditf;
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
fn test__floatunditf(a: u128, expected_hi: u64, expected_lo: u64) void {
|
||||
const x = __floatunditf(a);
|
||||
|
||||
const x_repr = @bitCast(u128, x);
|
||||
const x_hi = @intCast(u64, x_repr >> 64);
|
||||
const x_lo = @truncate(u64, x_repr);
|
||||
|
||||
if (x_hi == expected_hi and x_lo == expected_lo) {
|
||||
return;
|
||||
}
|
||||
// nan repr
|
||||
else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
|
||||
if ((x_hi & 0x7fff000000000000) == 0x7fff000000000000 and ((x_hi & 0xffffffffffff) > 0 or x_lo > 0)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@panic("__floatunditf test failure");
|
||||
}
|
||||
|
||||
test "floatunditf" {
|
||||
test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000);
|
||||
test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000);
|
||||
test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0);
|
||||
test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000);
|
||||
test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000);
|
||||
test__floatunditf(0x2, 0x4000000000000000, 0x0);
|
||||
test__floatunditf(0x1, 0x3fff000000000000, 0x0);
|
||||
test__floatunditf(0x0, 0x0, 0x0);
|
||||
}
|
||||
29
std/special/compiler_rt/floatunsitf.zig
Normal file
29
std/special/compiler_rt/floatunsitf.zig
Normal file
@ -0,0 +1,29 @@
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
const std = @import("../../index.zig");
|
||||
|
||||
pub extern fn __floatunsitf(a: u64) f128 {
|
||||
@setRuntimeSafety(is_test);
|
||||
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const mantissa_bits = std.math.floatMantissaBits(f128);
|
||||
const exponent_bits = std.math.floatExponentBits(f128);
|
||||
const exponent_bias = (1 << (exponent_bits - 1)) - 1;
|
||||
const implicit_bit = 1 << mantissa_bits;
|
||||
|
||||
const exp = (u64.bit_count - 1) - @clz(a);
|
||||
const shift = mantissa_bits - @intCast(u7, exp);
|
||||
|
||||
// TODO: @bitCast alignment error
|
||||
var result align(16) = (@intCast(u128, a) << shift) ^ implicit_bit;
|
||||
result += (@intCast(u128, exp) + exponent_bias) << mantissa_bits;
|
||||
|
||||
return @bitCast(f128, result);
|
||||
}
|
||||
|
||||
test "import floatunsitf" {
|
||||
_ = @import("floatunsitf_test.zig");
|
||||
}
|
||||
29
std/special/compiler_rt/floatunsitf_test.zig
Normal file
29
std/special/compiler_rt/floatunsitf_test.zig
Normal file
@ -0,0 +1,29 @@
|
||||
const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void {
|
||||
const x = __floatunsitf(a);
|
||||
|
||||
const x_repr = @bitCast(u128, x);
|
||||
const x_hi = @intCast(u64, x_repr >> 64);
|
||||
const x_lo = @truncate(u64, x_repr);
|
||||
|
||||
if (x_hi == expected_hi and x_lo == expected_lo) {
|
||||
return;
|
||||
}
|
||||
// nan repr
|
||||
else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
|
||||
if ((x_hi & 0x7fff000000000000) == 0x7fff000000000000 and ((x_hi & 0xffffffffffff) > 0 or x_lo > 0)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@panic("__floatunsitf test failure");
|
||||
}
|
||||
|
||||
test "floatunsitf" {
|
||||
test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0);
|
||||
test__floatunsitf(0, 0x0, 0x0);
|
||||
test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0);
|
||||
test__floatunsitf(0x12345678, 0x401b234567800000, 0x0);
|
||||
}
|
||||
@ -85,8 +85,8 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t
|
||||
// a underflows on conversion to the destination type or is an exact
|
||||
// zero. The result may be a denormal or zero. Extract the exponent
|
||||
// to get the shift amount for the denormalization.
|
||||
const aExp = aAbs >> srcSigBits;
|
||||
const shift = srcExpBias - dstExpBias - aExp + 1;
|
||||
const aExp = @intCast(u32, aAbs >> srcSigBits);
|
||||
const shift = @intCast(u32, srcExpBias - dstExpBias - aExp + 1);
|
||||
|
||||
const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user