| ... | ... | @@ -563,15 +563,15 @@ pub const Value = extern union { |
| 563 | 563 | } |
| 564 | 564 | |
| 565 | 565 | /// Asserts that the value is a float or an integer. |
| 566 | | pub fn toF128(self: Value) f128 { |
| 566 | pub fn toFloat(self: Value, comptime T: type) T { |
| 567 | 567 | return switch (self.tag()) { |
| 568 | 568 | .float_16 => @panic("TODO soft float"), |
| 569 | | .float_32 => self.cast(Payload.Float_32).?.val, |
| 570 | | .float_64 => self.cast(Payload.Float_64).?.val, |
| 571 | | .float_128 => self.cast(Payload.Float_128).?.val, |
| 569 | .float_32 => @floatCast(T, self.cast(Payload.Float_32).?.val), |
| 570 | .float_64 => @floatCast(T, self.cast(Payload.Float_64).?.val), |
| 571 | .float_128 => @floatCast(T, self.cast(Payload.Float_128).?.val), |
| 572 | 572 | |
| 573 | 573 | .zero, .the_one_possible_value => 0, |
| 574 | | .int_u64 => @intToFloat(f128, self.cast(Payload.Int_u64).?.int), |
| 574 | .int_u64 => @intToFloat(T, self.cast(Payload.Int_u64).?.int), |
| 575 | 575 | // .int_i64 => @intToFloat(f128, self.cast(Payload.Int_i64).?.int), |
| 576 | 576 | .int_i64 => @panic("TODO lld: error: undefined symbol: __floatditf"), |
| 577 | 577 | |
| ... | ... | @@ -773,6 +773,50 @@ pub const Value = extern union { |
| 773 | 773 | } |
| 774 | 774 | } |
| 775 | 775 | |
| 776 | /// Converts an integer or a float to a float. |
| 777 | /// Returns `error.Overflow` if the value does not fit in the new type. |
| 778 | pub fn floatCast(self: Value, allocator: *Allocator, ty: Type, target: Target) !Value { |
| 779 | const dest_bit_count = switch (ty.tag()) { |
| 780 | .comptime_float => 128, |
| 781 | else => ty.floatBits(target), |
| 782 | }; |
| 783 | switch (dest_bit_count) { |
| 784 | 16, 32, 64, 128 => {}, |
| 785 | else => std.debug.panic("TODO float cast bit count {}\n", .{dest_bit_count}), |
| 786 | } |
| 787 | if (ty.isInt()) { |
| 788 | @panic("TODO int to float"); |
| 789 | } |
| 790 | |
| 791 | switch (dest_bit_count) { |
| 792 | 16 => { |
| 793 | @panic("TODO soft float"); |
| 794 | // var res_payload = Value.Payload.Float_16{.val = self.toFloat(f16)}; |
| 795 | // if (!self.eql(Value.initPayload(&res_payload.base))) |
| 796 | // return error.Overflow; |
| 797 | // return Value.initPayload(&res_payload.base).copy(allocator); |
| 798 | }, |
| 799 | 32 => { |
| 800 | var res_payload = Value.Payload.Float_32{.val = self.toFloat(f32)}; |
| 801 | if (!self.eql(Value.initPayload(&res_payload.base))) |
| 802 | return error.Overflow; |
| 803 | return Value.initPayload(&res_payload.base).copy(allocator); |
| 804 | }, |
| 805 | 64 => { |
| 806 | var res_payload = Value.Payload.Float_64{.val = self.toFloat(f64)}; |
| 807 | if (!self.eql(Value.initPayload(&res_payload.base))) |
| 808 | return error.Overflow; |
| 809 | return Value.initPayload(&res_payload.base).copy(allocator); |
| 810 | }, |
| 811 | 128 => { |
| 812 | const float_payload = try allocator.create(Value.Payload.Float_128); |
| 813 | float_payload.* = .{ .val = self.toFloat(f128) }; |
| 814 | return Value.initPayload(&float_payload.base); |
| 815 | }, |
| 816 | else => unreachable, |
| 817 | } |
| 818 | } |
| 819 | |
| 776 | 820 | /// Asserts the value is a float |
| 777 | 821 | pub fn floatHasFraction(self: Value) bool { |
| 778 | 822 | return switch (self.tag()) { |
| ... | ... | @@ -919,7 +963,7 @@ pub const Value = extern union { |
| 919 | 963 | /// Asserts the value is comparable. |
| 920 | 964 | pub fn order(lhs: Value, rhs: Value) std.math.Order { |
| 921 | 965 | const lhs_tag = lhs.tag(); |
| 922 | | const rhs_tag = lhs.tag(); |
| 966 | const rhs_tag = rhs.tag(); |
| 923 | 967 | const lhs_is_zero = lhs_tag == .zero or lhs_tag == .the_one_possible_value; |
| 924 | 968 | const rhs_is_zero = rhs_tag == .zero or rhs_tag == .the_one_possible_value; |
| 925 | 969 | if (lhs_is_zero) return rhs.orderAgainstZero().invert(); |
| ... | ... | @@ -939,8 +983,8 @@ pub const Value = extern union { |
| 939 | 983 | } |
| 940 | 984 | } |
| 941 | 985 | if (lhs_float or rhs_float) { |
| 942 | | const lhs_f128 = lhs.toF128(); |
| 943 | | const rhs_f128 = rhs.toF128(); |
| 986 | const lhs_f128 = lhs.toFloat(f128); |
| 987 | const rhs_f128 = rhs.toFloat(f128); |
| 944 | 988 | return std.math.order(lhs_f128, rhs_f128); |
| 945 | 989 | } |
| 946 | 990 | |