On Mon Jul 09 14:22:56 2012, BBYRD wrote:
Show quoted text> This is fixed in the latest version:
>
> >perl -MMath::BigInt -wle "print Math::BigInt -> new(3) -> blsft(1,1e20)"
> 300000000000000000000
>
> Please close this ticket.
This isn't what I see. On my Ubuntu 64-bit machine, Perl 5.6.2 produces '300000000000000000000' but every other version from 5.8.2 up through 5.19.5 produces -3. For 1e19 they produce "-6893488147419103232".
Even more interesting:
perl -MMath::BigInt=lib,Calc ... produces -3
perl -MMath::BigInt=lib,Pari ... produces 2.999999999999999999E20
perl -MMath::BigInt=lib,GMP ... produces 55340232221128654845
All but GMP produce the right answer if given Math::BigInt->new("1e20") as the argument. See below for more on GMP's behavior.
One solution is to change the objectify argument from 2 to 3, but that doesn't work if the shift amount is already an object. We really need to separately objectify $n. Calc's _new is calling length($n) directly, which returns 5 for 1e20. Oops -- that's why we screw up. I believe we really need to objectify the base if it is handed in (we can take the shortcuts of leaving it alone if not defined or some common base e.g. 2, 8, 10, 16).
The GMP backend reads the base with svUV, so that's a separate issue, but was probably done because the core code does not objectify the base. The underlying mpz_pow_ui call uses an mpz base and a UV shift amount so this is easy for the core shift code. However, from what I can tell, arguments that can be bigints must be objectified. So there is a compatibility issue.