diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-12 13:25:44 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-12 13:25:44 +0100 |
| commit | 9643f32c998f92c882f0793f3956d51a923acfcb (patch) | |
| tree | 32c463e9268bd6dbb21d387f40880178a872dbd3 /lib/std | |
| parent | beb275b371cd50ee1d57528d2792f2f267e6013d (diff) | |
| parent | 16076964d6e7c8f17117614d5a7d83070d5b8902 (diff) | |
| download | zig-9643f32c998f92c882f0793f3956d51a923acfcb.tar.gz zig-9643f32c998f92c882f0793f3956d51a923acfcb.zip | |
Merge pull request #10861 from ziglang/f80
make f80 less hacky; lower as u80 on non-x86
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/math.zig | 43 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/addXf3.zig | 18 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/compareXf2.zig | 4 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/extend_f80.zig | 6 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/trunc_f80.zig | 6 |
5 files changed, 42 insertions, 35 deletions
diff --git a/lib/std/math.zig b/lib/std/math.zig index 6802d420fd..4b8bcf2287 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -36,28 +36,17 @@ pub const sqrt2 = 1.414213562373095048801688724209698079; /// 1/sqrt(2) pub const sqrt1_2 = 0.707106781186547524400844362104849039; -// From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128) pub const f128_true_min = @bitCast(f128, @as(u128, 0x00000000000000000000000000000001)); pub const f128_min = @bitCast(f128, @as(u128, 0x00010000000000000000000000000000)); pub const f128_max = @bitCast(f128, @as(u128, 0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); pub const f128_epsilon = @bitCast(f128, @as(u128, 0x3F8F0000000000000000000000000000)); pub const f128_toint = 1.0 / f128_epsilon; -pub const F80Repr = if (@import("builtin").cpu.arch.endian() == .Little) extern struct { - fraction: u64, - exp: u16, - _pad: u32 = undefined, -} else extern struct { - exp: u16, - _pad: u32 = undefined, // TODO verify compatibility with hardware - fraction: u64, -}; - // float.h details -pub const f80_true_min = @ptrCast(*const f80, &F80Repr{ .fraction = 1, .exp = 0 }).*; -pub const f80_min = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 1 }).*; -pub const f80_max = @ptrCast(*const f80, &F80Repr{ .fraction = 0xFFFFFFFFFFFFFFFF, .exp = 0x7FFE }).*; -pub const f80_epsilon = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 0x3FC0 }).*; +pub const f80_true_min = make_f80(.{ .fraction = 1, .exp = 0 }); +pub const f80_min = make_f80(.{ .fraction = 0x8000000000000000, .exp = 1 }); +pub const f80_max = make_f80(.{ .fraction = 0xFFFFFFFFFFFFFFFF, .exp = 0x7FFE }); +pub const f80_epsilon = make_f80(.{ .fraction = 0x8000000000000000, .exp = 0x3FC0 }); pub const f80_toint = 1.0 / f80_epsilon; pub const f64_true_min = 4.94065645841246544177e-324; @@ -107,9 +96,9 @@ pub const qnan_f64 = @bitCast(f64, qnan_u64); pub const inf_u64 = @as(u64, 0x7FF << 52); pub const inf_f64 = @bitCast(f64, inf_u64); -pub const inf_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 0x7fff }).*; -pub const nan_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0xA000000000000000, .exp = 0x7fff }).*; -pub const qnan_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0xC000000000000000, .exp = 0x7fff }).*; +pub const inf_f80 = make_f80(F80{ .fraction = 0x8000000000000000, .exp = 0x7fff }); +pub const nan_f80 = make_f80(F80{ .fraction = 0xA000000000000000, .exp = 0x7fff }); +pub const qnan_f80 = make_f80(F80{ .fraction = 0xC000000000000000, .exp = 0x7fff }); pub const nan_u128 = @as(u128, 0x7fff0000000000000000000000000001); pub const nan_f128 = @bitCast(f128, nan_u128); @@ -1504,3 +1493,21 @@ test "boolMask" { pub fn comptimeMod(num: anytype, denom: comptime_int) IntFittingRange(0, denom - 1) { return @intCast(IntFittingRange(0, denom - 1), @mod(num, denom)); } + +pub const F80 = struct { + fraction: u64, + exp: u16, +}; + +pub fn make_f80(repr: F80) f80 { + const int = (@as(u80, repr.exp) << 64) | repr.fraction; + return @bitCast(f80, int); +} + +pub fn break_f80(x: f80) F80 { + const int = @bitCast(u80, x); + return .{ + .fraction = @truncate(u64, int), + .exp = @truncate(u16, int >> 64), + }; +} diff --git a/lib/std/special/compiler_rt/addXf3.zig b/lib/std/special/compiler_rt/addXf3.zig index 1339cc340d..13758afce7 100644 --- a/lib/std/special/compiler_rt/addXf3.zig +++ b/lib/std/special/compiler_rt/addXf3.zig @@ -232,8 +232,8 @@ fn normalize_f80(exp: *i32, significand: *u80) void { } pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 { - var a_rep align(16) = @ptrCast(*const std.math.F80Repr, &a).*; - var b_rep align(16) = @ptrCast(*const std.math.F80Repr, &b).*; + var a_rep = std.math.break_f80(a); + var b_rep = std.math.break_f80(b); var a_exp: i32 = a_rep.exp & 0x7FFF; var b_exp: i32 = b_rep.exp & 0x7FFF; @@ -257,7 +257,7 @@ pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 { std.debug.assert(a_rep.fraction & significand_mask != 0); // NaN + anything = qNaN a_rep.fraction |= qnan_bit; - return @ptrCast(*const f80, &a_rep).*; + return std.math.make_f80(a_rep); } } if (b_exp == max_exp) { @@ -268,7 +268,7 @@ pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 { std.debug.assert(b_rep.fraction & significand_mask != 0); // anything + NaN = qNaN b_rep.fraction |= qnan_bit; - return @ptrCast(*const f80, &b_rep).*; + return std.math.make_f80(b_rep); } } @@ -279,7 +279,7 @@ pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 { if (b_zero) { // but we need to get the sign right for zero + zero a_rep.exp &= b_rep.exp; - return @ptrCast(*const f80, &a_rep).*; + return std.math.make_f80(a_rep); } else { return b; } @@ -359,7 +359,7 @@ pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 { if (a_exp >= max_exp) { a_rep.exp = max_exp | result_sign; a_rep.fraction = int_bit; // integer bit is set for +/-inf - return @ptrCast(*const f80, &a_rep).*; + return std.math.make_f80(a_rep); } if (a_exp <= 0) { @@ -387,13 +387,13 @@ pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 { a_rep.fraction = @truncate(u64, a_int); a_rep.exp = @truncate(u16, a_int >> significand_bits); - return @ptrCast(*const f80, &a_rep).*; + return std.math.make_f80(a_rep); } pub fn __subxf3(a: f80, b: f80) callconv(.C) f80 { - var b_rep align(16) = @ptrCast(*const std.math.F80Repr, &b).*; + var b_rep = std.math.break_f80(b); b_rep.exp ^= 0x8000; - return __addxf3(a, @ptrCast(*const f80, &b_rep).*); + return __addxf3(a, std.math.make_f80(b_rep)); } test { diff --git a/lib/std/special/compiler_rt/compareXf2.zig b/lib/std/special/compiler_rt/compareXf2.zig index 36f6f5f1c1..9640298f8f 100644 --- a/lib/std/special/compiler_rt/compareXf2.zig +++ b/lib/std/special/compiler_rt/compareXf2.zig @@ -147,8 +147,8 @@ pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 { // Comparison between f80 pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT { - const a_rep = @ptrCast(*const std.math.F80Repr, &a).*; - const b_rep = @ptrCast(*const std.math.F80Repr, &b).*; + const a_rep = std.math.break_f80(a); + const b_rep = std.math.break_f80(b); const sig_bits = std.math.floatMantissaBits(f80); const int_bit = 0x8000000000000000; const sign_bit = 0x8000; diff --git a/lib/std/special/compiler_rt/extend_f80.zig b/lib/std/special/compiler_rt/extend_f80.zig index 29ba8560ce..4686421db0 100644 --- a/lib/std/special/compiler_rt/extend_f80.zig +++ b/lib/std/special/compiler_rt/extend_f80.zig @@ -41,7 +41,7 @@ inline fn extendF80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(s const src_qnan = 1 << (src_sig_bits - 1); const src_nan_code = src_qnan - 1; - var dst: std.math.F80Repr align(16) = undefined; + var dst: std.math.F80 = undefined; // Break a into a sign and representation of the absolute value const a_abs = a & src_abs_mask; @@ -83,7 +83,7 @@ inline fn extendF80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(s } dst.exp |= sign; - return @ptrCast(*const f80, &dst).*; + return std.math.make_f80(dst); } pub fn __extendxftf2(a: f80) callconv(.C) f128 { @@ -99,7 +99,7 @@ pub fn __extendxftf2(a: f80) callconv(.C) f128 { const dst_min_normal = @as(u128, 1) << dst_sig_bits; // Break a into a sign and representation of the absolute value - var a_rep = @ptrCast(*const std.math.F80Repr, &a).*; + var a_rep = std.math.break_f80(a); const sign = a_rep.exp & 0x8000; a_rep.exp &= 0x7FFF; var abs_result: u128 = undefined; diff --git a/lib/std/special/compiler_rt/trunc_f80.zig b/lib/std/special/compiler_rt/trunc_f80.zig index 567d03be63..19e8d44b86 100644 --- a/lib/std/special/compiler_rt/trunc_f80.zig +++ b/lib/std/special/compiler_rt/trunc_f80.zig @@ -42,7 +42,7 @@ inline fn trunc(comptime dst_t: type, a: f80) dst_t { const dst_nan_mask = dst_qnan - 1; // Break a into a sign and representation of the absolute value - var a_rep = @ptrCast(*const std.math.F80Repr, &a).*; + var a_rep = std.math.break_f80(a); const sign = a_rep.exp & 0x8000; a_rep.exp &= 0x7FFF; a_rep.fraction &= 0x7FFFFFFFFFFFFFFF; @@ -125,7 +125,7 @@ pub fn __trunctfxf2(a: f128) callconv(.C) f80 { const a_abs = a_rep & src_abs_mask; const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0; - var res: std.math.F80Repr align(16) = undefined; + var res: std.math.F80 = undefined; if (a_abs > src_inf) { // a is NaN. @@ -155,5 +155,5 @@ pub fn __trunctfxf2(a: f128) callconv(.C) f80 { } res.exp |= sign; - return @ptrCast(*const f80, &res).*; + return std.math.make_f80(res); } |
