aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-02-12 13:25:44 +0100
committerGitHub <noreply@github.com>2022-02-12 13:25:44 +0100
commit9643f32c998f92c882f0793f3956d51a923acfcb (patch)
tree32c463e9268bd6dbb21d387f40880178a872dbd3 /lib/std
parentbeb275b371cd50ee1d57528d2792f2f267e6013d (diff)
parent16076964d6e7c8f17117614d5a7d83070d5b8902 (diff)
downloadzig-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.zig43
-rw-r--r--lib/std/special/compiler_rt/addXf3.zig18
-rw-r--r--lib/std/special/compiler_rt/compareXf2.zig4
-rw-r--r--lib/std/special/compiler_rt/extend_f80.zig6
-rw-r--r--lib/std/special/compiler_rt/trunc_f80.zig6
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);
}