mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
Sema: Allow small integer types to coerce to floats
If the float can store all possible values of the integer without rounding, coercion is allowed. The integer's precision must be less than or equal to the float's significand precision. Closes #18614
This commit is contained in:
committed by
Andrew Kelley
parent
5082e85de9
commit
484cc15366
@@ -157,6 +157,59 @@ test "@floatFromInt(f80)" {
|
||||
try comptime S.doTheTest(i256);
|
||||
}
|
||||
|
||||
test "type coercion from int to float" {
|
||||
const check = struct {
|
||||
// Check that an integer value can be coerced to a float type and
|
||||
// then converted back to the original value without rounding issues.
|
||||
fn value(Float: type, int: anytype) !void {
|
||||
const float: Float = int;
|
||||
const Int = @TypeOf(int);
|
||||
try std.testing.expectEqual(int, @as(Int, @intFromFloat(float)));
|
||||
try std.testing.expectEqual(int, @as(Int, @intFromFloat(@ceil(float))));
|
||||
try std.testing.expectEqual(int, @as(Int, @intFromFloat(@floor(float))));
|
||||
}
|
||||
|
||||
// Exhaustively check that all possible values of the integer type can
|
||||
// safely be coerced to the float type.
|
||||
fn allValues(Float: type, Int: type) !void {
|
||||
var int: Int = std.math.minInt(Int);
|
||||
while (int < std.math.maxInt(Int)) : (int += 1)
|
||||
try value(Float, int);
|
||||
}
|
||||
|
||||
// Check that the min and max values of the integer type can safely be
|
||||
// coerced to the float type.
|
||||
fn edgeValues(Float: type, Int: type) !void {
|
||||
var int: Int = std.math.minInt(Int);
|
||||
try value(Float, int);
|
||||
int = std.math.maxInt(Int);
|
||||
try value(Float, int);
|
||||
}
|
||||
};
|
||||
|
||||
try check.allValues(f16, u11);
|
||||
try check.allValues(f16, i12);
|
||||
|
||||
try check.edgeValues(f32, u24);
|
||||
try check.edgeValues(f32, i25);
|
||||
|
||||
try check.edgeValues(f64, u53);
|
||||
try check.edgeValues(f64, i54);
|
||||
|
||||
try check.edgeValues(f80, u64);
|
||||
try check.edgeValues(f80, i65);
|
||||
|
||||
try check.edgeValues(f128, u113);
|
||||
try check.edgeValues(f128, i114);
|
||||
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
|
||||
// Basic sanity check that the coercions work for vectors too.
|
||||
const int_vec: @Vector(2, u24) = @splat(123);
|
||||
try check.value(@Vector(2, f32), int_vec);
|
||||
}
|
||||
|
||||
test "@intFromFloat" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Test that integer types above a certain size will not coerce to a float.
|
||||
|
||||
fn testCoerce(Float: type, Int: type) void {
|
||||
var i: Int = 0;
|
||||
_ = &i;
|
||||
_ = @as(Float, i);
|
||||
}
|
||||
|
||||
export fn entry() void {
|
||||
testCoerce(f16, u11); // Okay
|
||||
testCoerce(f16, u12); // Too big
|
||||
|
||||
testCoerce(f16, i12);
|
||||
testCoerce(f16, i13);
|
||||
|
||||
testCoerce(f32, u24);
|
||||
testCoerce(f32, u25);
|
||||
|
||||
testCoerce(f32, i25);
|
||||
testCoerce(f32, i26);
|
||||
|
||||
testCoerce(f64, u53);
|
||||
testCoerce(f64, u54);
|
||||
|
||||
testCoerce(f64, i54);
|
||||
testCoerce(f64, i55);
|
||||
|
||||
testCoerce(f80, u64);
|
||||
testCoerce(f80, u65);
|
||||
|
||||
testCoerce(f80, i65);
|
||||
testCoerce(f80, i66);
|
||||
|
||||
testCoerce(f128, u113);
|
||||
testCoerce(f128, u114);
|
||||
|
||||
testCoerce(f128, i114);
|
||||
testCoerce(f128, i115);
|
||||
}
|
||||
|
||||
// error
|
||||
//
|
||||
// :6:20: error: expected type 'f16', found 'u12'
|
||||
// :6:20: error: expected type 'f16', found 'i13'
|
||||
// :6:20: error: expected type 'f32', found 'u25'
|
||||
// :6:20: error: expected type 'f32', found 'i26'
|
||||
// :6:20: error: expected type 'f64', found 'u54'
|
||||
// :6:20: error: expected type 'f64', found 'i55'
|
||||
// :6:20: error: expected type 'f80', found 'u65'
|
||||
// :6:20: error: expected type 'f80', found 'i66'
|
||||
// :6:20: error: expected type 'f128', found 'u114'
|
||||
// :6:20: error: expected type 'f128', found 'i115'
|
||||
Reference in New Issue
Block a user