authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-06-28 20:40:11+12:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-06-30 21:58:59+12:00
logc32b2e45efb0d0ced14c76d5221b2db636e40246
tree29ce016f10da23d49d8b6735680c028f6ef95350
parent379950f81debb1e4df4e69511fbebd61911013b4

compiler_rt: Add floatuntisf


2 files changed, 131 insertions(+), 0 deletions(-)

std/special/compiler_rt/floatuntisf.zig created+59
...@@ -0,0 +1,59 @@
1const builtin = @import("builtin");
2const is_test = builtin.is_test;
3
4const FLT_MANT_DIG = 24;
5
6pub extern fn __floatuntisf(arg: u128) f32 {
7 @setRuntimeSafety(is_test);
8
9 if (arg == 0)
10 return 0.0;
11
12 var a = arg;
13 const N: u32 = @sizeOf(u128) * 8;
14 const sd = @bitCast(i32, N -% @clz(a)); // number of significant digits
15 var e: i32 = sd -% 1; // exponent
16 if (sd > FLT_MANT_DIG) {
17 // start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
18 // finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
19 // 12345678901234567890123456
20 // 1 = msb 1 bit
21 // P = bit FLT_MANT_DIG-1 bits to the right of 1
22 // Q = bit FLT_MANT_DIG bits to the right of 1
23 // R = "or" of all bits to the right of Q
24 switch (sd) {
25 FLT_MANT_DIG + 1 => {
26 a <<= 1;
27 },
28 FLT_MANT_DIG + 2 => {},
29 else => {
30 const shift_amt = @bitCast(i32, N +% (FLT_MANT_DIG + 2)) -% sd;
31 const shift_amt_u7 = @intCast(u7, shift_amt);
32 a = (a >> @intCast(u7, sd -% (FLT_MANT_DIG + 2))) |
33 @boolToInt((a & (u128(@maxValue(u128)) >> shift_amt_u7)) != 0);
34 },
35 }
36 // finish
37 a |= @boolToInt((a & 4) != 0); // Or P into R
38 a +%= 1; // round - this step may add a significant bit
39 a >>= 2; // dump Q and R
40 // a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits
41 if ((a & (u128(1) << FLT_MANT_DIG)) != 0) {
42 a >>= 1;
43 e +%= 1;
44 }
45 // a is now rounded to FLT_MANT_DIG bits
46 } else {
47 a <<= @intCast(u7, FLT_MANT_DIG -% sd);
48 // a is now rounded to FLT_MANT_DIG bits
49 }
50
51 const high = @bitCast(u32, (e +% 127) << 23); // exponent
52 const low = @truncate(u32, a) & 0x007fffff; // mantissa
53
54 return @bitCast(f32, high | low);
55}
56
57test "import floatuntisf" {
58 _ = @import("floatuntisf_test.zig");
59}
std/special/compiler_rt/floatuntisf_test.zig created+72
...@@ -0,0 +1,72 @@
1const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;
2const assert = @import("std").debug.assert;
3
4fn test__floatuntisf(a: u128, expected: f32) void {
5 const x = __floatuntisf(a);
6 assert(x == expected);
7}
8
9test "floatuntisf" {
10 test__floatuntisf(0, 0.0);
11
12 test__floatuntisf(1, 1.0);
13 test__floatuntisf(2, 2.0);
14 test__floatuntisf(20, 20.0);
15
16 test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
17 test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
18
19 test__floatuntisf(make_ti(0x8000008000000000, 0), 0x1.000001p+127);
20 test__floatuntisf(make_ti(0x8000000000000800, 0), 0x1.0p+127);
21 test__floatuntisf(make_ti(0x8000010000000000, 0), 0x1.000002p+127);
22
23 test__floatuntisf(make_ti(0x8000000000000000, 0), 0x1.000000p+127);
24
25 test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
26
27 test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
28 test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
29
30 test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
31
32 test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
33 test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
34 test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
35
36 test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);
37 test__floatuntisf(0xFFFFFFFFFFFFFFFF, 0x1p+64);
38
39 test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
40
41 test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
42 test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
43 test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
44 test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
45 test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
46
47 test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
48 test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
49 test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
50 test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
51 test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
52
53 test__floatuntisf(make_ti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76);
54 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76);
55 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76);
56 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76);
57 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76);
58 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76);
59 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76);
60 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76);
61 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76);
62 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76);
63 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76);
64 test__floatuntisf(make_ti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);
65}
66
67fn make_ti(high: u64, low: u64) u128 {
68 var result: u128 = high;
69 result <<= 64;
70 result |= low;
71 return result;
72}