authorgravatar for srazin123@gmail.compoypoyan <srazin123@gmail.com> 2024-05-21 21:28:05+08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-05-21 13:28:05+00:00
logaa0736651346304199cebc8ea97bebbcde0491e3
treed73e794dd9681034b183ad436031871ea2c1029a
parent33d7815813cd166a35772da46d74dbb50c68b6c8
signaturebadge-check Signed by PGP key B5690EEEBB952194

std.math.big.int.Managed: adjust size of arg for limbs_buffer in format()


2 files changed, 56 insertions(+), 9 deletions(-)

lib/std/math/big/int.zig+7-9
...@@ -2201,8 +2201,8 @@ pub const Const = struct {...@@ -2201,8 +2201,8 @@ pub const Const = struct {
2201 }2201 }
22022202
2203 /// To allow `std.fmt.format` to work with this type.2203 /// To allow `std.fmt.format` to work with this type.
2204 /// If the integer is larger than `pow(2, 64 * @sizeOf(usize) * 8), this function will fail2204 /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`,
2205 /// to print the string, printing "(BigInt)" instead of a number.2205 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
2206 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.2206 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
2207 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.2207 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2208 pub fn format(2208 pub fn format(
...@@ -2231,13 +2231,11 @@ pub const Const = struct {...@@ -2231,13 +2231,11 @@ pub const Const = struct {
2231 std.fmt.invalidFmtError(fmt, self);2231 std.fmt.invalidFmtError(fmt, self);
2232 }2232 }
22332233
2234 var limbs: [128]Limb = undefined;2234 const available_len = 64;
2235 const needed_limbs = calcDivLimbsBufferLen(self.limbs.len, 1);2235 if (self.limbs.len > available_len)
2236 if (needed_limbs > limbs.len)
2237 return out_stream.writeAll("(BigInt)");2236 return out_stream.writeAll("(BigInt)");
22382237
2239 // This is the inverse of calcDivLimbsBufferLen2238 var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;
2240 const available_len = (limbs.len / 3) - 2;
22412239
2242 const biggest: Const = .{2240 const biggest: Const = .{
2243 .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len),2241 .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len),
...@@ -2804,8 +2802,8 @@ pub const Managed = struct {...@@ -2804,8 +2802,8 @@ pub const Managed = struct {
2804 }2802 }
28052803
2806 /// To allow `std.fmt.format` to work with `Managed`.2804 /// To allow `std.fmt.format` to work with `Managed`.
2807 /// If the integer is larger than `pow(2, 64 * @sizeOf(usize) * 8), this function will fail2805 /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`,
2808 /// to print the string, printing "(BigInt)" instead of a number.2806 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
2809 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.2807 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
2810 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.2808 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2811 pub fn format(2809 pub fn format(
lib/std/math/big/int_test.zig+49
...@@ -3232,3 +3232,52 @@ test "Managed sqrt(n) succeed with res.bitCountAbs() >= usize bits" {...@@ -3232,3 +3232,52 @@ test "Managed sqrt(n) succeed with res.bitCountAbs() >= usize bits" {
3232 try expected.setString(10, "11663466984815033033");3232 try expected.setString(10, "11663466984815033033");
3233 try std.testing.expectEqual(std.math.Order.eq, expected.order(res));3233 try std.testing.expectEqual(std.math.Order.eq, expected.order(res));
3234}3234}
3235
3236test "(BigInt) positive" {
3237 var a = try Managed.initSet(testing.allocator, 2);
3238 defer a.deinit();
3239
3240 var b = try Managed.init(testing.allocator);
3241 defer b.deinit();
3242
3243 var c = try Managed.initSet(testing.allocator, 1);
3244 defer c.deinit();
3245
3246 // a = pow(2, 64 * @sizeOf(usize) * 8), b = a - 1
3247 try a.pow(&a, 64 * @sizeOf(Limb) * 8);
3248 try b.sub(&a, &c);
3249
3250 const a_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{a});
3251 defer testing.allocator.free(a_fmt);
3252
3253 const b_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{b});
3254 defer testing.allocator.free(b_fmt);
3255
3256 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
3257 try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)"));
3258}
3259
3260test "(BigInt) negative" {
3261 var a = try Managed.initSet(testing.allocator, 2);
3262 defer a.deinit();
3263
3264 var b = try Managed.init(testing.allocator);
3265 defer b.deinit();
3266
3267 var c = try Managed.initSet(testing.allocator, 1);
3268 defer c.deinit();
3269
3270 // a = -pow(2, 64 * @sizeOf(usize) * 8), b = a + 1
3271 try a.pow(&a, 64 * @sizeOf(Limb) * 8);
3272 a.negate();
3273 try b.add(&a, &c);
3274
3275 const a_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{a});
3276 defer testing.allocator.free(a_fmt);
3277
3278 const b_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{b});
3279 defer testing.allocator.free(b_fmt);
3280
3281 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
3282 try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)"));
3283}