authorgravatar for jason@ket.soJason Phan <jason@ket.so> 2022-12-05 14:58:45-06:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-05 22:58:45+02:00
log97827d6d38ecd078fbbcff3d71a7e104341695cd
tree1be80e5aca0e36fd3086ad74d97062878406f82a
parent9e74e4c1f87acd987d6e96ca7388fd69f512ef1f
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

std.fmt.formatInt: Use an optimized path for decimals

It enables faster decimal-to-string conversions for values in the range [0, 100).

1 files changed, 38 insertions(+), 6 deletions(-)

lib/std/fmt.zig+38-6
...@@ -1429,12 +1429,29 @@ pub fn formatInt(...@@ -1429,12 +1429,29 @@ pub fn formatInt(
14291429
1430 var a: MinInt = abs_value;1430 var a: MinInt = abs_value;
1431 var index: usize = buf.len;1431 var index: usize = buf.len;
1432 while (true) {1432
1433 const digit = a % base;1433 // TODO isComptime here because of https://github.com/ziglang/zig/issues/13335.
1434 index -= 1;1434 if (base == 10 and !isComptime()) {
1435 buf[index] = digitToChar(@intCast(u8, digit), case);1435 while (a >= 100) : (a = @divTrunc(a, 100)) {
1436 a /= base;1436 index -= 2;
1437 if (a == 0) break;1437 buf[index..][0..2].* = digits2(@intCast(usize, a % 100));
1438 }
1439
1440 if (a < 10) {
1441 index -= 1;
1442 buf[index] = '0' + @intCast(u8, a);
1443 } else {
1444 index -= 2;
1445 buf[index..][0..2].* = digits2(@intCast(usize, a));
1446 }
1447 } else {
1448 while (true) {
1449 const digit = a % base;
1450 index -= 1;
1451 buf[index] = digitToChar(@intCast(u8, digit), case);
1452 a /= base;
1453 if (a == 0) break;
1454 }
1438 }1455 }
14391456
1440 if (value_info.signedness == .signed) {1457 if (value_info.signedness == .signed) {
...@@ -1454,12 +1471,27 @@ pub fn formatInt(...@@ -1454,12 +1471,27 @@ pub fn formatInt(
1454 return formatBuf(buf[index..], options, writer);1471 return formatBuf(buf[index..], options, writer);
1455}1472}
14561473
1474// TODO: Remove once https://github.com/ziglang/zig/issues/868 is resolved.
1475fn isComptime() bool {
1476 var a: u8 = 0;
1477 return @typeInfo(@TypeOf(.{a})).Struct.fields[0].is_comptime;
1478}
1479
1457pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) usize {1480pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) usize {
1458 var fbs = std.io.fixedBufferStream(out_buf);1481 var fbs = std.io.fixedBufferStream(out_buf);
1459 formatInt(value, base, case, options, fbs.writer()) catch unreachable;1482 formatInt(value, base, case, options, fbs.writer()) catch unreachable;
1460 return fbs.pos;1483 return fbs.pos;
1461}1484}
14621485
1486// Converts values in the range [0, 100) to a string.
1487fn digits2(value: usize) [2]u8 {
1488 return ("0001020304050607080910111213141516171819" ++
1489 "2021222324252627282930313233343536373839" ++
1490 "4041424344454647484950515253545556575859" ++
1491 "6061626364656667686970717273747576777879" ++
1492 "8081828384858687888990919293949596979899")[value * 2 ..][0..2].*;
1493}
1494
1463const FormatDurationData = struct {1495const FormatDurationData = struct {
1464 ns: u64,1496 ns: u64,
1465 negative: bool = false,1497 negative: bool = false,