diff -r 23cdb1f98069 -r ea8bf21980fa src/org/python/core/PyLong.java --- a/src/org/python/core/PyLong.java Mon Mar 18 21:06:33 2013 -0700 +++ b/src/org/python/core/PyLong.java Mon Mar 18 22:24:15 2013 -0700 @@ -39,6 +39,8 @@ private final BigInteger value; + private static final char[] LOOKUP = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + public BigInteger getValue() { return value; } @@ -994,12 +996,39 @@ @ExposedMethod(doc = BuiltinDocs.long___hex___doc) final PyString long___hex__() { - String s = getValue().toString(16); - if (s.startsWith("-")) { - return new PyString("-0x" + s.substring(1, s.length()) + "L"); - } else { - return new PyString("0x" + s + "L"); + /* + Issue 2013: + getValue() returns a BigInteger object reference, and BigInteger.toString(radix) is known to + take computationally expensive time to compute for large numbers. + */ + //String s = getValue().toString(16); + + BigInteger value = getValue(); + + // obvious shortcut + if (value.signum() == 0) + return new PyString("0x0L"); + + // we want to work in absolute numeric value (negative sign is added afterward) + String s = toHexString(getValue().abs().toByteArray()); + String prefix = value.signum() < 0 ? "-0x" : "0x"; + + return new PyString(prefix + s + "L"); + } + + final static String toHexString(byte[] input) { + if (input == null || input.length <= 0) + return null; + + char[] output = new char[input.length * 2]; + + for (int i = 0; i < input.length; i++) { + output[2*i] = LOOKUP[(input[i] >> 4) & 0x0F]; + output[2*i+1] = LOOKUP[input[i] & 0x0F]; } + + // before returning the char array as string, remove leading zeroes, but not the last one + return new String(output).replaceFirst("^0+(?!$)", ""); } @ExposedMethod(doc = BuiltinDocs.long___str___doc)