authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-04-13 18:56:26+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-15 12:51:43-04:00
log3fd38429e44f485907647ff85ce405b787f67bb9
treeb206cf18903a1594776cfb86311ecbbbb69f12ca
parent0276d9ddc58694b81b5e98cc717243d50db873b1

Enable formatting in std.big.Int.format


2 files changed, 43 insertions(+), 23 deletions(-)

lib/std/math/big/int.zig+42-22
...@@ -381,14 +381,15 @@ pub const Int = struct {...@@ -381,14 +381,15 @@ pub const Int = struct {
381 return if (d < base) d else return error.DigitTooLargeForBase;381 return if (d < base) d else return error.DigitTooLargeForBase;
382 }382 }
383383
384 fn digitToChar(d: u8, base: u8) !u8 {384 fn digitToChar(d: u8, base: u8, uppercase: bool) !u8 {
385 if (d >= base) {385 if (d >= base) {
386 return error.DigitTooLargeForBase;386 return error.DigitTooLargeForBase;
387 }387 }
388388
389 const a: u8 = if (uppercase) 'A' else 'a';
389 return switch (d) {390 return switch (d) {
390 0...9 => '0' + d,391 0...9 => '0' + d,
391 0xa...0xf => ('a' - 0xa) + d,392 0xa...0xf => (a - 0xa) + d,
392 else => unreachable,393 else => unreachable,
393 };394 };
394 }395 }
...@@ -434,7 +435,7 @@ pub const Int = struct {...@@ -434,7 +435,7 @@ pub const Int = struct {
434 /// Converts self to a string in the requested base. Memory is allocated from the provided435 /// Converts self to a string in the requested base. Memory is allocated from the provided
435 /// allocator and not the one present in self.436 /// allocator and not the one present in self.
436 /// TODO make this call format instead of the other way around437 /// TODO make this call format instead of the other way around
437 pub fn toString(self: Int, allocator: *Allocator, base: u8) ![]const u8 {438 pub fn toString(self: Int, allocator: *Allocator, base: u8, uppercase: bool) ![]const u8 {
438 if (base < 2 or base > 16) {439 if (base < 2 or base > 16) {
439 return error.InvalidBase;440 return error.InvalidBase;
440 }441 }
...@@ -456,7 +457,7 @@ pub const Int = struct {...@@ -456,7 +457,7 @@ pub const Int = struct {
456 var shift: usize = 0;457 var shift: usize = 0;
457 while (shift < Limb.bit_count) : (shift += base_shift) {458 while (shift < Limb.bit_count) : (shift += base_shift) {
458 const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & @as(Limb, base - 1));459 const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & @as(Limb, base - 1));
459 const ch = try digitToChar(r, base);460 const ch = try digitToChar(r, base, uppercase);
460 try digits.append(ch);461 try digits.append(ch);
461 }462 }
462 }463 }
...@@ -492,7 +493,7 @@ pub const Int = struct {...@@ -492,7 +493,7 @@ pub const Int = struct {
492 var r_word = r.limbs[0];493 var r_word = r.limbs[0];
493 var i: usize = 0;494 var i: usize = 0;
494 while (i < digits_per_limb) : (i += 1) {495 while (i < digits_per_limb) : (i += 1) {
495 const ch = try digitToChar(@intCast(u8, r_word % base), base);496 const ch = try digitToChar(@intCast(u8, r_word % base), base, uppercase);
496 r_word /= base;497 r_word /= base;
497 try digits.append(ch);498 try digits.append(ch);
498 }499 }
...@@ -503,7 +504,7 @@ pub const Int = struct {...@@ -503,7 +504,7 @@ pub const Int = struct {
503504
504 var r_word = q.limbs[0];505 var r_word = q.limbs[0];
505 while (r_word != 0) {506 while (r_word != 0) {
506 const ch = try digitToChar(@intCast(u8, r_word % base), base);507 const ch = try digitToChar(@intCast(u8, r_word % base), base, uppercase);
507 r_word /= base;508 r_word /= base;
508 try digits.append(ch);509 try digits.append(ch);
509 }510 }
...@@ -528,9 +529,28 @@ pub const Int = struct {...@@ -528,9 +529,28 @@ pub const Int = struct {
528 out_stream: var,529 out_stream: var,
529 ) !void {530 ) !void {
530 self.assertWritable();531 self.assertWritable();
531 // TODO look at fmt and support other bases
532 // TODO support read-only fixed integers532 // TODO support read-only fixed integers
533 const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");533
534 comptime var radix = 10;
535 comptime var uppercase = false;
536
537 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) {
538 radix = 10;
539 uppercase = false;
540 } else if (comptime std.mem.eql(u8, fmt, "b")) {
541 radix = 2;
542 uppercase = false;
543 } else if (comptime std.mem.eql(u8, fmt, "x")) {
544 radix = 16;
545 uppercase = false;
546 } else if (comptime std.mem.eql(u8, fmt, "X")) {
547 radix = 16;
548 uppercase = true;
549 } else {
550 @compileError("Unknown format string: '" ++ fmt ++ "'");
551 }
552
553 const str = self.toString(self.allocator.?, radix, uppercase) catch @panic("TODO make this non allocating");
534 defer self.allocator.?.free(str);554 defer self.allocator.?.free(str);
535 return out_stream.writeAll(str);555 return out_stream.writeAll(str);
536 }556 }
...@@ -1746,7 +1766,7 @@ test "big.int string to" {...@@ -1746,7 +1766,7 @@ test "big.int string to" {
1746 const a = try Int.initSet(testing.allocator, 120317241209124781241290847124);1766 const a = try Int.initSet(testing.allocator, 120317241209124781241290847124);
1747 defer a.deinit();1767 defer a.deinit();
17481768
1749 const as = try a.toString(testing.allocator, 10);1769 const as = try a.toString(testing.allocator, 10, false);
1750 defer testing.allocator.free(as);1770 defer testing.allocator.free(as);
1751 const es = "120317241209124781241290847124";1771 const es = "120317241209124781241290847124";
17521772
...@@ -1757,14 +1777,14 @@ test "big.int string to base base error" {...@@ -1757,14 +1777,14 @@ test "big.int string to base base error" {
1757 const a = try Int.initSet(testing.allocator, 0xffffffff);1777 const a = try Int.initSet(testing.allocator, 0xffffffff);
1758 defer a.deinit();1778 defer a.deinit();
17591779
1760 testing.expectError(error.InvalidBase, a.toString(testing.allocator, 45));1780 testing.expectError(error.InvalidBase, a.toString(testing.allocator, 45, false));
1761}1781}
17621782
1763test "big.int string to base 2" {1783test "big.int string to base 2" {
1764 const a = try Int.initSet(testing.allocator, -0b1011);1784 const a = try Int.initSet(testing.allocator, -0b1011);
1765 defer a.deinit();1785 defer a.deinit();
17661786
1767 const as = try a.toString(testing.allocator, 2);1787 const as = try a.toString(testing.allocator, 2, false);
1768 defer testing.allocator.free(as);1788 defer testing.allocator.free(as);
1769 const es = "-1011";1789 const es = "-1011";
17701790
...@@ -1775,7 +1795,7 @@ test "big.int string to base 16" {...@@ -1775,7 +1795,7 @@ test "big.int string to base 16" {
1775 const a = try Int.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab);1795 const a = try Int.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab);
1776 defer a.deinit();1796 defer a.deinit();
17771797
1778 const as = try a.toString(testing.allocator, 16);1798 const as = try a.toString(testing.allocator, 16, false);
1779 defer testing.allocator.free(as);1799 defer testing.allocator.free(as);
1780 const es = "efffffff00000001eeeeeeefaaaaaaab";1800 const es = "efffffff00000001eeeeeeefaaaaaaab";
17811801
...@@ -1786,7 +1806,7 @@ test "big.int neg string to" {...@@ -1786,7 +1806,7 @@ test "big.int neg string to" {
1786 const a = try Int.initSet(testing.allocator, -123907434);1806 const a = try Int.initSet(testing.allocator, -123907434);
1787 defer a.deinit();1807 defer a.deinit();
17881808
1789 const as = try a.toString(testing.allocator, 10);1809 const as = try a.toString(testing.allocator, 10, false);
1790 defer testing.allocator.free(as);1810 defer testing.allocator.free(as);
1791 const es = "-123907434";1811 const es = "-123907434";
17921812
...@@ -1797,7 +1817,7 @@ test "big.int zero string to" {...@@ -1797,7 +1817,7 @@ test "big.int zero string to" {
1797 const a = try Int.initSet(testing.allocator, 0);1817 const a = try Int.initSet(testing.allocator, 0);
1798 defer a.deinit();1818 defer a.deinit();
17991819
1800 const as = try a.toString(testing.allocator, 10);1820 const as = try a.toString(testing.allocator, 10, false);
1801 defer testing.allocator.free(as);1821 defer testing.allocator.free(as);
1802 const es = "0";1822 const es = "0";
18031823
...@@ -2628,7 +2648,7 @@ test "big.int div multi-multi zero-limb trailing (with rem)" {...@@ -2628,7 +2648,7 @@ test "big.int div multi-multi zero-limb trailing (with rem)" {
26282648
2629 testing.expect((try q.to(u128)) == 0x10000000000000000);2649 testing.expect((try q.to(u128)) == 0x10000000000000000);
26302650
2631 const rs = try r.toString(testing.allocator, 16);2651 const rs = try r.toString(testing.allocator, 16, false);
2632 defer testing.allocator.free(rs);2652 defer testing.allocator.free(rs);
2633 testing.expect(std.mem.eql(u8, rs, "4444444344444443111111111111111100000000000000000000000000000000"));2653 testing.expect(std.mem.eql(u8, rs, "4444444344444443111111111111111100000000000000000000000000000000"));
2634}2654}
...@@ -2647,7 +2667,7 @@ test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-li...@@ -2647,7 +2667,7 @@ test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-li
26472667
2648 testing.expect((try q.to(u128)) == 0x1);2668 testing.expect((try q.to(u128)) == 0x1);
26492669
2650 const rs = try r.toString(testing.allocator, 16);2670 const rs = try r.toString(testing.allocator, 16, false);
2651 defer testing.allocator.free(rs);2671 defer testing.allocator.free(rs);
2652 testing.expect(std.mem.eql(u8, rs, "444444434444444311111111111111110000000000000000"));2672 testing.expect(std.mem.eql(u8, rs, "444444434444444311111111111111110000000000000000"));
2653}2673}
...@@ -2664,11 +2684,11 @@ test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-li...@@ -2664,11 +2684,11 @@ test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-li
2664 defer r.deinit();2684 defer r.deinit();
2665 try Int.divTrunc(&q, &r, a, b);2685 try Int.divTrunc(&q, &r, a, b);
26662686
2667 const qs = try q.toString(testing.allocator, 16);2687 const qs = try q.toString(testing.allocator, 16, false);
2668 defer testing.allocator.free(qs);2688 defer testing.allocator.free(qs);
2669 testing.expect(std.mem.eql(u8, qs, "10000000000000000820820803105186f"));2689 testing.expect(std.mem.eql(u8, qs, "10000000000000000820820803105186f"));
26702690
2671 const rs = try r.toString(testing.allocator, 16);2691 const rs = try r.toString(testing.allocator, 16, false);
2672 defer testing.allocator.free(rs);2692 defer testing.allocator.free(rs);
2673 testing.expect(std.mem.eql(u8, rs, "4e11f2baa5896a321d463b543d0104e30000000000000000"));2693 testing.expect(std.mem.eql(u8, rs, "4e11f2baa5896a321d463b543d0104e30000000000000000"));
2674}2694}
...@@ -2688,11 +2708,11 @@ test "big.int div multi-multi fuzz case #1" {...@@ -2688,11 +2708,11 @@ test "big.int div multi-multi fuzz case #1" {
2688 defer r.deinit();2708 defer r.deinit();
2689 try Int.divTrunc(&q, &r, a, b);2709 try Int.divTrunc(&q, &r, a, b);
26902710
2691 const qs = try q.toString(testing.allocator, 16);2711 const qs = try q.toString(testing.allocator, 16, false);
2692 defer testing.allocator.free(qs);2712 defer testing.allocator.free(qs);
2693 testing.expect(std.mem.eql(u8, qs, "3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1"));2713 testing.expect(std.mem.eql(u8, qs, "3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1"));
26942714
2695 const rs = try r.toString(testing.allocator, 16);2715 const rs = try r.toString(testing.allocator, 16, false);
2696 defer testing.allocator.free(rs);2716 defer testing.allocator.free(rs);
2697 testing.expect(std.mem.eql(u8, rs, "310d1d4c414426b4836c2635bad1df3a424e50cbdd167ffccb4dfff57d36b4aae0d6ca0910698220171a0f3373c1060a046c2812f0027e321f72979daa5e7973214170d49e885de0c0ecc167837d44502430674a82522e5df6a0759548052420b91ec1"));2717 testing.expect(std.mem.eql(u8, rs, "310d1d4c414426b4836c2635bad1df3a424e50cbdd167ffccb4dfff57d36b4aae0d6ca0910698220171a0f3373c1060a046c2812f0027e321f72979daa5e7973214170d49e885de0c0ecc167837d44502430674a82522e5df6a0759548052420b91ec1"));
2698}2718}
...@@ -2712,11 +2732,11 @@ test "big.int div multi-multi fuzz case #2" {...@@ -2712,11 +2732,11 @@ test "big.int div multi-multi fuzz case #2" {
2712 defer r.deinit();2732 defer r.deinit();
2713 try Int.divTrunc(&q, &r, a, b);2733 try Int.divTrunc(&q, &r, a, b);
27142734
2715 const qs = try q.toString(testing.allocator, 16);2735 const qs = try q.toString(testing.allocator, 16, false);
2716 defer testing.allocator.free(qs);2736 defer testing.allocator.free(qs);
2717 testing.expect(std.mem.eql(u8, qs, "40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4"));2737 testing.expect(std.mem.eql(u8, qs, "40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4"));
27182738
2719 const rs = try r.toString(testing.allocator, 16);2739 const rs = try r.toString(testing.allocator, 16, false);
2720 defer testing.allocator.free(rs);2740 defer testing.allocator.free(rs);
2721 testing.expect(std.mem.eql(u8, rs, "a900000000000000000000000000000000000000000000000000"));2741 testing.expect(std.mem.eql(u8, rs, "a900000000000000000000000000000000000000000000000000"));
2722}2742}
src-self-hosted/translate_c.zig+1-1
...@@ -3922,7 +3922,7 @@ fn transCreateNodeAPInt(c: *Context, int: *const ZigClangAPSInt) !*ast.Node {...@@ -3922,7 +3922,7 @@ fn transCreateNodeAPInt(c: *Context, int: *const ZigClangAPSInt) !*ast.Node {
3922 },3922 },
3923 else => @compileError("unimplemented"),3923 else => @compileError("unimplemented"),
3924 }3924 }
3925 const str = big.toString(c.a(), 10) catch |err| switch (err) {3925 const str = big.toString(c.a(), 10, false) catch |err| switch (err) {
3926 error.OutOfMemory => return error.OutOfMemory,3926 error.OutOfMemory => return error.OutOfMemory,
3927 else => unreachable,3927 else => unreachable,
3928 };3928 };