I have two simple functions where performance is critical, one for encoding an array of int
s to a long, another for doing the opposite (decoding the long back to an array of int
s).
The solutions I have come up with below are fairly fast. Can these be made even faster?
Please note: I am constrained by using the same function signatures.
public static final long encode(int[] digits) {
return
1000000000000000000L * digits[0]
+ 100000000000000000L * digits[1]
+ 10000000000000000L * digits[2]
+ 1000000000000000L * digits[3]
+ 100000000000000L * digits[4]
+ 10000000000000L * digits[5]
+ 1000000000000L * digits[6]
+ 100000000000L * digits[7]
+ 10000000000L * digits[8]
+ 1000000000L * digits[9]
+ 100000000L * digits[10]
+ 10000000L * digits[11]
+ 1000000L * digits[12]
+ 100000L * digits[13]
+ 10000L * digits[14]
+ 1000L * digits[15]
+ 100L * digits[16]
+ 10L * digits[17]
+ 1L * digits[18];
}
public static final int[] decode(long move) {
int[] digits = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int index = digits.length - 1;
while(move > 0) {
digits[index--] = (int)(move % 10);
move = move / 10;
}
return digits;
}
These are used for persisting a Chess move in a simple engine, for example:
//=========================================================================
// MOVE INFO
//=========================================================================
public static final int MOVE_INFO_COUNT = 19;
public static final int MOVE_INFO_EXTRA_1 = 0; // -> ACTIVE DIGIT IS ALWAYS 1
public static final int MOVE_INFO_EXTRA_2 = 1; // -> UNUSED (0)
public static final int MOVE_INFO_EXTRA_3 = 2; // -> UNUSED (0)
public static final int MOVE_INFO_PLAYER = 3; // -> PLAYER CONSTANTS (0 - 1)
public static final int MOVE_INFO_MOVE_TYPE = 4; // -> MOVE-TYPE CONSTANTS (0 - 8)
public static final int MOVE_INFO_MOVED_PIECE = 5; // -> PIECE CONSTANTS (0 - 6)
public static final int MOVE_INFO_SOURCE_ROW = 6; // -> RANK (0 - 7) OR 9 = NOT APPLICABLE
public static final int MOVE_INFO_SOURCE_COL = 7; // -> FILE (0 - 7) OR 9 = NOT APPLICABLE
public static final int MOVE_INFO_TARGET_ROW = 8; // -> RANK (0 - 7) OR 9 = NOT APPLICABLE
public static final int MOVE_INFO_TARGET_COL = 9; // -> FILE (0 - 7) OR 9 = NOT APPLICABLE
public static final int MOVE_INFO_CAPTURED_PIECE = 10; // -> PIECE CONSTANTS (0 - 6)
public static final int MOVE_INFO_EN_PASSANT_ROW = 11; // -> RANK (0 - 7) OR 9 = NOT APPLICABLE
public static final int MOVE_INFO_EN_PASSANT_COL = 12; // -> FILE (0 - 7) OR 9 = NOT APPLICABLE
public static final int MOVE_INFO_PREVIOUS_EN_PASSANT_ROW = 13; // -> RANK (0 - 7) OR 9 = NOT APPLICABLE
public static final int MOVE_INFO_PREVIOUS_EN_PASSANT_COL = 14; // -> FILE (0 - 7) OR 9 = NOT APPLICABLE
public static final int MOVE_INFO_WHITE_CASTLING_RIGHTS = 15; // -> CASTLING-RIGHTS CONSTANTS (0 - 3)
public static final int MOVE_INFO_BLACK_CASTLING_RIGHTS = 16; // -> CASTLING-RIGHTS CONSTANTS (0 - 3)
public static final int MOVE_INFO_PREVIOUS_WHITE_CASTLING_RIGHTS = 17; // -> CASTLING-RIGHTS CONSTANTS (0 - 3)
public static final int MOVE_INFO_PREVIOUS_BLACK_CASTLING_RIGHTS = 18; // -> CASTLING-RIGHTS CONSTANTS (0 - 3)
import com.chess.engine.Move;
public class DEBUG_ENCODE_DECODE {
private static final void benchmark(long iterations) {
long start = System.currentTimeMillis();
long counter = 0;
for(long i = 0L; i < iterations; i++) {
work();
counter++;
}
long end = System.currentTimeMillis();
System.out.println(counter +" ITERATIONS IN MILLISECONDS: " + (end - start));
}
private static final void work() {
long move = 1000432101234567890L;
if(Move.encodeMove(Move.decodeMove(move)) != move) {
throw new RuntimeException("ENCODE DECODE FAILED");
}
}
public static void main(String[] args) {
benchmark(100000000);
}
}
0
char. – Marko Topolnik Jul 10 '15 at 14:16decode
method, the MOD and DIV instructions are most probably the bottleneck. – Marko Topolnik Jul 10 '15 at 14:17