mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
Merge pull request #12918 from jacobly0/math-cast-comptime-int
std.math: fix behavior relating to comptime_int arguments
This commit is contained in:
commit
16cc65242f
14
build.zig
14
build.zig
@ -554,6 +554,8 @@ fn addCmakeCfgOptionsToExe(
|
||||
}) catch unreachable);
|
||||
assert(cfg.lld_include_dir.len != 0);
|
||||
exe.addIncludePath(cfg.lld_include_dir);
|
||||
exe.addIncludePath(cfg.llvm_include_dir);
|
||||
exe.addLibraryPath(cfg.llvm_lib_dir);
|
||||
addCMakeLibraryList(exe, cfg.clang_libraries);
|
||||
addCMakeLibraryList(exe, cfg.lld_libraries);
|
||||
addCMakeLibraryList(exe, cfg.llvm_libraries);
|
||||
@ -684,6 +686,8 @@ const CMakeConfig = struct {
|
||||
lld_include_dir: []const u8,
|
||||
lld_libraries: []const u8,
|
||||
clang_libraries: []const u8,
|
||||
llvm_lib_dir: []const u8,
|
||||
llvm_include_dir: []const u8,
|
||||
llvm_libraries: []const u8,
|
||||
dia_guids_lib: []const u8,
|
||||
};
|
||||
@ -745,6 +749,8 @@ fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig {
|
||||
.lld_include_dir = undefined,
|
||||
.lld_libraries = undefined,
|
||||
.clang_libraries = undefined,
|
||||
.llvm_lib_dir = undefined,
|
||||
.llvm_include_dir = undefined,
|
||||
.llvm_libraries = undefined,
|
||||
.dia_guids_lib = undefined,
|
||||
};
|
||||
@ -782,6 +788,14 @@ fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig {
|
||||
.prefix = "#define ZIG_DIA_GUIDS_LIB ",
|
||||
.field = "dia_guids_lib",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_LLVM_INCLUDE_PATH ",
|
||||
.field = "llvm_include_dir",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_LLVM_LIB_PATH ",
|
||||
.field = "llvm_lib_dir",
|
||||
},
|
||||
// .prefix = ZIG_LLVM_LINK_MODE parsed manually below
|
||||
};
|
||||
|
||||
|
@ -1063,10 +1063,11 @@ test "negateCast" {
|
||||
/// return null.
|
||||
pub fn cast(comptime T: type, x: anytype) ?T {
|
||||
comptime assert(@typeInfo(T) == .Int); // must pass an integer
|
||||
comptime assert(@typeInfo(@TypeOf(x)) == .Int); // must pass an integer
|
||||
if (maxInt(@TypeOf(x)) > maxInt(T) and x > maxInt(T)) {
|
||||
const is_comptime = @TypeOf(x) == comptime_int;
|
||||
comptime assert(is_comptime or @typeInfo(@TypeOf(x)) == .Int); // must pass an integer
|
||||
if ((is_comptime or maxInt(@TypeOf(x)) > maxInt(T)) and x > maxInt(T)) {
|
||||
return null;
|
||||
} else if (minInt(@TypeOf(x)) < minInt(T) and x < minInt(T)) {
|
||||
} else if ((is_comptime or minInt(@TypeOf(x)) < minInt(T)) and x < minInt(T)) {
|
||||
return null;
|
||||
} else {
|
||||
return @intCast(T, x);
|
||||
@ -1074,12 +1075,18 @@ pub fn cast(comptime T: type, x: anytype) ?T {
|
||||
}
|
||||
|
||||
test "cast" {
|
||||
try testing.expect(cast(u8, 300) == null);
|
||||
try testing.expect(cast(u8, @as(u32, 300)) == null);
|
||||
try testing.expect(cast(i8, -200) == null);
|
||||
try testing.expect(cast(i8, @as(i32, -200)) == null);
|
||||
try testing.expect(cast(u8, -1) == null);
|
||||
try testing.expect(cast(u8, @as(i8, -1)) == null);
|
||||
try testing.expect(cast(u64, -1) == null);
|
||||
try testing.expect(cast(u64, @as(i8, -1)) == null);
|
||||
|
||||
try testing.expect(cast(u8, 255).? == @as(u8, 255));
|
||||
try testing.expect(cast(u8, @as(u32, 255)).? == @as(u8, 255));
|
||||
try testing.expect(@TypeOf(cast(u8, 255).?) == u8);
|
||||
try testing.expect(@TypeOf(cast(u8, @as(u32, 255)).?) == u8);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,9 @@ const debug_safety = false;
|
||||
|
||||
/// Returns the number of limbs needed to store `scalar`, which must be a
|
||||
/// primitive integer value.
|
||||
/// Note: A comptime-known upper bound of this value that may be used
|
||||
/// instead if `scalar` is not already comptime-known is
|
||||
/// `calcTwosCompLimbCount(@typeInfo(@TypeOf(scalar)).Int.bits)`
|
||||
pub fn calcLimbLen(scalar: anytype) usize {
|
||||
if (scalar == 0) {
|
||||
return 1;
|
||||
@ -391,7 +394,18 @@ pub const Mutable = struct {
|
||||
/// Asserts the result fits in `r`. An upper bound on the number of limbs needed by
|
||||
/// r is `math.max(a.limbs.len, calcLimbLen(scalar)) + 1`.
|
||||
pub fn addScalar(r: *Mutable, a: Const, scalar: anytype) void {
|
||||
var limbs: [calcLimbLen(scalar)]Limb = undefined;
|
||||
// Normally we could just determine the number of limbs needed with calcLimbLen,
|
||||
// but that is not comptime-known when scalar is not a comptime_int. Instead, we
|
||||
// use calcTwosCompLimbCount for a non-comptime_int scalar, which can be pessimistic
|
||||
// in the case that scalar happens to be small in magnitude within its type, but it
|
||||
// is well worth being able to use the stack and not needing an allocator passed in.
|
||||
// Note that Mutable.init still sets len to calcLimbLen(scalar) in any case.
|
||||
const limb_len = comptime switch (@typeInfo(@TypeOf(scalar))) {
|
||||
.ComptimeInt => calcLimbLen(scalar),
|
||||
.Int => |info| calcTwosCompLimbCount(info.bits),
|
||||
else => @compileError("expected scalar to be an int"),
|
||||
};
|
||||
var limbs: [limb_len]Limb = undefined;
|
||||
const operand = init(&limbs, scalar).toConst();
|
||||
return add(r, a, operand);
|
||||
}
|
||||
@ -2303,7 +2317,18 @@ pub const Const = struct {
|
||||
|
||||
/// Same as `order` but the right-hand operand is a primitive integer.
|
||||
pub fn orderAgainstScalar(lhs: Const, scalar: anytype) math.Order {
|
||||
var limbs: [calcLimbLen(scalar)]Limb = undefined;
|
||||
// Normally we could just determine the number of limbs needed with calcLimbLen,
|
||||
// but that is not comptime-known when scalar is not a comptime_int. Instead, we
|
||||
// use calcTwosCompLimbCount for a non-comptime_int scalar, which can be pessimistic
|
||||
// in the case that scalar happens to be small in magnitude within its type, but it
|
||||
// is well worth being able to use the stack and not needing an allocator passed in.
|
||||
// Note that Mutable.init still sets len to calcLimbLen(scalar) in any case.
|
||||
const limb_len = comptime switch (@typeInfo(@TypeOf(scalar))) {
|
||||
.ComptimeInt => calcLimbLen(scalar),
|
||||
.Int => |info| calcTwosCompLimbCount(info.bits),
|
||||
else => @compileError("expected scalar to be an int"),
|
||||
};
|
||||
var limbs: [limb_len]Limb = undefined;
|
||||
const rhs = Mutable.init(&limbs, scalar);
|
||||
return order(lhs, rhs.toConst());
|
||||
}
|
||||
|
@ -573,7 +573,7 @@ test "big.int add sign" {
|
||||
try testing.expect((try a.to(i32)) == -3);
|
||||
}
|
||||
|
||||
test "big.int add scalar" {
|
||||
test "big.int add comptime scalar" {
|
||||
var a = try Managed.initSet(testing.allocator, 50);
|
||||
defer a.deinit();
|
||||
|
||||
@ -584,6 +584,17 @@ test "big.int add scalar" {
|
||||
try testing.expect((try b.to(u32)) == 55);
|
||||
}
|
||||
|
||||
test "big.int add scalar" {
|
||||
var a = try Managed.initSet(testing.allocator, 123);
|
||||
defer a.deinit();
|
||||
|
||||
var b = try Managed.init(testing.allocator);
|
||||
defer b.deinit();
|
||||
try b.addScalar(&a, @as(u32, 31));
|
||||
|
||||
try testing.expect((try b.to(u32)) == 154);
|
||||
}
|
||||
|
||||
test "big.int addWrap single-single, unsigned" {
|
||||
var a = try Managed.initSet(testing.allocator, maxInt(u17));
|
||||
defer a.deinit();
|
||||
|
@ -22,6 +22,8 @@
|
||||
#define ZIG_LLD_INCLUDE_PATH "@LLD_INCLUDE_DIRS@"
|
||||
#define ZIG_LLD_LIBRARIES "@LLD_LIBRARIES@"
|
||||
#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@"
|
||||
#define ZIG_LLVM_INCLUDE_PATH "@LLVM_INCLUDE_DIRS@"
|
||||
#define ZIG_LLVM_LIB_PATH "@LLVM_LIBDIRS@"
|
||||
#define ZIG_LLVM_LIBRARIES "@LLVM_LIBRARIES@"
|
||||
#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user