Annoying 32/64-bit inconsistency

K

kj

(NOTE: In the DB interactions below, I've rendered undef values as
(undef), even though in the real interaction DB would just print
a blank line. And, of course, the comments are my addition.)

On a 32-bit architecture:

DB<1> p ~0
4294967295
DB<2> p ~0 + 1
4294967296 # ~0 + 1 is stringified to an
# integer
DB<3> $x = sprintf '%s', ~0+1
DB<4> p $x
4294967296
DB<5> p $x > ~0 # numeric comparison correct,
1 # even though the integer
# represented by string $x is
# "too big" for 32 bits

DB<6> p $x == ~0 # ditto
(undef)




....but on a 64-bit architecture

DB<1> p ~0
18446744073709551615
DB<2> p ~0 + 1
1.84467440737096e+19 # first inconsistency: ~0 + 1
# stringified as a float
DB<3> $x = sprintf '%s', ~0 + 1
DB<4> p $x
1.84467440737096e+19
DB<5> $x = '18446744073709551616' # ...so we initialize $x explicitly
DB<6> p $x
18446744073709551616'
DB<8> p $x > ~0 # incorrect numeric comparison
(undef)
DB<9> p $x == ~0 # incorrect numeric comparison
1
DB<10> p $x == ~0 - ( ( 1 << 10 ) - 1 ) # incorrect numeric comparison
1
DB<11> p $x == ~0 - ( 1 << 10 ) # finally, this one is correct
(undef)
DB<12> $x = sprintf '%s', ~0

DB<13> p $x == ~0 # in contrast, all numeric
1 # comparisons with stringified ~0
# are OK
DB<14> p $x == ~0 - 1
(undef)




The 64-bit perl above was compiled with:

Platform:
osname=linux, osvers=2.6.15.7, archname=x86_64-linux-gnu-thread-multi
uname='linux crested 2.6.15.7 #1 smp sat jul 15 10:48:14 utc 2006 x86_64 gnulinux '
config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.8 -Dsitearch=/usr/local/lib/perl/5.8.8 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.8 -Dd_dosuid -des'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=define use64bitall=define uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O2',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include'
ccversion='', gccversion='4.1.2 (Ubuntu 4.1.2-0ubuntu4)', gccosandvers=''
intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
perllibs=-ldl -lm -lpthread -lc -lcrypt
libc=/lib/libc-2.5.so, so=so, useshrplib=true, libperl=libperl.so.5.8.8
gnulibc_version='2.5'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Characteristics of this binary (from libperl):
Compile-time options: MULTIPLICITY PERL_IMPLICIT_CONTEXT
PERL_MALLOC_WRAP THREADS_HAVE_PIDS USE_64_BIT_ALL
USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES
USE_PERLIO USE_REENTRANT_API
Built under linux




Is there any way I can modify these build parameters for 64-bit to
make perl handle the string containing the number ~0 + 1 in the
same way it does under 32-bit?

TIA!

kj
 
X

xhoster

kj said:
Is there any way I can modify these build parameters for 64-bit to
make perl handle the string containing the number ~0 + 1 in the
same way it does under 32-bit?

No, I don't think there is. 32 bits integers can be "promoted" to
64 bit "double", which can represent integers up to something like 1<<51
without losing of precision. 64 bit integers can't be promoted to doubles
without loss of precision: they have no place to go.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
kj
(NOTE: In the DB interactions below, I've rendered undef values as
(undef), even though in the real interaction DB would just print
a blank line. And, of course, the comments are my addition.)

To examine values under debugger, use `x' command.
DB<6> p $x == ~0 # ditto
(undef)

It is not.
Is there any way I can modify these build parameters for 64-bit to
make perl handle the string containing the number ~0 + 1 in the
same way it does under 32-bit?

You want NV to have more bits than IV. Use `long double' for NV, if
your compiler allows this.

Hope this helps,
Ilya
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,961
Messages
2,570,131
Members
46,689
Latest member
liammiller

Latest Threads

Top