Skip Menu |

This queue is for tickets about the List-MoreUtils CPAN distribution.

Report information
The Basics
Id: 93207
Status: resolved
Priority: 0/
Queue: List-MoreUtils

People
Owner: Nobody in particular
Requestors: DANAJ [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in:
  • 0.33
  • 0.400_001
Fixed in: 0.400_002



Subject: minmax truncates intermediates to double
minmax uses type 'double' to hold array values for comparison. This loses precision on 64-bit machines. E.g.: perl -MList::MoreUtils=minmax -E 'my @n = map { ~0-$_ } 0..10; say join " ", minmax(@n);' 18446744073709551615 18446744073709551615 When the type is changed to NV and run on a Perl with long doubles, we get: 18446744073709551605 18446744073709551615 as expected. List::Util min/max uses an NV, so with long doubles it gives the right answer: perl -MList::MoreUtils=minmax -MList::Util=min,max -E 'my @n = map { ~0-$_ } 0..10; say join " ", minmax(@n); say join " ", min(@n), max(@n)' 18446744073709551615 18446744073709551615 18446744073709551605 18446744073709551615 However this doesn't work on "normal" Perl builds which give the incorrect: perl -MList::MoreUtils=minmax -MList::Util=min,max -E 'my @n = map { ~0-$_ } 0..10; say join " ", minmax(@n); say join " ", min(@n), max(@n)' 18446744073709551615 18446744073709551615 18446744073709551615 18446744073709551605 However it does give the option of using objects (e.g. Math::BigInt, Math::GMPz, Math::GMP) to work around. Change to "my @n = map { Math::BigInt->new($_) } map { ~0-$_ } 0..10" for example, and min/max will work. Ideas: 1. Switch to NV, call it a day. 64-bit integer comparisons will be broken on most machines and we don't care. Let namby-pamby number theory people go use Python. 2. Do object comparisons when we see them like in List::Util. At least we can work around it. 3. Instead of putting everything in a NV, use SvIsUV etc. to keep IV/UV as IV/UV, so no data loss. This is complicated (especially when objects are thrown in) and one still has to solve the mixed cases (e.g. an array containing a mix of IV, UV, NV, objects) which may have no perfect answer.
How about porting the check from https://github.com/i-scream/Unix-Statgrab/blob/master/inc/Config/AutoConf/SG.pm#L113 to LMU? Would it fit the requirements? Cheers, Jens
On Fri Feb 21 07:06:49 2014, REHSACK wrote: Show quoted text
> How about porting the check from https://github.com/i-scream/Unix- > Statgrab/blob/master/inc/Config/AutoConf/SG.pm#L113 to LMU? Would it > fit the requirements?
I don't think so. More like Math::GMPz's code (among others). if (object / magic, do things like Scalar::Util) else if (SvUOK(asv)) { UV value is SvUV(asv) } else if (SvIOK(asv)) { IV value is SvIV(asv) } else if (SvNOK(asv)) { NV value is SvNV(asv) } else { string .. we could parse as UV, IV, or NV } That is, Perl already has flags that tell us what type the SV is. The current code ignores them and puts everything in a double. This is *way* easier than the many cases that come up from the above, and works just fine for inputs less than ~ 2^49 (or in the case of using NV with a Perl compiled with long doubles on a platform with 80+ bit long doubles, it works for all UV/IV/NVs).
Fixed (with test) in 0.400_002