Closed p5pRT closed 22 years ago
I can't remember if this $expletive pair of bugs ever got a bug number
1: 5.6.x pp.c has this comment:
do { double next = floor(adouble / 128); *--in = (unsigned char)(adouble - (next * 128)) | 0x80; if (in \<= buf) /* this cannot happen ;-) */ DIE(aTHX_ "Cannot compress integer"); in--; adouble = next; } while (adouble > 0);
er\, right\, for some value of cannot:
$ perl5.6.1-64-Os -le 'pack "w"\, ~0' Cannot compress integer at -e line 1.
Secondly\, it's an undocumented warning:
$ perl5.6.1-64-Os -Mdiagnostics -le 'print pack "w"\, ~0' Uncaught exception from user code: Cannot compress integer at -e line 1.
While the first is fixed in 5.8\, the second is not\, although it's harder to provoke:
perl5.9.0 -Mdiagnostics -le 'print length pack "w"\, 2**800' Uncaught exception from user code: Cannot compress integer at -e line 1.
perl5.6.1-64-Os -V is:
Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration: Platform: osname=freebsd\, osvers=4.5-stable\, archname=i386-freebsd-64int uname='freebsd thinking-cap.moo 4.5-stable freebsd 4.5-stable #1: wed feb 6 16:15:14 gmt 2002 nick@thinking-cap.moo:stuffusrsrcsyscompilethinkingcap i386 ' config_args='-e' hint=recommended\, useposix=true\, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef use64bitint=define use64bitall=undef uselongdouble=undef Compiler: cc='ccache gcc'\, ccflags ='-fno-strict-aliasing -I/usr/local/include'\, optimize='-Os'\, cppflags='-fno-strict-aliasing -I/usr/local/include' ccversion=''\, gccversion='2.95.3 20010315 (release) [FreeBSD]'\, gccosandvers='' intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=12345678 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12 ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8 alignbytes=4\, usemymalloc=n\, prototype=define Linker and Libraries: ld='ccache gcc'\, ldflags ='-Wl\,-E -L/usr/local/lib' libpth=/usr/lib /usr/local/lib libs=-lm -lc -lcrypt -lutil perllibs=-lm -lc -lcrypt -lutil libc=\, so=so\, useshrplib=false\, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags=' ' cccdlflags='-DPIC -fpic'\, lddlflags='-shared -L/usr/local/lib'
Characteristics of this binary (from libperl): Compile-time options: USE_64_BIT_INT USE_LARGE_FILES Built under freebsd Compiled at May 18 2002 14:48:12 @INC: /usr/local/lib/perl5/5.6.1/i386-freebsd-64int /usr/local/lib/perl5/5.6.1 /usr/local/lib/perl5/site_perl/5.6.1/i386-freebsd-64int /usr/local/lib/perl5/site_perl/5.6.1 /usr/local/lib/perl5/site_perl/5.005 /usr/local/lib/perl5/site_perl .
This is a bug report mainly to let off steam because I can't find a way to compare the bit pattern of all 64 bits of an integer on 5.6.1 built with 64 bits.
All large (20 decimal digit) strings get converted to integers via this code in 5.6.1's sv.c:
if (numtype & IS_NUMBER_NOT_IV) { /* May be not an integer. Need to cache NV if we cache IV * - otherwise future conversion to NV will be wrong. */ NV d;
d = Atof(SvPVX(sv));
if (SvTYPE(sv) \< SVt_PVNV) sv_upgrade(sv\, SVt_PVNV); SvNVX(sv) = d; (void)SvNOK_on(sv); (void)SvIOK_on(sv); #if defined(USE_LONG_DOUBLE) DEBUG_c(PerlIO_printf(Perl_debug_log\, "0x%"UVxf" 2nv(%" PERL_PRIgldbl ")\n"\, PTR2UV(sv)\, SvNVX(sv))); #else DEBUG_c(PerlIO_printf(Perl_debug_log\, "0x%"UVxf" 2nv(%g)\n"\, PTR2UV(sv)\, SvNVX(sv))); #endif if (SvNVX(sv) \< -0.5) { SvIVX(sv) = I_V(SvNVX(sv)); goto ret_zero; } else { SvUVX(sv) = U_V(SvNVX(sv)); SvIsUV_on(sv); }
which has just subjected it to an intermediate NV cast. ${expletive}\, as there go my low order bits. That code path is used even *inside* use integer;
And my last hope\, pack "w"\, which does decimal string arithmetic\, doesn't help me because of this:
perl5.6.1-64-Os -le 'pack "w"\, 18446744073709551615' Cannot compress integer at -e line 1.
(although if I write it as a string\, it works
perl5.6.1-64-Os -le 'pack "w"\, "18446744073709551615"' )
but then that doesn't solve my problems\, because I have negative numbers to compare\, and -1 isn't "-1":
perl -wle '$a = -1; $b = "-1"; print "$a "\,$a; print "$b "\,$b'
-1 4294967295
-1 -1
Who said ~~ was the scalar context operator? \
(remember\, I can't use numeric -\, as that forces a conversion via sv_2uv\, and sv_2uv is converting via floating point for some of the values I'm interested in)
Oops. That was a rant. use 5.8.0; # 64 bit stuff works
Nicholas Clark -- Even better than the real thing: http://nms-cgi.sourceforge.net/
On Sun\, Oct 06\, 2002 at 10:14:46PM -0000\, Nicholas Clark wrote:
Secondly\, it's an undocumented warning:
$ perl5.6.1-64-Os -Mdiagnostics -le 'print pack "w"\, ~0' Uncaught exception from user code: Cannot compress integer at -e line 1.
While the first is fixed in 5.8\, the second is not\, although it's harder to provoke:
perl5.9.0 -Mdiagnostics -le 'print length pack "w"\, 2**800' Uncaught exception from user code: Cannot compress integer at -e line 1.
Let's make that 3:
$ perl5.9.0 -Mdiagnostics -le 'print length pack "w"\, -1' Uncaught exception from user code: Cannot compress negative numbers at -e line 1. $ perl5.9.0 -Mdiagnostics -le 'print length pack "w"\, "11111111111e0"' Uncaught exception from user code: can compress only unsigned integer at -e line 1. $ perl5.9.0 -Mdiagnostics -le 'print length pack "w"\, 2**800' Uncaught exception from user code: Cannot compress integer at -e line 1.
There are two code paths that can croak with "can compress only unsigned integer" \, and I believe I'm hitting the first. I think I'd need a tied value to hit the second.
Appended patch makes it only possible to hit "cannot happen" (the third) for compressing Inf\, documents all three in perldiag.pod\, and changes the "can compress only unsigned integer" to "Can only compress unsigned integers" to be better English and capitalised consistently with all the other warnings in perldiag.pod (It's not documented. Why would anyone be depending on the exact wording)
For an IEEE double the buffer is 147 bytes. The calculation is a constant\, so the compiler's constant folding should get it right. I believe the calculation is optimally correct\, because the position of the croak() in the loop was wrong (it wasn't using 1 byte of the buffer) and before I fixed that I could croak it at 2**1022 and 2**1023.
Call me pointlessly obsessed\, but perl doesn't favour arbitrary limitations\, and having a 16 or so byte buffer is arbitrary\, particularly when I can calculate the longest buffer needed\, and that buffer is not excessively large. Even if it makes no sense to pass numbers that big to pack 'w' :-)
I believe my "alphabetical" ordering for perldiag is correct - it seems to be tr/A-Za-z/a-za-z/dc and then sort (case insensitive\, drop all non alphabetics)
(sorry\, I'm getting speed obsessed\, and that should be faster than a regexp)
Nicholas Clark -- Even better than the real thing: http://nms-cgi.sourceforge.net/
Nicholas Clark \nick@​unfortu\.net wrote: :Appended patch makes it only possible to hit "cannot happen" (the third) for :compressing Inf\, documents all three in perldiag.pod\, and changes the : "can compress only unsigned integer" to : "Can only compress unsigned integers" :to be better English and capitalised consistently with all the other warnings :in perldiag.pod
Thanks\, applied as #18010.
:(sorry\, I'm getting speed obsessed [...])
No apologies needed. :)
Hugo
On Sat\, Oct 12\, 2002 at 05:41:26PM +0100\, hv@crypt.org wrote:
Nicholas Clark \nick@​unfortu\.net wrote: :Appended patch makes it only possible to hit "cannot happen" (the third) for :compressing Inf\, documents all three in perldiag.pod\, and changes the : "can compress only unsigned integer" to : "Can only compress unsigned integers" :to be better English and capitalised consistently with all the other warnings :in perldiag.pod
Thanks\, applied as #18010.
Benjamin Goldberg observed that I failed to pass the number of tests to skip at one point.
Nicholas Clark -- Brainfuck better than perl? http://www.perl.org/advocacy/spoofathon/
Nicholas Clark wrote:
--- t/op/pack.t.orig Sun Oct 20 16:07:56 2002 +++ t/op/pack.t Sun Oct 27 20:10:35 2002
Thanks\, applied as #18069.
@@ -192\,7 +192\,7 @@ sub list_eq ($$) { # This should be about the biggest thing possible on an IEEE double my $big = eval '2**1023';
- skip "Couldn't generate 2**1023 - got error '$@'" + skip "Couldn't generate 2**1023 - got error '$@'"\, 3 unless defined $big and $big != $big / 2;
eval \{ $x = pack 'w'\, $big \};
Fixed\, patched\, resolved.
@jhi - Status changed from 'new' to 'resolved'
Migrated from rt.perl.org#17772 (status was 'resolved')
Searchable as RT17772$