| author | |
| committer | |
| log | aa0736651346304199cebc8ea97bebbcde0491e3 |
| tree | d73e794dd9681034b183ad436031871ea2c1029a |
| parent | 33d7815813cd166a35772da46d74dbb50c68b6c8 |
| signature |
2 files changed, 56 insertions(+), 9 deletions(-)
lib/std/math/big/int.zig+7-9| ... | ... | @@ -2201,8 +2201,8 @@ pub const Const = struct { |
| 2201 | 2201 | } |
| 2202 | 2202 | |
| 2203 | 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 fail | |
| 2205 | /// to print the string, printing "(BigInt)" instead of a number. | |
| 2204 | /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, | |
| 2205 | /// this function will fail to print the string, printing "(BigInt)" instead of a number. | |
| 2206 | 2206 | /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. |
| 2207 | 2207 | /// See `toString` and `toStringAlloc` for a way to print big integers without failure. |
| 2208 | 2208 | pub fn format( |
| ... | ... | @@ -2231,13 +2231,11 @@ pub const Const = struct { |
| 2231 | 2231 | std.fmt.invalidFmtError(fmt, self); |
| 2232 | 2232 | } |
| 2233 | 2233 | |
| 2234 | var limbs: [128]Limb = undefined; | |
| 2235 | const needed_limbs = calcDivLimbsBufferLen(self.limbs.len, 1); | |
| 2236 | if (needed_limbs > limbs.len) | |
| 2234 | const available_len = 64; | |
| 2235 | if (self.limbs.len > available_len) | |
| 2237 | 2236 | return out_stream.writeAll("(BigInt)"); |
| 2238 | 2237 | |
| 2239 | // This is the inverse of calcDivLimbsBufferLen | |
| 2240 | const available_len = (limbs.len / 3) - 2; | |
| 2238 | var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined; | |
| 2241 | 2239 | |
| 2242 | 2240 | const biggest: Const = .{ |
| 2243 | 2241 | .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len), |
| ... | ... | @@ -2804,8 +2802,8 @@ pub const Managed = struct { |
| 2804 | 2802 | } |
| 2805 | 2803 | |
| 2806 | 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 fail | |
| 2808 | /// to print the string, printing "(BigInt)" instead of a number. | |
| 2805 | /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, | |
| 2806 | /// this function will fail to print the string, printing "(BigInt)" instead of a number. | |
| 2809 | 2807 | /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. |
| 2810 | 2808 | /// See `toString` and `toStringAlloc` for a way to print big integers without failure. |
| 2811 | 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 | 3232 | try expected.setString(10, "11663466984815033033"); |
| 3233 | 3233 | try std.testing.expectEqual(std.math.Order.eq, expected.order(res)); |
| 3234 | 3234 | } |
| 3235 | ||
| 3236 | test "(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 | ||
| 3260 | test "(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 | } |