JDK 8 code review request for initial unsigned integer arithmetic library support

Eamonn McManus eamonn at mcmanus.net
Wed Jan 18 05:08:07 UTC 2012


Hi Joe,

That looks great to me (emcmanus). One thing I noticed is that the
behaviour is not explicitly specified when parseUnsignedLong is given a
null String reference. But I see that is also true of the existing
parseLong and valueOf(String) and decode(String), so perhaps there should
be a separate bug to update the spec there. The phrase "If the string
cannot be parsed as a long" does not cover this case as obviously as it
might.

Cheers,
Éamonn


On 17 January 2012 18:54, Joe Darcy <joe.darcy at oracle.com> wrote:

>  Hi Eamonn,
>
>
> On 01/15/2012 09:53 AM, Eamonn McManus wrote:
>
> It's great to see this!
>
>
> I agree :-)
>
> I've posted a revised webrev at
>
>     http://cr.openjdk.java.net/~darcy/4504839.2
>
> More detailed responses inline.
>
>
> The API looks reasonable to me.
>
>  > For the first cut, I've favored keeping the code straightforward over
> trickier but potentially faster algorithms.
>
>  The code looks clean and correct to me. But I think we could afford one
> or two cheap improvements to Long without diving into the full-blown
> Hacker's Delight algorithms:
>
>  In toUnsignedBigInteger(i) we could check whether i is nonnegative and
> use plain BigInteger.valueOf(i) in that case. Also, although the difference
> is sure to be unmeasurable, I think (int) (i >>> 32) would be better
> than (int) ((i >> 32) & 0xffffffff).
>
>
> Good points; changed.
>
>
>
>  In parseUnsignedLong, we can avoid using BigInteger by parsing all but
> the last digit as a positive number and then adding in that digit:
>      long first = parseLong(s.substring(0, len - 1), radix);
>     int second = Character.digit(s.charAt(len - 1), radix);
>     if (second < 0) {
>         throw new NumberFormatException("Bad digit at end of " + s);
>     }
>     long result = first * radix + second;
>     if (compareUnsigned(result, first) < 0) {
>         throw new NumberFormatException(String.format("String value %s
> exceeds " +
>                                                         "range of unsigned
> long.", s));
>     }
>  By my measurements this speeds up the parsing of random decimal unsigned
> longs by about 2.5 times. Changing the existing code to move the limit
> constant to a field or to test for overflow using bi.bitLength() instead
> still leaves it about twice as slow.
>
>
> Changed.
>
> Also from some off-list comments from Mike, I've modified the first
> sentence of the parseUnsignedLong methods to explicitly mention the "long"
> type; this is consistent with the phrasing of the signed parseLong methods
> in java.lang.Long.
>
>
>
>  In divideUnsigned, after eliminating negative divisors we could check
> whether the dividend is also nonnegative and use plain division in that
> case.
>
>
> Changed.
>
>
>
>  In remainderUnsigned, we could check whether both arguments are
> nonnegative and use plain % in that case, and we could also check whether
> the divisor is unsigned-less than the dividend, and return it directly in
> that case.
>
>
> Changed.
>
> I've also added test cases for the unsigned divide and remainder methods.
>
> Thanks again,
>
> -Joe
>
>
>
> Éamonn
>
>
> On 13 January 2012 21:26, Joe Darcy <joe.darcy at oracle.com> wrote:
>
>> Hello,
>>
>> Polishing up some work I've had *almost* done for a long time, please
>> review an initial take on providing library support for unsigned integer
>> arithmetic:
>>
>>    4504839 Java libraries should provide support for unsigned integer
>> arithmetic
>>    4215269 Some Integer.toHexString(int) results cannot be decoded back
>> to an int
>>    6322074 Converting integers to string as if unsigned
>>
>>    http://cr.openjdk.java.net/~darcy/4504839.1/
>>
>> For the first cut, I've favored keeping the code straightforward over
>> trickier but potentially faster algorithms.  Tests need to be written for
>> the unsigned divide and remainder methods, but otherwise the regression
>> tests are fairly extensive.
>>
>> To avoid the overhead of having to deal with boxed objects, the unsigned
>> functionality is implemented as static methods on Integer and Long, etc. as
>> opposed to introducing new types like UnsignedInteger and UnsignedLong.
>>
>> (This work is not meant to preclude other integer arithmetic enhancements
>> from going into JDK 8, such as add/subtract/multiply/divide methods that
>> throw exceptions on overflow.)
>>
>> Thanks,
>>
>> -Joe
>>
>>
>>
>
>



More information about the core-libs-dev mailing list