| author | |
| committer | |
| log | e3a63b4e5abd501d58a2fc574b827f3250c14461 |
| tree | 114c2e109f4ca83e2867af9bcab375430a8d433d |
| parent | d3d77138ecd692a045c478d804d188b3d88c14d5 |
3 files changed, 144 insertions(+), 0 deletions(-)
lib/std/special/compiler_rt.zig+5| ... | @@ -75,6 +75,9 @@ comptime { | ... | @@ -75,6 +75,9 @@ comptime { |
| 75 | @export("__floatsisf", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage); | 75 | @export("__floatsisf", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage); |
| 76 | @export("__floatdidf", @import("compiler_rt/floatdidf.zig").__floatdidf, linkage); | 76 | @export("__floatdidf", @import("compiler_rt/floatdidf.zig").__floatdidf, linkage); |
| 77 | @export("__floatsitf", @import("compiler_rt/floatsiXf.zig").__floatsitf, linkage); | 77 | @export("__floatsitf", @import("compiler_rt/floatsiXf.zig").__floatsitf, linkage); |
| 78 | |||
| 79 | @export("__floatunsisf", @import("compiler_rt/floatunsisf.zig").__floatunsisf, linkage); | ||
| 80 | @export("__floatundisf", @import("compiler_rt/floatundisf.zig").__floatundisf, linkage); | ||
| 78 | @export("__floatunsidf", @import("compiler_rt/floatunsidf.zig").__floatunsidf, linkage); | 81 | @export("__floatunsidf", @import("compiler_rt/floatunsidf.zig").__floatunsidf, linkage); |
| 79 | @export("__floatundidf", @import("compiler_rt/floatundidf.zig").__floatundidf, linkage); | 82 | @export("__floatundidf", @import("compiler_rt/floatundidf.zig").__floatundidf, linkage); |
| 80 | 83 | ||
| ... | @@ -183,6 +186,8 @@ comptime { | ... | @@ -183,6 +186,8 @@ comptime { |
| 183 | @export("__aeabi_l2d", @import("compiler_rt/floatdidf.zig").__floatdidf, linkage); | 186 | @export("__aeabi_l2d", @import("compiler_rt/floatdidf.zig").__floatdidf, linkage); |
| 184 | @export("__aeabi_ui2d", @import("compiler_rt/floatunsidf.zig").__floatunsidf, linkage); | 187 | @export("__aeabi_ui2d", @import("compiler_rt/floatunsidf.zig").__floatunsidf, linkage); |
| 185 | @export("__aeabi_ul2d", @import("compiler_rt/floatundidf.zig").__floatundidf, linkage); | 188 | @export("__aeabi_ul2d", @import("compiler_rt/floatundidf.zig").__floatundidf, linkage); |
| 189 | @export("__aeabi_ui2f", @import("compiler_rt/floatunsisf.zig").__floatunsisf, linkage); | ||
| 190 | @export("__aeabi_ul2f", @import("compiler_rt/floatundisf.zig").__floatundisf, linkage); | ||
| 186 | 191 | ||
| 187 | @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage); | 192 | @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage); |
| 188 | @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage); | 193 | @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage); |
lib/std/special/compiler_rt/floatundisf.zig created+86| ... | @@ -0,0 +1,86 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const maxInt = std.math.maxInt; | ||
| 4 | |||
| 5 | const FLT_MANT_DIG = 24; | ||
| 6 | |||
| 7 | pub extern fn __floatundisf(arg: u64) f32 { | ||
| 8 | @setRuntimeSafety(builtin.is_test); | ||
| 9 | |||
| 10 | if (arg == 0) return 0; | ||
| 11 | |||
| 12 | var a = arg; | ||
| 13 | const N: usize = @TypeOf(a).bit_count; | ||
| 14 | // Number of significant digits | ||
| 15 | const sd = N - @clz(u64, a); | ||
| 16 | // 8 exponent | ||
| 17 | var e = @intCast(u32, sd) - 1; | ||
| 18 | |||
| 19 | if (sd > FLT_MANT_DIG) { | ||
| 20 | // start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx | ||
| 21 | // finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR | ||
| 22 | // 12345678901234567890123456 | ||
| 23 | // 1 = msb 1 bit | ||
| 24 | // P = bit FLT_MANT_DIG-1 bits to the right of 1 | ||
| 25 | // Q = bit FLT_MANT_DIG bits to the right of 1 | ||
| 26 | // R = "or" of all bits to the right of Q | ||
| 27 | switch (sd) { | ||
| 28 | FLT_MANT_DIG + 1 => a <<= 1, | ||
| 29 | FLT_MANT_DIG + 2 => {}, | ||
| 30 | else => { | ||
| 31 | const shift_amt = @intCast(u6, ((N + FLT_MANT_DIG + 2) - sd)); | ||
| 32 | const all_ones: u64 = maxInt(u64); | ||
| 33 | a = (a >> @intCast(u6, sd - (FLT_MANT_DIG + 2))) | | ||
| 34 | @boolToInt(a & (all_ones >> shift_amt) != 0); | ||
| 35 | }, | ||
| 36 | } | ||
| 37 | // Or P into R | ||
| 38 | a |= @boolToInt((a & 4) != 0); | ||
| 39 | // round - this step may add a significant bit | ||
| 40 | a += 1; | ||
| 41 | // dump Q and R | ||
| 42 | a >>= 2; | ||
| 43 | // a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits | ||
| 44 | if ((a & (@as(u64, 1) << FLT_MANT_DIG)) != 0) { | ||
| 45 | a >>= 1; | ||
| 46 | e += 1; | ||
| 47 | } | ||
| 48 | // a is now rounded to FLT_MANT_DIG bits | ||
| 49 | } else { | ||
| 50 | a <<= @intCast(u6, FLT_MANT_DIG - sd); | ||
| 51 | // a is now rounded to FLT_MANT_DIG bits | ||
| 52 | } | ||
| 53 | |||
| 54 | const result: u32 = ((e + 127) << 23) | // exponent | ||
| 55 | @truncate(u32, a & 0x007FFFFF); // mantissa | ||
| 56 | return @bitCast(f32, result); | ||
| 57 | } | ||
| 58 | |||
| 59 | fn test__floatundisf(a: u64, expected: f32) void { | ||
| 60 | std.testing.expectEqual(expected, __floatundisf(a)); | ||
| 61 | } | ||
| 62 | |||
| 63 | test "floatundisf" { | ||
| 64 | test__floatundisf(0, 0.0); | ||
| 65 | test__floatundisf(1, 1.0); | ||
| 66 | test__floatundisf(2, 2.0); | ||
| 67 | test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62F); | ||
| 68 | test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62F); | ||
| 69 | test__floatundisf(0x8000008000000000, 0x1p+63F); | ||
| 70 | test__floatundisf(0x8000010000000000, 0x1.000002p+63F); | ||
| 71 | test__floatundisf(0x8000000000000000, 0x1p+63F); | ||
| 72 | test__floatundisf(0x8000000000000001, 0x1p+63F); | ||
| 73 | test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64F); | ||
| 74 | test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64F); | ||
| 75 | test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50F); | ||
| 76 | test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50F); | ||
| 77 | test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50F); | ||
| 78 | test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50F); | ||
| 79 | test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50F); | ||
| 80 | test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50F); | ||
| 81 | test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50F); | ||
| 82 | test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50F); | ||
| 83 | test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50F); | ||
| 84 | test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50F); | ||
| 85 | test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50F); | ||
| 86 | } | ||
lib/std/special/compiler_rt/floatunsisf.zig created+53| ... | @@ -0,0 +1,53 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const maxInt = std.math.maxInt; | ||
| 4 | |||
| 5 | const significandBits = 23; | ||
| 6 | const exponentBias = 127; | ||
| 7 | const implicitBit = @as(u32, 1) << significandBits; | ||
| 8 | |||
| 9 | pub extern fn __floatunsisf(arg: u32) f32 { | ||
| 10 | @setRuntimeSafety(builtin.is_test); | ||
| 11 | |||
| 12 | if (arg == 0) return 0.0; | ||
| 13 | |||
| 14 | // The exponent is the width of abs(a) | ||
| 15 | const exp = @as(u32, 31) - @clz(u32, arg); | ||
| 16 | |||
| 17 | var mantissa: u32 = undefined; | ||
| 18 | if (exp <= significandBits) { | ||
| 19 | // Shift a into the significand field and clear the implicit bit | ||
| 20 | const shift = @intCast(u5, significandBits - exp); | ||
| 21 | mantissa = @as(u32, arg) << shift ^ implicitBit; | ||
| 22 | } else { | ||
| 23 | const shift = @intCast(u5, exp - significandBits); | ||
| 24 | // Round to the nearest number after truncation | ||
| 25 | mantissa = @as(u32, arg) >> shift ^ implicitBit; | ||
| 26 | // Align to the left and check if the truncated part is halfway over | ||
| 27 | const round = arg << @intCast(u5, 31 - shift); | ||
| 28 | mantissa += @boolToInt(round > 0x80000000); | ||
| 29 | // Tie to even | ||
| 30 | mantissa += mantissa & 1; | ||
| 31 | } | ||
| 32 | |||
| 33 | // Use the addition instead of a or since we may have a carry from the | ||
| 34 | // mantissa to the exponent | ||
| 35 | var result = mantissa; | ||
| 36 | result += (exp + exponentBias) << significandBits; | ||
| 37 | |||
| 38 | return @bitCast(f32, result); | ||
| 39 | } | ||
| 40 | |||
| 41 | fn test_one_floatunsisf(a: u32, expected: u32) void { | ||
| 42 | const r = __floatunsisf(a); | ||
| 43 | std.testing.expect(@bitCast(u32, r) == expected); | ||
| 44 | } | ||
| 45 | |||
| 46 | test "floatunsisf" { | ||
| 47 | // Test the produced bit pattern | ||
| 48 | test_one_floatunsisf(0, 0); | ||
| 49 | test_one_floatunsisf(1, 0x3f800000); | ||
| 50 | test_one_floatunsisf(0x7FFFFFFF, 0x4f000000); | ||
| 51 | test_one_floatunsisf(0x80000000, 0x4f000000); | ||
| 52 | test_one_floatunsisf(0xFFFFFFFF, 0x4f800000); | ||
| 53 | } | ||