Skip Menu |

This queue is for tickets about the Math-BigInt CPAN distribution.

Report information
The Basics
Id: 66450
Status: open
Priority: 0/
Queue: Math-BigInt

People
Owner: Nobody in particular
Requestors: peter.john.acklam [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 1.993
Fixed in: (no value)



Subject: Math::BigInt->blsft() can't handle arbitrarily large base
Math::BigInt->blsft() can't handle an arbitrarily large base: $ perl -MMath::BigInt -wle 'print Math::BigInt -> new(3) -> blsft(1,1e20)' -3 Math::BigFloat->blsft() gets it right: $ perl -MMath::BigFloat -wle 'print Math::BigFloat -> new(3) -> blsft(1,1e20)' 300000000000000000000 This bug appears in older versions than 1.993, but I haven't checked how long it has been present.
I am not sure if there is any point in adding support for an arbitrarily large base (and number of places to shift). Silenly giving the wrong result is no good either. The best thing is probably to given an error when the Perl scalar is so large that it might overflow.
This is fixed in the latest version: Show quoted text
>perl -MMath::BigInt -wle "print Math::BigInt -> new(3) -> blsft(1,1e20)"
300000000000000000000 Please close this ticket.
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.
In the next release I have done some modifications so that blsft() should work with bases up to the largest unsigned int. I have added this limitation since some libraries (e.g., GMP) can not handle arbitrarily large bases. The current version gives $ perl -Ilib -MMath::BigInt=lib,Pari -MMath::BigInt -wle 'print Math::BigInt -> new(3) -> blsft(1, 1e19)' 3.0000000000000000000E19 $ perl -Ilib -MMath::BigInt=lib,BitVect -MMath::BigInt -wle 'print Math::BigInt -> new(3) -> blsft(1, 1e19)' Bit::Vector::new_Dec(): input string syntax error at /usr/local/share/perl5/site_perl/5.26/Math/BigInt/BitVect.pm line 66. The new code gives the correct output 30000000000000000000.