aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-20 16:41:08 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-20 16:41:08 -0700
commitc8ded2f9c940be2d59f5e9dc7d66374b67afba63 (patch)
tree2a9608fdf705567e3992020e8953b5e391e70b28
parent4cb5fed10ba2233a3b19c33b56585eb73da8b001 (diff)
downloadzig-c8ded2f9c940be2d59f5e9dc7d66374b67afba63.tar.gz
zig-c8ded2f9c940be2d59f5e9dc7d66374b67afba63.zip
stage2: implement big int to float conversion
-rw-r--r--src/value.zig27
-rw-r--r--test/behavior/eval.zig16
-rw-r--r--test/behavior/eval_stage1.zig12
3 files changed, 39 insertions, 16 deletions
diff --git a/src/value.zig b/src/value.zig
index fce5e8afb1..7c24cdab81 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1853,17 +1853,26 @@ pub const Value = extern union {
};
}
- pub fn intToFloat(val: Value, allocator: *Allocator, dest_ty: Type, target: Target) !Value {
+ pub fn intToFloat(val: Value, arena: *Allocator, dest_ty: Type, target: Target) !Value {
switch (val.tag()) {
.undef, .zero, .one => return val,
.the_only_possible_value => return Value.initTag(.zero), // for i0, u0
.int_u64 => {
- return intToFloatInner(val.castTag(.int_u64).?.data, allocator, dest_ty, target);
+ return intToFloatInner(val.castTag(.int_u64).?.data, arena, dest_ty, target);
},
.int_i64 => {
- return intToFloatInner(val.castTag(.int_i64).?.data, allocator, dest_ty, target);
+ return intToFloatInner(val.castTag(.int_i64).?.data, arena, dest_ty, target);
+ },
+ .int_big_positive => {
+ const limbs = val.castTag(.int_big_positive).?.data;
+ const float = bigIntToFloat(limbs, true);
+ return floatToValue(float, arena, dest_ty, target);
+ },
+ .int_big_negative => {
+ const limbs = val.castTag(.int_big_negative).?.data;
+ const float = bigIntToFloat(limbs, false);
+ return floatToValue(float, arena, dest_ty, target);
},
- .int_big_positive, .int_big_negative => @panic("big int to float"),
else => unreachable,
}
}
@@ -1878,6 +1887,16 @@ pub const Value = extern union {
}
}
+ fn floatToValue(float: f128, arena: *Allocator, dest_ty: Type, target: Target) !Value {
+ switch (dest_ty.floatBits(target)) {
+ 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
+ 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
+ 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),
+ 128 => return Value.Tag.float_128.create(arena, float),
+ else => unreachable,
+ }
+ }
+
/// Supports both floats and ints; handles undefined.
pub fn numberAddWrap(
lhs: Value,
diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig
index 950a2b6c10..3d603ff732 100644
--- a/test/behavior/eval.zig
+++ b/test/behavior/eval.zig
@@ -390,3 +390,19 @@ test "inline for with same type but different values" {
}
try expect(res == 5);
}
+
+test "f32 at compile time is lossy" {
+ try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
+}
+
+test "f32 at compile time is lossy" {
+ try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
+}
+
+test "f64 at compile time is lossy" {
+ try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
+}
+
+test {
+ comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
+}
diff --git a/test/behavior/eval_stage1.zig b/test/behavior/eval_stage1.zig
index c78d02c85e..2f9f33cfc5 100644
--- a/test/behavior/eval_stage1.zig
+++ b/test/behavior/eval_stage1.zig
@@ -114,22 +114,10 @@ test "float literal at compile time not lossy" {
try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
}
-test "f32 at compile time is lossy" {
- try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
-}
-
-test "f64 at compile time is lossy" {
- try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
-}
-
test "f128 at compile time is lossy" {
try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
}
-test {
- comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
-}
-
pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
_ = field_name;
return struct {