authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-20 16:41:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-20 16:41:08-07:00
logc8ded2f9c940be2d59f5e9dc7d66374b67afba63
tree2a9608fdf705567e3992020e8953b5e391e70b28
parent4cb5fed10ba2233a3b19c33b56585eb73da8b001

stage2: implement big int to float conversion


3 files changed, 39 insertions(+), 16 deletions(-)

src/value.zig+23-4
...@@ -1853,17 +1853,26 @@ pub const Value = extern union {...@@ -1853,17 +1853,26 @@ pub const Value = extern union {
1853 };1853 };
1854 }1854 }
18551855
1856 pub fn intToFloat(val: Value, allocator: *Allocator, dest_ty: Type, target: Target) !Value {1856 pub fn intToFloat(val: Value, arena: *Allocator, dest_ty: Type, target: Target) !Value {
1857 switch (val.tag()) {1857 switch (val.tag()) {
1858 .undef, .zero, .one => return val,1858 .undef, .zero, .one => return val,
1859 .the_only_possible_value => return Value.initTag(.zero), // for i0, u01859 .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
1860 .int_u64 => {1860 .int_u64 => {
1861 return intToFloatInner(val.castTag(.int_u64).?.data, allocator, dest_ty, target);1861 return intToFloatInner(val.castTag(.int_u64).?.data, arena, dest_ty, target);
1862 },1862 },
1863 .int_i64 => {1863 .int_i64 => {
1864 return intToFloatInner(val.castTag(.int_i64).?.data, allocator, dest_ty, target);1864 return intToFloatInner(val.castTag(.int_i64).?.data, arena, dest_ty, target);
1865 },
1866 .int_big_positive => {
1867 const limbs = val.castTag(.int_big_positive).?.data;
1868 const float = bigIntToFloat(limbs, true);
1869 return floatToValue(float, arena, dest_ty, target);
1870 },
1871 .int_big_negative => {
1872 const limbs = val.castTag(.int_big_negative).?.data;
1873 const float = bigIntToFloat(limbs, false);
1874 return floatToValue(float, arena, dest_ty, target);
1865 },1875 },
1866 .int_big_positive, .int_big_negative => @panic("big int to float"),
1867 else => unreachable,1876 else => unreachable,
1868 }1877 }
1869 }1878 }
...@@ -1878,6 +1887,16 @@ pub const Value = extern union {...@@ -1878,6 +1887,16 @@ pub const Value = extern union {
1878 }1887 }
1879 }1888 }
18801889
1890 fn floatToValue(float: f128, arena: *Allocator, dest_ty: Type, target: Target) !Value {
1891 switch (dest_ty.floatBits(target)) {
1892 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
1893 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
1894 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),
1895 128 => return Value.Tag.float_128.create(arena, float),
1896 else => unreachable,
1897 }
1898 }
1899
1881 /// Supports both floats and ints; handles undefined.1900 /// Supports both floats and ints; handles undefined.
1882 pub fn numberAddWrap(1901 pub fn numberAddWrap(
1883 lhs: Value,1902 lhs: Value,
test/behavior/eval.zig+16
...@@ -390,3 +390,19 @@ test "inline for with same type but different values" {...@@ -390,3 +390,19 @@ test "inline for with same type but different values" {
390 }390 }
391 try expect(res == 5);391 try expect(res == 5);
392}392}
393
394test "f32 at compile time is lossy" {
395 try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
396}
397
398test "f32 at compile time is lossy" {
399 try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
400}
401
402test "f64 at compile time is lossy" {
403 try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
404}
405
406test {
407 comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
408}
test/behavior/eval_stage1.zig-12
...@@ -114,22 +114,10 @@ test "float literal at compile time not lossy" {...@@ -114,22 +114,10 @@ test "float literal at compile time not lossy" {
114 try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);114 try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
115}115}
116116
117test "f32 at compile time is lossy" {
118 try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
119}
120
121test "f64 at compile time is lossy" {
122 try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
123}
124
125test "f128 at compile time is lossy" {117test "f128 at compile time is lossy" {
126 try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);118 try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
127}119}
128120
129test {
130 comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
131}
132
133pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {121pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
134 _ = field_name;122 _ = field_name;
135 return struct {123 return struct {