Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UInteger range inconsistencies #12

Open
unserializable opened this issue Feb 12, 2017 · 5 comments
Open

UInteger range inconsistencies #12

unserializable opened this issue Feb 12, 2017 · 5 comments

Comments

@unserializable
Copy link

Unsigned integer range handling has incorrectnesses / inconsistencies.

E.g. UInteger can be formed from integer -34 but not from long -34.

@Test
public void test_negative_uint_34il() {
    UInteger a = uint(-34);
    UInteger b = uint(-34L);
    assertTrue (a == b);
}

Reported error is Exception in thread "main" java.lang.NumberFormatException: Value is out of range : -34 for the b definition.

I would either expect both of the samples below to fail or succeed, but not act differently. What is the intent in this library? Shouldn't both these cases succeed, since -34 is a value that is representable in 32 bit signed integer?

@lukaseder
Copy link
Member

Thanks for reporting. Yes, that does look weird because you see two times the value -34. But the intention of the two constructors is quite different, in fact. as documented in the Javadoc.

  • uint(int) pretends the argument int value is really a primitive unsigned int and considers the most significant bit (holding the minus sign in 2s complement) as the 0x8000000 bit. In this case, -34 is 0xFFFFFFDE, which is the same as the unsigned integer value 4294967262
  • uint(long) takes the least significant 32 bits from the argument long value and treats that as an unsigned integer. In this case, -34 is simply out of range.

@lukaseder
Copy link
Member

... in other words, the behaviour is expected and consistent across all types, i.e. you'll find the same duality in ubyte(byte) vs ubyte(short) or ushort(short) vs. ushort(int) or ulong(long) vs. ulong(BigInteger)

@unserializable
Copy link
Author

Thanks for the quick reply, @lukaseder! My project javadocs from attached sources don't contain the references you quote. Is the jOOU version which documentation you are referring to available from Maven repositories?

But as you said the following:

uint(long) takes the least significant 32 bits from the argument long value and treats that as an unsigned integer. In this case, -34 is simply out of range

the long handling seems even more weird, as it would be always possible to take least significant 32 bits from the long and treat that them as unsigned integer. The results for anything that fits into 32-bit signed integer should be identical too. Illustrating with -34 again:

String longBitString = Long.toBinaryString(-34L);
String intBitString = Integer.toBinaryString(-34);
System.out.printf("%64s%n", longBitString);
System.out.printf("%64s%n", intBitString);

which shows that the last 32 bits of long -34 are the same as full 32 bits of int -34.

1111111111111111111111111111111111111111111111111111111111011110
                                11111111111111111111111111011110
                                ^                               

One can of course do the int cast to get the last 32-bits of the long and then make an uint out of it, but doesn't that kind of defeat the purpose of the uint(long) when one needs to use uint((int)-34L) anyway, to bypass the NumberFormatException? Actual usage in code is not using long constants of course, but variables of type long.

@lukaseder
Copy link
Member

The Javadoc is available here: https://www.jooq.org/products/jOOU/javadoc/latest ... And it should also be available from Maven Central.

@lukaseder lukaseder reopened this Feb 13, 2017
@lukaseder
Copy link
Member

Interesting comment, you're right of course. That could be a design goal. Currently, the most significant 32 bits are required to be all zero, but we don't have to require this in principle. It would lead to the obvious discussion about "clever convenience" vs. "failing early". And it would probably also complicate the ULong type.

But I'm willing to review this change request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants