compiler_rt: Add trunc f128 narrowing functions
parent
a3ab4325fd
commit
379950f81d
|
@ -4,7 +4,13 @@ pub extern fn __truncsfhf2(a: f32) u16 {
|
|||
return @bitCast(u16, truncXfYf2(f16, f32, a));
|
||||
}
|
||||
|
||||
const CHAR_BIT = 8;
|
||||
pub extern fn __trunctfsf2(a: f128) f32 {
|
||||
return truncXfYf2(f32, f128, a);
|
||||
}
|
||||
|
||||
pub extern fn __trunctfdf2(a: f128) f64 {
|
||||
return truncXfYf2(f64, f128, a);
|
||||
}
|
||||
|
||||
inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
|
||||
const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);
|
||||
|
@ -16,7 +22,7 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t
|
|||
|
||||
// Various constants whose values follow from the type parameters.
|
||||
// Any reasonable optimizer will fold and propagate all of these.
|
||||
const srcBits = @sizeOf(src_t) * CHAR_BIT;
|
||||
const srcBits = src_t.bit_count;
|
||||
const srcExpBits = srcBits - srcSigBits - 1;
|
||||
const srcInfExp = (1 << srcExpBits) - 1;
|
||||
const srcExpBias = srcInfExp >> 1;
|
||||
|
@ -31,7 +37,7 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t
|
|||
const srcQNaN = 1 << (srcSigBits - 1);
|
||||
const srcNaNCode = srcQNaN - 1;
|
||||
|
||||
const dstBits = @sizeOf(dst_t) * CHAR_BIT;
|
||||
const dstBits = dst_t.bit_count;
|
||||
const dstExpBits = dstBits - dstSigBits - 1;
|
||||
const dstInfExp = (1 << dstExpBits) - 1;
|
||||
const dstExpBias = dstInfExp >> 1;
|
||||
|
@ -79,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: u32 = aAbs >> srcSigBits;
|
||||
const shift: u32 = srcExpBias - dstExpBias - aExp + 1;
|
||||
const aExp = aAbs >> srcSigBits;
|
||||
const shift = srcExpBias - dstExpBias - aExp + 1;
|
||||
|
||||
const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal;
|
||||
|
||||
|
|
|
@ -62,3 +62,73 @@ test "truncsfhf2" {
|
|||
test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24
|
||||
test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
|
||||
}
|
||||
|
||||
const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
|
||||
|
||||
fn test__trunctfsf2(a: f128, expected: u32) void {
|
||||
const x = __trunctfsf2(a);
|
||||
|
||||
const rep = @bitCast(u32, x);
|
||||
if (rep == expected) {
|
||||
return;
|
||||
}
|
||||
// test other possible NaN representation(signal NaN)
|
||||
else if (expected == 0x7fc00000) {
|
||||
if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@panic("__trunctfsf2 test failure");
|
||||
}
|
||||
|
||||
test "trunctfsf2" {
|
||||
// qnan
|
||||
test__trunctfsf2(@bitCast(f128, u128(0x7fff800000000000 << 64)), 0x7fc00000);
|
||||
// nan
|
||||
test__trunctfsf2(@bitCast(f128, u128((0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000);
|
||||
// inf
|
||||
test__trunctfsf2(@bitCast(f128, u128(0x7fff000000000000 << 64)), 0x7f800000);
|
||||
// zero
|
||||
test__trunctfsf2(0.0, 0x0);
|
||||
|
||||
test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);
|
||||
test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);
|
||||
test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);
|
||||
test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);
|
||||
}
|
||||
|
||||
const __trunctfdf2 = @import("truncXfYf2.zig").__trunctfdf2;
|
||||
|
||||
fn test__trunctfdf2(a: f128, expected: u64) void {
|
||||
const x = __trunctfdf2(a);
|
||||
|
||||
const rep = @bitCast(u64, x);
|
||||
if (rep == expected) {
|
||||
return;
|
||||
}
|
||||
// test other possible NaN representation(signal NaN)
|
||||
else if (expected == 0x7ff8000000000000) {
|
||||
if ((rep & 0x7ff0000000000000) == 0x7ff0000000000000 and (rep & 0xfffffffffffff) > 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@panic("__trunctfsf2 test failure");
|
||||
}
|
||||
|
||||
test "trunctfdf2" {
|
||||
// qnan
|
||||
test__trunctfdf2(@bitCast(f128, u128(0x7fff800000000000 << 64)), 0x7ff8000000000000);
|
||||
// nan
|
||||
test__trunctfdf2(@bitCast(f128, u128((0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000);
|
||||
// inf
|
||||
test__trunctfdf2(@bitCast(f128, u128(0x7fff000000000000 << 64)), 0x7ff0000000000000);
|
||||
// zero
|
||||
test__trunctfdf2(0.0, 0x0);
|
||||
|
||||
test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb);
|
||||
test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7);
|
||||
test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
|
||||
test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue