mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
big ints: Fix set(signed int minimum) panic
This commit is contained in:
parent
f6bf24b2f3
commit
1e09157b53
@ -18,18 +18,12 @@ const debug_safety = false;
|
||||
/// Returns the number of limbs needed to store `scalar`, which must be a
|
||||
/// primitive integer value.
|
||||
pub fn calcLimbLen(scalar: anytype) usize {
|
||||
const T = @TypeOf(scalar);
|
||||
switch (@typeInfo(T)) {
|
||||
.Int => |info| {
|
||||
const UT = if (info.signedness == .signed) std.meta.Int(.unsigned, info.bits - 1) else T;
|
||||
return @sizeOf(UT) / @sizeOf(Limb);
|
||||
},
|
||||
.ComptimeInt => {
|
||||
const w_value = if (scalar < 0) -scalar else scalar;
|
||||
return @divFloor(math.log2(w_value), limb_bits) + 1;
|
||||
},
|
||||
else => @compileError("parameter must be a primitive integer type"),
|
||||
if (scalar == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const w_value = std.math.absCast(scalar);
|
||||
return @divFloor(@intCast(Limb, math.log2(w_value)), limb_bits) + 1;
|
||||
}
|
||||
|
||||
pub fn calcToStringLimbsBufferLen(a_len: usize, base: u8) usize {
|
||||
@ -218,26 +212,22 @@ pub const Mutable = struct {
|
||||
/// needs to be to store a specific value.
|
||||
pub fn set(self: *Mutable, value: anytype) void {
|
||||
const T = @TypeOf(value);
|
||||
const needed_limbs = calcLimbLen(value);
|
||||
assert(needed_limbs <= self.limbs.len); // value too big
|
||||
|
||||
self.len = needed_limbs;
|
||||
self.positive = value >= 0;
|
||||
|
||||
switch (@typeInfo(T)) {
|
||||
.Int => |info| {
|
||||
const UT = if (info.signedness == .signed) std.meta.Int(.unsigned, info.bits - 1) else T;
|
||||
|
||||
const needed_limbs = @sizeOf(UT) / @sizeOf(Limb);
|
||||
assert(needed_limbs <= self.limbs.len); // value too big
|
||||
self.len = 0;
|
||||
self.positive = value >= 0;
|
||||
|
||||
var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);
|
||||
var w_value = std.math.absCast(value);
|
||||
|
||||
if (info.bits <= limb_bits) {
|
||||
self.limbs[0] = @as(Limb, w_value);
|
||||
self.len += 1;
|
||||
self.limbs[0] = w_value;
|
||||
} else {
|
||||
var i: usize = 0;
|
||||
while (w_value != 0) : (i += 1) {
|
||||
self.limbs[i] = @truncate(Limb, w_value);
|
||||
self.len += 1;
|
||||
|
||||
// TODO: shift == 64 at compile-time fails. Fails on u128 limbs.
|
||||
w_value >>= limb_bits / 2;
|
||||
@ -246,13 +236,7 @@ pub const Mutable = struct {
|
||||
}
|
||||
},
|
||||
.ComptimeInt => {
|
||||
comptime var w_value = if (value < 0) -value else value;
|
||||
|
||||
const req_limbs = @divFloor(math.log2(w_value), limb_bits) + 1;
|
||||
assert(req_limbs <= self.limbs.len); // value too big
|
||||
|
||||
self.len = req_limbs;
|
||||
self.positive = value >= 0;
|
||||
comptime var w_value = std.math.absCast(value);
|
||||
|
||||
if (w_value <= maxInt(Limb)) {
|
||||
self.limbs[0] = w_value;
|
||||
|
||||
@ -61,6 +61,13 @@ test "big.int sub-limb to" {
|
||||
try testing.expect((try a.to(u8)) == 10);
|
||||
}
|
||||
|
||||
test "big.int set negative minimum" {
|
||||
var a = try Managed.initSet(testing.allocator, @as(i64, minInt(i64)));
|
||||
defer a.deinit();
|
||||
|
||||
try testing.expect((try a.to(i64)) == minInt(i64));
|
||||
}
|
||||
|
||||
test "big.int to target too small error" {
|
||||
var a = try Managed.initSet(testing.allocator, 0xffffffff);
|
||||
defer a.deinit();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user