On 11/24/2015 05:50 PM, Ulf wrote:
Hi,
Am 24.11.2015 um 12:07 schrieb Aleksey Shipilev:
Thanks for reviews, Ivan, John, Sherman and Paul!
I am pushing this change now.
I know, I'm late, but have you ever tried? :
static void getChars(int i, int index, byte[] buf) {
// int q, r; // superfluous
// int charPos = index; // superfluous
boolean negative = i < 0;
// Generate two digits per iteration // q and r are not
needed outside loop
for (int q, i = negative ? i : -i; <= -100; i = q) {
q = i / 100;
byte r = (byte)((q * 100 - i) & 0x7F);
// byte allows the compiler to use byte wide addressing
opcodes
// which have smaller footprint and are potentially faster
// .. & 0x7F may additionally save negative bound check
buf[(byte)(--index & 0x7F)] = DigitOnes[r];
buf[(byte)(--index & 0x7F)] = DigitTens[r];
...but index can be large and overflow byte range. Imagine concatenating
into a String with target length > 127 ...
}
// We know there are at most two digits left at this point.
byte q = (byte)i / 10;
buf[(byte)(--index & 0x7F)] = (byte)(q * 10 - i +'0');
// Whatever left is the remaining digit.
if (q < 0) {
buf[(byte)(--index & 0x7F)] = (byte)('0' - q);
}
if (negative) {
buf[(byte)(--index & 0x7F)] = (byte)'-';
}
}
Additionally may try this:
(saves some calculations, but adds array access, only 1 for more
frequent i < 10, otherwise 2)
// We know there are at most two digits left at this point.
byte r = (byte)(-i & 0x7F);
buf[(byte)(--index & 0x7F)] = DigitOnes[r];
// Whatever left is the remaining digit.
if (r >= 10) {
buf[(byte)(--index & 0x7F)] = DigitTens[r];
}
if (negative) {
buf[(byte)(--index & 0x7F)] = (byte)'-';
}
2)
The lookup tables DigitTens and DigitOnes are always used together.
Packing them in an one table can save us one array access for the
price of little arithmetic.
static final int[] TwoDigits = {
('0'<<16)+'0', ('0'<<16)+'1', ('0'<<16)+'2', ('0'<<16)+'3',
('0'<<16)+'4',
('0'<<16)+'5', ('0'<<16)+'6', ('0'<<16)+'7', ('0'<<16)+'8',
('0'<<16)+'9',
...
int twoDig = TwoDigits[r];
buf[--charPos] = (byte)twoDig;
buf[--charPos] = (byte)(twoDig >> 16);
...
This could be done faster if using 1 "Unsafe putChar/Short()" instead
2 buf[--charPos] + shift.
... and better use char/short[] to save footprint and the compiler
calculating the table offset with charPos<<1.
Alternatively use byte[] TwoDigits =
useInternalCompactByteArrayOfString("00010203040506070809....")
-Ulf