Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stringifying NaN and Inf depends on the underlying C library #10713

Closed
p5pRT opened this issue Oct 11, 2010 · 10 comments
Closed

Stringifying NaN and Inf depends on the underlying C library #10713

p5pRT opened this issue Oct 11, 2010 · 10 comments

Comments

@p5pRT
Copy link

p5pRT commented Oct 11, 2010

Migrated from rt.perl.org#78330 (status was 'resolved')

Searchable as RT78330$

@p5pRT
Copy link
Author

p5pRT commented Oct 11, 2010

From @rafl

This is a bug report for perl from rafl@​debian.org,
generated with the help of perlbug 1.39 running under perl 5.12.2.


[Please describe your issue here]

To stringify NVs containing NaN or Inf, the Gconvert macro is used. For most
platforms this macro just calls something like​:

  sprintf(buf, "%.*g", DBL_DIG, nv);

That leaves the formatting of the NV up to the C library perl is working
against.

As it happens, different C libraries have different ways of formatting Not A
Number and Infinity. On win32, for example, the above would output "1.#INF",
"-1.#INF", "1.#QNAN", and "-1.#IND", instead of "inf", "-inf", "nan", and
"-nan", which what most C libraries would produce.

So far Window's libc is the only one I've found to provide odd results for this,
but there's probably more.

I think the Perl programmer shouldn't have to care about the details of the C
library perl is running on, so I think the stringification of NaN and Inf should
be the same across platforms. Perl should use something like
isinf/isnan/fbclassify to detect the NaN and Inf special-cases and format them
as strings itself.

Attached will be a patch adding tests for this. I've also pushed a branch
containing that patch to smoke-me/nan_inf_str.

@p5pRT
Copy link
Author

p5pRT commented Oct 11, 2010

From @rafl

0001-Add-tests-for-stringifying-NaN-and-Inf.patch
From 7e7b870751068e26e2d984893c5d24689c41ab01 Mon Sep 17 00:00:00 2001
From: Florian Ragwitz <rafl@debian.org>
Date: Mon, 11 Oct 2010 06:30:41 +0200
Subject: [PATCH] Add tests for stringifying NaN and Inf

---
 t/base/num.t |   16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/t/base/num.t b/t/base/num.t
index fbeddc9..a2b084f 100644
--- a/t/base/num.t
+++ b/t/base/num.t
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..53\n";
+print "1..57\n";
 
 # First test whether the number stringification works okay.
 # (Testing with == would exercize the IV/NV part, not the PV.)
@@ -209,3 +209,17 @@ print $a eq "16702650"     ? "ok 52\n" : "not ok 52 # $a\n";
 
 $a = 0B1101; "$a";
 print $a eq "13"           ? "ok 53\n" : "not ok 53 # $a\n";
+
+# NaN and Inf
+
+$a = 9 ** 9 ** 9; "$a";
+print $a eq "inf" ? "ok 54\n" : "not ok 54 # $a\n";
+
+$a = -9 ** 9 ** 9; "$a";
+print $a eq "-inf" ? "ok 55\n" : "not ok 55 # $a\n";
+
+$a = -sin 9 ** 9 ** 9; "$a";
+print $a eq "nan" ? "ok 56\n" : "not ok 56 # $a\n";
+
+$a = sin 9 ** 9 ** 9; "$a";
+print $a eq "-nan" ? "ok 57\n" : "not ok 57 # $a\n";
-- 
1.7.1

@p5pRT
Copy link
Author

p5pRT commented Oct 11, 2010

From @rafl

This ticket is NOT about identical stringification of all NVs on all platforms
(win32, for example, formats 1e34 as 1e+034, instead of 1e+34, as most platforms
do, but that's OK as that's still the same value when using the string in
numeric context again), but only about the stringification of Not A Number and
Infinity.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.12.2:

Configured by rafl at Tue Sep  7 01:57:32 CEST 2010.

Summary of my perl5 (revision 5 version 12 subversion 2) configuration:
   
  Platform:
    osname=linux, osvers=2.6.36-rc2, archname=x86_64-linux-thread-multi
    uname='linux tardis 2.6.36-rc2 #3 smp thu aug 26 15:07:28 cest 2010 x86_64 gnulinux '
    config_args='-des -Dusedevel -DDEBUGGING -Dusethreads -Dmultiplicity -Uversiononly -Accflags=-Wall -Wextra -Doptimize=-g -O0 -ggdb3 -Dprefix=/home/rafl/.perl5122/'
    hint=recommended, useposix=true, d_sigaction=define
    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 -Wall -Wextra -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-g -O0 -ggdb3',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -Wall -Wextra -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.4.5 20100902 (prerelease)', 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 =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc -lgdbm_compat
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.11.2.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.11.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -g -O0 -ggdb3 -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.12.2:
    /home/rafl/.perl5122/lib/site_perl/5.12.2/x86_64-linux-thread-multi
    /home/rafl/.perl5122/lib/site_perl/5.12.2
    /home/rafl/.perl5122/lib/5.12.2/x86_64-linux-thread-multi
    /home/rafl/.perl5122/lib/5.12.2
    .


Environment for perl 5.12.2:
    HOME=/home/rafl
    LANG=C
    LANGUAGE (unset)
    LC_CTYPE=de_DE.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/rafl/.perl5122/bin:/home/rafl/.local/bin:/usr/lib/ccache:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
    PERL_BADLANG (unset)
    SHELL=zsh

@p5pRT
Copy link
Author

p5pRT commented Oct 12, 2010

From @doughera88

On Mon, 11 Oct 2010, Florian Ragwitz wrote​:

# New Ticket Created by Florian Ragwitz
# Please include the string​: [perl #78330]
# in the subject line of all future correspondence about this issue.
# <URL​: http​://rt.perl.org/rt3/Ticket/Display.html?id=78330 >

-----------------------------------------------------------------
[Please describe your issue here]

To stringify NVs containing NaN or Inf, the Gconvert macro is used. For most
platforms this macro just calls something like​:

sprintf(buf, "%.*g", DBL_DIG, nv);

That leaves the formatting of the NV up to the C library perl is working
against.

As it happens, different C libraries have different ways of formatting Not A
Number and Infinity. On win32, for example, the above would output "1.#INF",
"-1.#INF", "1.#QNAN", and "-1.#IND", instead of "inf", "-inf", "nan", and
"-nan", which what most C libraries would produce.

So far Window's libc is the only one I've found to provide odd results for this,
but there's probably more.

I think the Perl programmer shouldn't have to care about the details of the C
library perl is running on, so I think the stringification of NaN and Inf should
be the same across platforms. Perl should use something like
isinf/isnan/fbclassify to detect the NaN and Inf special-cases and format them
as strings itself.

On the flip side, I think a user shouldn't have to worry about the details
of what language a program is written in, so I think the stringification
of NaN and Inf should be the same across programs running on the same
platform.

On balance, I'm actually not sure which way I lean on this one; I'd like
to see some data on what scanf() and friends do on Windows and other
"non-conforming" platforms when fed in the proposed output strings.

--
  Andy Dougherty doughera@​lafayette.edu

@p5pRT
Copy link
Author

p5pRT commented Oct 12, 2010

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Oct 12, 2010

From @ikegami

On Tue, Oct 12, 2010 at 11​:21 AM, Andy Dougherty <doughera@​lafayette.edu>wrote​:

On the flip side, I think a user shouldn't have to worry about the details
of what language a program is written in, so I think the stringification
of NaN and Inf should be the same across programs running on the same
platform.

Does MinGW use MS's notation? There could very well be no such standard
format.

On balance, I'm actually not sure which way I lean on this one; I'd like
to see some data on what scanf() and friends do on Windows and other
"non-conforming" platforms when fed in the proposed output strings.

Gimme code, and I'll run it through MS's compiler.

- Eric Brine

@p5pRT
Copy link
Author

p5pRT commented Oct 12, 2010

From ambrus@math.bme.hu

On Tue, Oct 12, 2010 at 5​:21 PM, Andy Dougherty <doughera@​lafayette.edu> wrote​:

On Mon, 11 Oct 2010, Florian Ragwitz wrote​:

# <URL​: http​://rt.perl.org/rt3/Ticket/Display.html?id=78330 >

As it happens, different C libraries have different ways of formatting Not A
Number and Infinity. On win32, for example, the above would output "1.#INF",
"-1.#INF", "1.#QNAN", and "-1.#IND", instead of "inf", "-inf", "nan", and
"-nan", which what most C libraries would produce.

On the flip side, I think a user shouldn't have to worry about the details
of what language a program is written in, so I think the stringification
of NaN and Inf should be the same across programs running on the same
platform.

The C99 standard describes the format infinity and nan should be
printed by printf (but note that it allows either "inf" or
"infinity"), so I'd guess this is a case of working around a feature
in a C library, for which there are lots of precedents in perl.

Ambrus

@p5pRT
Copy link
Author

p5pRT commented Oct 12, 2010

From @sisyphus

----- Original Message -----
From​: "Andy Dougherty" <doughera@​lafayette.edu>

On balance, I'm actually not sure which way I lean on this one; I'd like
to see some data on what scanf() and friends do on Windows and other
"non-conforming" platforms when fed in the proposed output strings.

As regards the way that *perl* interprets the strings on Windows, it's a bit
all over the place.
On both StrawberryPerl 5.12.0 and ActivePerl 5.12.0 I get​:

##########################
C​:\>perl -we "print 'nan' + 0"
0
C​:\>perl -we "print 'nann' + 0"
Argument "nann" isn't numeric in addition (+) at -e line 1.
0
C​:\>perl -we "print 'inf' + 0"
0
C​:\>perl -we "print 'inff' + 0"
Argument "inff" isn't numeric in addition (+) at -e line 1.
0
C​:\>
#########################
Clearly, 'nan' and 'inf' are both recognised as numeric (in numeric
context), but are assigned zero.

On my own MinGW-built perl 5.12.0 (and 5.12.2, too) , all seems well​:

#########################
C​:\>perl -we "print 'nan' + 0"
-1.#IND
C​:\>perl -we "print 'nann' + 0"
Argument "nann" isn't numeric in addition (+) at -e line 1.
-1.#IND
C​:\>perl -we "print 'inf' + 0"
1.#INF
C​:\>perl -we "print 'inff' + 0"
Argument "inff" isn't numeric in addition (+) at -e line 1.
1.#INF
C​:\>
#########################

The difference between the 3 perls is, of course, the compiler that built
them.
ActivePerl use Visual Studio, StrawberryPerl use the 32-bit gcc-4.4.0 from
MinGW64, and I'm using MinGW32's gcc-3.4.5.

Even on perl 5.8.9 and 5.10.1 (but not 5.10.0, for some reason) MinGW32's
good ol' gcc-3.4.5 gets it right.

I do have a couple of x64 builds of perl 5.12 (built using MinGW64's
gcc-4.6.0) and they both provide the same "incorrect" output as
StrawberryPerl/ActivePerl.

Cheers,
Rob

@p5pRT
Copy link
Author

p5pRT commented Aug 15, 2016

From @cpansprout

This ticket is resolved, as perl now consistently uses NaN and Inf for stringification, as of 5.22.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 15, 2016

@cpansprout - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant