develooper Front page | perl.perl5.porters | Postings from May 2008

Re: [perl #54590] "Can't take log of 0" error in perl 5.8.8. 64 bit

From:
Tom Christiansen
Date:
May 22, 2008 11:46
Subject:
Re: [perl #54590] "Can't take log of 0" error in perl 5.8.8. 64 bit
Message ID:
29721.1211481961@chthon
Scripsit hodie, XI Kalendas Iunias MMDCCLXI AUC, circa horam quartam 
mediamque post meridiem (tempus Romae), Abigail <abigail@abigail.be>:

> On Wed, May 21, 2008 at 10:14:48AM -0700, Lourdes Peña Castillo wrote:

>> # New Ticket Created by  "Lourdes Peña Castillo"
>> # Please include the string:  [perl #54590]
>> # in the subject line of all future correspondence about this issue.
>> # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=3D54590 >

>> Hi,

>> If I run the following code in perl v5.8.8 built for x86_64-linux-
>> thread-multi, I get the error "Can't take log of 0 at - line 1."

>> perl
>> print log(2.5e-310)/log(10);

>> But if I run it in perl v5.8.7 built for i486-linux-gnu-thread-multi, 
>> I get

>> Is this a known issue with perl 5.8.8. for 64bits? Thanks!

[... now enter Abigail ...]

> I see a difference depending on whether Perl was build using 64 bit
> integers or not, I get the error when running with 32 bit build, and
> -309.602059991327962 when running with a 64 bit build. The version
> (5.8.7, 5.8.8, 5.10.0) doesn't matter, nor does it matter whether it
> was built with threads or not.

> It seems that in a 32-bit build, 2.5e-310 gets constant folded to 0.

Abigail and Lourdes,

I get slightly mixed results depending on version, configuration, and
platform (software+hardware).  Here're the five different boxes and the
respective perl versions I tested under each box.  Amongst perl5 tests, 
I see the log 0 failure occurring uniquely on the last of these alone:

    Box  vperl      details

    A   v5.8.8      cygwin-thread-multi-64int

    B   v5.6.0      i686-linux-thread
	v5.10.0     i686-linux-thread-multi-64int

    C   5.005_02    OpenBSD.i386-openbsd
	5.005_03    OpenBSD.i386-openbsd
	5.005_54    OpenBSD.i386-openbsd
	v5.6.0      OpenBSD.i386-openbsd-thread
	v5.8.7      OpenBSD.i386-openbsd
	v5.10.0     0penBSD.i386-openbsd-thread-multi-64int

    D   v5.8.8      OpenBSD.i386-openbsd
	v5.10.0     OpenBSD.i386-openbsd

    E   v5.6.0      OpenBSD.sparc-openbsd
	v5.10.0     OpenBSD.sparc-openbsd    <- Can't take log of 0 

On all of these EXCEPT FOR THE VERY LAST-MOST ENTRY ALONE, 
I universally get 

    -309.602059991328

Although admittedly when on machine C, I run 

    boxC% perl1 -e 'print log(2.5e-310)/log(10), "\n";'
    -309.60205999132796251

or

    boxC% perl4.036 -e 'print log(2.5e-310)/log(10), "\n";'
    -309.60205999132796251

I do get more digits.  But they're there anyway, since

    boxC% perl5.10.0 -e 'printf "%.45f\n", log ( 2.5e-310 ) /log ( 10 ) '
    -309.602059991327962507057236507534980773925781250

No, the different response of not being able to take the log of 0 occurs
only on that fifth machine, the sparc, *but* it occurs only with 5.10.0,
*not* 5.6.0--and, somewhat curiously, it is a run-time exception, too:

    boxE% perl5.6.0 -le 'print log ( 2.5e-310 ) /log( 10 ) '
    -309.60205999132796251

    boxE% perl5.10.0 -le 'print log ( 2.5e-310 ) /log( 10 ) '
    Can't take log of 0 at -e line 1.
    Exit 255

    boxE% perl5.10.0 -cw -le 'print log ( 2.5e-310 ) /log( 10 ) '
    -e syntax OK

Whereas in older Perl, it was usually a compile-time error.  

We can use 1/0 to show that this was always the case until 
the lastmost release; that is, up until 5.10.0.

Although I see that it runs just fine under original perl, 
(ie, perl1) which had the curious behaviour of producing 
an Inf--and exiting 0! (O *how* I do so *love* venerably 
retrotesting code with perl1! :-)

    boxC% perl1 -e 'print 1/0, "\n";'
    Inf

But later than that, we get an exception during compilation
due to constant-folding:

    boxC% perl4.036 -cw -le 'print 1/0'
    Illegal division by constant zero in file /tmp/perl-eY11150 at line 2, next char ;
    /tmp/perl-eY11150 had compilation errors.
    Exit 2

    boxC% perl5.00503 -cw -le 'print 1/0'
    Illegal division by zero at -e line 1.
    Exit 255

    boxC% perl5.8.7 -cw -le 'print 1/0'
    Illegal division by zero at -e line 1.
    Exit 255

Yet today, this is different--depending.  Whatever happened to 
constant-folding at compile-time? Oh right! No exceptions there 
any longer; I'd forgotten that particular delta entry.

    boxC% perl5.10.0 -cw -le 'print 1/0'
    -e syntax OK

    boxC% perl5.10.0     -le 'print 1/0'
    Illegal division by zero at -e line 1.
    Exit 19

Curious range of exit status, though, eh?  19?  Why 19?

That seems to make no sense as a sysexit, a signo, nor 
an errno--yet I should presume it but a malinging errno, 
though; wouldn't you?

It's certainly not a sysexit per sysexit.h at all (they're >64), 
which, rather lamentably, nobody much uses.  See <sysexit.h>:

  EX_OK EX_CANTCREAT EX_CONFIG EX_DATAERR EX_IOERR EX_NOHOST
  EX_NOINPUT EX_NOPERM EX_NOUSER EX_OSERR EX_OSFILE EX_PROTOCOL
  EX_SOFTWARE EX_TEMPFAIL EX_UNAVAILABLE EX_USAGE 

Now, if it were 128..255, that then I thiknk would be a signal in 
the high byte.  And signal 19 is SIGCONT, the now-unused SIGFPE, 
only 8.  But it's not, so I think it an errno.  Don't you?

Digging through docs on die() to figure out what happened suggests
die() seems to have taken some errno that was just sitting around 
and used that.  But errno 19 is ENODEV.  

The CRT (=libc startup) often leaves this value lying about, perhaps 
from a failed isatty(3).  *But* when it leaves the errno lying about, 
*you* end up lying about what was lying about; that is, about what 
really occurrred, so to speak. :-)

Now I ask you, is this behaviour all of: reasonable and expected, 
understandable and predictable, *and* desirable?

FTR, my own current answer to that question happens to be "hmm".

--tom



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About