Skip to content

Commit dfebbdb

Browse files
committed
Update to the latest variant for computing the number of digits of an integer
* Quite a bit faster, see #2365
1 parent 8600510 commit dfebbdb

File tree

2 files changed

+21
-22
lines changed

2 files changed

+21
-22
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Performance:
4141
* Fiber-local variables are much faster now by using less synchronization.
4242
* Improved the performance of the exceptional case of `String#chr` (#2318, @chrisseaton).
4343
* Improved the performance of `IO#read_nonblock` when no data is available to be read.
44-
* Faster solution for lazy integer length (#2365, @chrisseaton).
44+
* Faster solution for lazy integer length (#2365, @lemire, @chrisseaton).
4545

4646
Changes:
4747

src/main/java/org/truffleruby/core/rope/LazyIntRope.java

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,24 @@ protected LazyIntRope(int value, Encoding encoding, int length) {
3131
assert Integer.toString(value).length() == length : value + " " + length;
3232
}
3333

34-
@CompilationFinal(dimensions = 1) private static final int[] LENGTH_TABLE = {
35-
9,
36-
99,
37-
999,
38-
9999,
39-
99999,
40-
999999,
41-
9999999,
42-
99999999,
43-
999999999,
44-
Integer.MAX_VALUE };
45-
46-
// From https://lemire.me/blog/2021/05/28/computing-the-number-of-digits-of-an-integer-quickly/
47-
// and https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/9d4cd21d0a/2021/05/28/digitcount.java (license: public domain)
34+
// @formatter:off
35+
@CompilationFinal(dimensions = 1) private static final long[] LENGTH_TABLE = {
36+
0x100000000L, 0x1FFFFFFF6L, 0x1FFFFFFF6L,
37+
0x1FFFFFFF6L, 0x2FFFFFF9CL, 0x2FFFFFF9CL,
38+
0x2FFFFFF9CL, 0x3FFFFFC18L, 0x3FFFFFC18L,
39+
0x3FFFFFC18L, 0x4FFFFD8F0L, 0x4FFFFD8F0L,
40+
0x4FFFFD8F0L, 0x4FFFFD8F0L, 0x5FFFE7960L,
41+
0x5FFFE7960L, 0x5FFFE7960L, 0x6FFF0BDC0L,
42+
0x6FFF0BDC0L, 0x6FFF0BDC0L, 0x7FF676980L,
43+
0x7FF676980L, 0x7FF676980L, 0x7FF676980L,
44+
0x8FA0A1F00L, 0x8FA0A1F00L, 0x8FA0A1F00L,
45+
0x9C4653600L, 0x9C4653600L, 0x9C4653600L,
46+
0xA00000000L, 0xA00000000L
47+
};
48+
// @formatter:on
49+
50+
// From https://lemire.me/blog/2021/06/03/computing-the-number-of-digits-of-an-integer-even-faster/
51+
// and https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/4e6e171a7d/2021/06/03/digitcount.c (license: public domain)
4852
private static int length(int value) {
4953
final int sign;
5054
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, value < 0)) {
@@ -61,13 +65,8 @@ private static int length(int value) {
6165
}
6266

6367
final int bits = 31 - Integer.numberOfLeadingZeros(value | 1);
64-
int digits = ((9 * bits) >>> 5);
65-
66-
if (value > LENGTH_TABLE[digits]) {
67-
digits += 1;
68-
}
69-
70-
return sign + digits + 1;
68+
int digits = (int) ((value + LENGTH_TABLE[bits]) >>> 32);
69+
return sign + digits;
7170
}
7271

7372
@Override

0 commit comments

Comments
 (0)