authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-06-28 20:26:35+12:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-06-30 21:58:59+12:00
log379950f81debb1e4df4e69511fbebd61911013b4
tree0e9a7b4246cddcc46632b1fcf2cadc475cf987ff
parenta3ab4325fd05807c4a5b70aed3b515ce7ccd753f

compiler_rt: Add trunc f128 narrowing functions


2 files changed, 115 insertions(+), 39 deletions(-)

std/special/compiler_rt/truncXfYf2.zig+11-5
...@@ -4,7 +4,13 @@ pub extern fn __truncsfhf2(a: f32) u16 {...@@ -4,7 +4,13 @@ pub extern fn __truncsfhf2(a: f32) u16 {
4 return @bitCast(u16, truncXfYf2(f16, f32, a));4 return @bitCast(u16, truncXfYf2(f16, f32, a));
5}5}
66
7const CHAR_BIT = 8;7pub extern fn __trunctfsf2(a: f128) f32 {
8 return truncXfYf2(f32, f128, a);
9}
10
11pub extern fn __trunctfdf2(a: f128) f64 {
12 return truncXfYf2(f64, f128, a);
13}
814
9inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {15inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
10 const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);16 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...@@ -16,7 +22,7 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t
1622
17 // Various constants whose values follow from the type parameters.23 // Various constants whose values follow from the type parameters.
18 // Any reasonable optimizer will fold and propagate all of these.24 // Any reasonable optimizer will fold and propagate all of these.
19 const srcBits = @sizeOf(src_t) * CHAR_BIT;25 const srcBits = src_t.bit_count;
20 const srcExpBits = srcBits - srcSigBits - 1;26 const srcExpBits = srcBits - srcSigBits - 1;
21 const srcInfExp = (1 << srcExpBits) - 1;27 const srcInfExp = (1 << srcExpBits) - 1;
22 const srcExpBias = srcInfExp >> 1;28 const srcExpBias = srcInfExp >> 1;
...@@ -31,7 +37,7 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t...@@ -31,7 +37,7 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t
31 const srcQNaN = 1 << (srcSigBits - 1);37 const srcQNaN = 1 << (srcSigBits - 1);
32 const srcNaNCode = srcQNaN - 1;38 const srcNaNCode = srcQNaN - 1;
3339
34 const dstBits = @sizeOf(dst_t) * CHAR_BIT;40 const dstBits = dst_t.bit_count;
35 const dstExpBits = dstBits - dstSigBits - 1;41 const dstExpBits = dstBits - dstSigBits - 1;
36 const dstInfExp = (1 << dstExpBits) - 1;42 const dstInfExp = (1 << dstExpBits) - 1;
37 const dstExpBias = dstInfExp >> 1;43 const dstExpBias = dstInfExp >> 1;
...@@ -79,8 +85,8 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t...@@ -79,8 +85,8 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t
79 // a underflows on conversion to the destination type or is an exact85 // a underflows on conversion to the destination type or is an exact
80 // zero. The result may be a denormal or zero. Extract the exponent86 // zero. The result may be a denormal or zero. Extract the exponent
81 // to get the shift amount for the denormalization.87 // to get the shift amount for the denormalization.
82 const aExp: u32 = aAbs >> srcSigBits;88 const aExp = aAbs >> srcSigBits;
83 const shift: u32 = srcExpBias - dstExpBias - aExp + 1;89 const shift = srcExpBias - dstExpBias - aExp + 1;
8490
85 const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal;91 const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal;
8692
std/special/compiler_rt/truncXfYf2_test.zig+104-34
...@@ -11,54 +11,124 @@ fn test__truncsfhf2(a: u32, expected: u16) void {...@@ -11,54 +11,124 @@ fn test__truncsfhf2(a: u32, expected: u16) void {
11}11}
1212
13test "truncsfhf2" {13test "truncsfhf2" {
14 test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN14 test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN
15 test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN15 test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN
1616
17 test__truncsfhf2(0, 0); // 017 test__truncsfhf2(0, 0); // 0
18 test__truncsfhf2(0x80000000, 0x8000); // -018 test__truncsfhf2(0x80000000, 0x8000); // -0
1919
20 test__truncsfhf2(0x7f800000, 0x7c00); // inf20 test__truncsfhf2(0x7f800000, 0x7c00); // inf
21 test__truncsfhf2(0xff800000, 0xfc00); // -inf21 test__truncsfhf2(0xff800000, 0xfc00); // -inf
2222
23 test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf23 test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf
24 test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf24 test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf
2525
26 test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf26 test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf
27 test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf27 test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf
2828
29 test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-1429 test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14
30 test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-1430 test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14
3131
32 test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 6550432 test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504
33 test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -6550433 test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504
3434
35 test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 6550435 test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504
36 test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -6550436 test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504
3737
38 test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 6550438 test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504
39 test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -6550439 test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504
4040
41 test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-1041 test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10
42 test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-1042 test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10
4343
44 test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/344 test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3
45 test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/345 test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3
4646
47 test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.141592653547 test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535
48 test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.141592653548 test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535
4949
50 test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+1250 test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12
5151
52 test__truncsfhf2(0x3f800000, 0x3c00); // normal, 152 test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1
53 test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-1453 test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14
5454
55 test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-2455 test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24
56 test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-2456 test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24
5757
58 test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-2458 test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24
59 test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-2459 test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24
6060
61 test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-2061 test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20
62 test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-2462 test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24
63 test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero63 test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
64}
65
66const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
67
68fn test__trunctfsf2(a: f128, expected: u32) void {
69 const x = __trunctfsf2(a);
70
71 const rep = @bitCast(u32, x);
72 if (rep == expected) {
73 return;
74 }
75 // test other possible NaN representation(signal NaN)
76 else if (expected == 0x7fc00000) {
77 if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) {
78 return;
79 }
80 }
81
82 @panic("__trunctfsf2 test failure");
83}
84
85test "trunctfsf2" {
86 // qnan
87 test__trunctfsf2(@bitCast(f128, u128(0x7fff800000000000 << 64)), 0x7fc00000);
88 // nan
89 test__trunctfsf2(@bitCast(f128, u128((0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000);
90 // inf
91 test__trunctfsf2(@bitCast(f128, u128(0x7fff000000000000 << 64)), 0x7f800000);
92 // zero
93 test__trunctfsf2(0.0, 0x0);
94
95 test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);
96 test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);
97 test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);
98 test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);
99}
100
101const __trunctfdf2 = @import("truncXfYf2.zig").__trunctfdf2;
102
103fn test__trunctfdf2(a: f128, expected: u64) void {
104 const x = __trunctfdf2(a);
105
106 const rep = @bitCast(u64, x);
107 if (rep == expected) {
108 return;
109 }
110 // test other possible NaN representation(signal NaN)
111 else if (expected == 0x7ff8000000000000) {
112 if ((rep & 0x7ff0000000000000) == 0x7ff0000000000000 and (rep & 0xfffffffffffff) > 0) {
113 return;
114 }
115 }
116
117 @panic("__trunctfsf2 test failure");
118}
119
120test "trunctfdf2" {
121 // qnan
122 test__trunctfdf2(@bitCast(f128, u128(0x7fff800000000000 << 64)), 0x7ff8000000000000);
123 // nan
124 test__trunctfdf2(@bitCast(f128, u128((0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000);
125 // inf
126 test__trunctfdf2(@bitCast(f128, u128(0x7fff000000000000 << 64)), 0x7ff0000000000000);
127 // zero
128 test__trunctfdf2(0.0, 0x0);
129
130 test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb);
131 test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7);
132 test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
133 test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
64}134}