-
Notifications
You must be signed in to change notification settings - Fork 0
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
Fix Bin/Hex parsing of BigInteger for powers of 2 #5
Fix Bin/Hex parsing of BigInteger for powers of 2 #5
Conversation
// Small value that fits in Int32. | ||
result = new BigInteger((int)leading); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the (int)leading == int.MinValue
condition and changed it to call new BigInteger(int)
.
It avoids allocation by using BigInteger.s_bnMinInt
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, I didn't realize that BigInteger(int)
constructor has an optimization to avoid the allocation for int.MinValue.
In previous commit I delegated to that constructor to handle MinValue. I'll update the comment.
Sorry, I didn't mention this was in my fork. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for pointing out my mistakes!
I'm going to think more about optimization and measure the performance of each case.
// Small value that fits in Int32. | ||
result = new BigInteger((int)leading); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, I didn't realize that BigInteger(int)
constructor has an optimization to avoid the allocation for int.MinValue.
In previous commit I delegated to that constructor to handle MinValue. I'll update the comment.
if ((int)signBits < 0) | ||
{ | ||
// Negative value | ||
result = leading == 0 | ||
? new BigInteger(-1, [leading, 1u]) | ||
: new BigInteger(-1, [unchecked((uint)-(int)leading)]); | ||
} | ||
else | ||
{ | ||
// Positive value | ||
result = new BigInteger(1, [leading]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed that the bits of negative result needs negation here.
The non-zero case for negative and positive can be combined in bit hack: leading ^ signBits - signBits
. The zero case needs [0, 1]
.
Span<uint> trimmed = new Span<uint>(bits).TrimStart(0u); | ||
if (trimmed.Length == 0) | ||
{ | ||
bits = new uint[bits.Length + 1]; | ||
bits[^1] = 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A new digit is required only if all the trailing digits are zero.
It's really a headache for allocation management.
dotnet#95543 (comment)
I fixed Bin/Hex parsing of BigInteger for powers of 2.