JDK 8 code review request for initial unsigned integer arithmetic library support
Joe Darcy
joe.darcy at oracle.com
Wed Jan 18 05:41:35 UTC 2012
Hi Eamonn,
The body javadoc text of the two-argument parseUnsignedLong method does
state
620 * <p>An exception of type {@code NumberFormatException} is
621 * thrown if any of the following situations occurs:
622 * <ul>
623 * <li>The first argument is {@code null} or is a string of
624 * length zero.
...
However, it is true that the method does not have an explicit @throws
clause detailing this condition and that somewhat unconventionally an
NPE is *not* throw for an nonsensical null input. The behavior of the
one-argument version of parseUnsignedLong is defined in terms of the
two-argument version so strictly from a specification perspective, I
think the existing text is okay as-is even if suboptimal.
Thanks for the reviews,
-Joe
On 01/17/2012 09:08 PM, Eamonn McManus wrote:
> 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
> <mailto: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
> <http://cr.openjdk.java.net/%7Edarcy/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
>> <mailto: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/
>> <http://cr.openjdk.java.net/%7Edarcy/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