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

DBL_MAX (and the like) not parsed #15781

Open
p5pRT opened this issue Dec 28, 2016 · 12 comments
Open

DBL_MAX (and the like) not parsed #15781

p5pRT opened this issue Dec 28, 2016 · 12 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 28, 2016

Migrated from rt.perl.org#130423 (status was 'open')

Searchable as RT130423$

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2016

From @jhi

Problem​: Perl doesn't parse the decimal expansion of DBL_MAX at all.

The example code shows to different wrong ways, and one correct
result. (Apologies for the bad wrapping, plain email is not
the best format for long lines or code, see the attachments.)

$x1 =
'179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000';
$y1 = sprintf("%f", $x1);
$y2 = sprintf("%f", eval
'179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000');
chomp(my $e2 = $@​);
use POSIX 'DBL_MAX';
$y3 = sprintf("%f", DBL_MAX);
print "y1 = $y1\n";
print "y2 = $y2 ($e2)\n";
print "y3 = $y3\n";

Output (from the 5.25.6 I have installed, but blead is no different)​:

y1 = Inf
y2 = 0.000000 (Number too long at (eval 3) line 1.)
y3 =
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000

You can remove the eval wrapping from $y2 to get the parse to die
immediately.

The above form of DBL_MAX is the IEEE 754 double precision (64-bit)
maximum. There can be others​: the 80-bit x86-style "uselongdouble"
maximum (LDBL_MAX) or the 128-bit IEEE-754 quadruple precision
(which may or may not be "uselongdouble", it may be the native
format/format chosen with the C compiler).

Both of these formats would require close to 5000 decimal digits in the
full expansion, having such a large statically allocated token buffer
would probably not be the best idea. (There is even octuple precision
defined in the IEEE-754, though I haven't heard of implementations.)

[Note​: I tried sending this earlier, but I think my local outgoing mail
queue is not really outgoing]

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2016

From @jhi

dblmax.pl

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2016

From @jhi

y1 = Inf
y2 = 0.000000 (Number too long at (eval 3) line 1.)
y3 = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2016

From @jhi

Summary of my perl5 (revision 5 version 25 subversion 6) configuration​:
 
  Platform​:
  osname=darwin
  osvers=15.6.0
  archname=darwin-2level
  uname='darwin vredefort2.local 15.6.0 darwin kernel version 15.6.0​: thu sep 1 15​:01​:16 pdt 2016; root​:xnu-3248.60.11~2release_x86_64 x86_64 '
  config_args='-des -Dusedevel -Uversiononly -Dprefix=/opt/local/perl-5.25.6'
  hint=recommended
  useposix=true
  d_sigaction=define
  useithreads=undef
  usemultiplicity=undef
  use64bitint=define
  use64bitall=define
  uselongdouble=undef
  usemymalloc=n
  bincompat5005=undef
  Compiler​:
  cc='cc'
  ccflags ='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.11 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -I/opt/local/include -DPERL_USE_SAFE_PUTENV'
  optimize='-O3'
  cppflags='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.11 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -I/opt/local/include'
  ccversion=''
  gccversion='4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.1.76)'
  gccosandvers=''
  intsize=4
  longsize=8
  ptrsize=8
  doublesize=8
  byteorder=12345678
  doublekind=3
  d_longlong=define
  longlongsize=8
  d_longdbl=define
  longdblsize=16
  longdblkind=3
  ivtype='long'
  ivsize=8
  nvtype='double'
  nvsize=8
  Off_t='off_t'
  lseeksize=8
  alignbytes=8
  prototype=define
  Linker and Libraries​:
  ld='cc'
  ldflags =' -mmacosx-version-min=10.11 -fstack-protector-strong -L/usr/local/lib -L/opt/local/lib'
  libpth=/usr/local/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.0/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib /usr/lib /opt/local/lib
  libs=-lpthread -lgdbm -ldbm -ldl -lm -lutil -lc
  perllibs=-lpthread -ldl -lm -lutil -lc
  libc=
  so=dylib
  useshrplib=false
  libperl=libperl.a
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs
  dlext=bundle
  d_dlsymun=undef
  ccdlflags=' '
  cccdlflags=' '
  lddlflags=' -mmacosx-version-min=10.11 -bundle -undefined dynamic_lookup -L/usr/local/lib -L/opt/local/lib -fstack-protector-strong'

Characteristics of this binary (from libperl)​:
  Compile-time options​:
  HAS_TIMES
  PERLIO_LAYERS
  PERL_COPY_ON_WRITE
  PERL_DONT_CREATE_GVSV
  PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
  PERL_MALLOC_WRAP
  PERL_OP_PARENT
  PERL_PRESERVE_IVUV
  PERL_USE_DEVEL
  PERL_USE_SAFE_PUTENV
  USE_64_BIT_ALL
  USE_64_BIT_INT
  USE_LARGE_FILES
  USE_LOCALE
  USE_LOCALE_COLLATE
  USE_LOCALE_CTYPE
  USE_LOCALE_NUMERIC
  USE_LOCALE_TIME
  USE_PERLIO
  USE_PERL_ATOF
  Built under darwin
  Compiled at Nov 20 2016 20​:10​:36
  @​INC​:
  /opt/local/perl-5.25.6/lib/site_perl/5.25.6/darwin-2level
  /opt/local/perl-5.25.6/lib/site_perl/5.25.6
  /opt/local/perl-5.25.6/lib/5.25.6/darwin-2level
  /opt/local/perl-5.25.6/lib/5.25.6
  .

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2016

From @sisyphus

-----Original Message-----
From​: Jarkko Hietaniemi (via RT)
Sent​: Thursday, December 29, 2016 1​:48 AM
To​: bugs-bitbucket@​rt.perl.org
Subject​: [perl #130423] DBL_MAX (and the like) not parsed

Output (from the 5.25.6 I have installed, but blead is no different)​:

y1 = Inf
y2 = 0.000000 (Number too long at (eval 3) line 1.)
y3 =
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000

FWIW, on Windows (perl-5.25.7, MSWin32-x64-multi-thread) y1 and y2 are the
same as above, but y3 differs​:

y1 = Inf
y2 = 0.000000 (Number too long at (eval 3) line 1.)
y3 =
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000

Cheers,
Rob

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2016

From @jhi

On Wednesday-201612-28 18​:23, Sisyphus via RT wrote​:

-----Original Message-----
From​: Jarkko Hietaniemi (via RT)
Sent​: Thursday, December 29, 2016 1​:48 AM
To​: bugs-bitbucket@​rt.perl.org
Subject​: [perl #130423] DBL_MAX (and the like) not parsed

Output (from the 5.25.6 I have installed, but blead is no different)​:

y1 = Inf
y2 = 0.000000 (Number too long at (eval 3) line 1.)
y3 =
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000

FWIW, on Windows (perl-5.25.7, MSWin32-x64-multi-thread) y1 and y2 are the
same as above, but y3 differs​:

y1 = Inf
y2 = 0.000000 (Number too long at (eval 3) line 1.)
y3 =
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000

Oh, goodie. Well, at least getting the yn to agree would be a start.

Cheers,
Rob

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2016

From zefram@fysh.org

sisyphus1@​optusnet.com.au wrote​:

FWIW, on Windows (perl-5.25.7, MSWin32-x64-multi-thread) y1 and y2 are the
same as above, but y3 differs​:
...
y3 =
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000

That's fucked up. Looks like it's libc's fault​: sprintf() using a
crap algorithm, converting to decimal with a fixed precision and then
expanding that to the output precision, rather than actually converting
to the output precision. Arguably we should implement our own float
formatter to avoid this sort of problem.

But anyway, that's unrelated to the input problem with which this ticket
is concerned. Open a separate ticket if you want to pursue it.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2016

From @sisyphus

-----Original Message-----
From​: Zefram
Sent​: Thursday, December 29, 2016 4​:07 PM
To​: perl5-porters@​perl.org
Subject​: Re​: [perl #130423] DBL_MAX (and the like) not parsed

sisyphus1@​optusnet.com.au wrote​:

FWIW, on Windows (perl-5.25.7, MSWin32-x64-multi-thread) y1 and y2 are
the
same as above, but y3 differs​:
...
y3 =
179769313486231570000...0000.000000

That's fucked up. Looks like it's libc's fault

Agreed.
There's no such issue with "long double" mingw builds.

In win32/GNUMakefile we have​:

ifeq ($(USE_LONG_DOUBLE),define)
BUILDOPT += -D__USE_MINGW_ANSI_STDIO
MINIBUILDOPT += -D__USE_MINGW_ANSI_STDIO
endif

I think there's a good chance that *unconditionally*
adding -D__USE_MINGW_ANSI_STDIO to both BUILDOPT and MINIBUILDOPT will fix
that problem with the "double" builds.

But anyway, that's unrelated to the input problem with which this ticket
is concerned. Open a separate ticket if you want to pursue it.

Shall do. (I'll do some testing first - in case there turns out to be more
to it.)

Cheers,
Rob

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2016

From @jhi

On Wed, 28 Dec 2016 21​:07​:53 -0800, zefram@​fysh.org wrote​:

sisyphus1@​optusnet.com.au wrote​:

FWIW, on Windows (perl-5.25.7, MSWin32-x64-multi-thread) y1 and y2
are the
same as above, but y3 differs​:
...
y3 =
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000

That's fucked up. Looks like it's libc's fault​: sprintf() using a
crap algorithm, converting to decimal with a fixed precision and then
expanding that to the output precision, rather than actually
converting
to the output precision. Arguably we should implement our own float
formatter to avoid this sort of problem.

I have a ticket open on using the netlib dtoa​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=122482
But am severely tuit-shortaged.

FWIW I tried adding

$x2 = '0x1.fffffffffffffp+1023';
$y4 = sprintf("%f", eval $x2);
$y5 = sprintf("%f", 0x1.fffffffffffffp+1023);
$y6 = sprintf("%a", DBL_MAX);
print "y4 = $y4\n";
print "y5 = $y5\n";
print "y6 = $y6\n";

and got

y4 = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
y5 = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
y6 = 0x1.fffffffffffffp+1023

which seems to indicate that the parsing of hexfp literals and the %a are okay (yay me).

But anyway, that's unrelated to the input problem with which this
ticket
is concerned. Open a separate ticket if you want to pursue it.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2016

From @sisyphus

-----Original Message-----
From​: Jarkko Hietaniemi (via RT)
Sent​: Thursday, December 29, 2016 1​:48 AM
To​: bugs-bitbucket@​rt.perl.org
Subject​: [perl #130423] DBL_MAX (and the like) not parsed

...

y1 = Inf

This could simply be that well known "off by one ulp" bug that afflicts
perl, couldn't it ?

Cheers,
Rob

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2016

From @jhi

On Thursday-201612-29 17​:01, Sisyphus via RT wrote​:

-----Original Message-----
From​: Jarkko Hietaniemi (via RT)
Sent​: Thursday, December 29, 2016 1​:48 AM
To​: bugs-bitbucket@​rt.perl.org
Subject​: [perl #130423] DBL_MAX (and the like) not parsed

...

y1 = Inf

This could simply be that well known "off by one ulp" bug that afflicts
perl, couldn't it ?

Possibly. Could be. I've purposefully avoided looking at that problem
because I'd rather spend time getting the gdtoa integrated than try fix
whatever homegrown we have now.

Cheers,
Rob

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

No branches or pull requests

2 participants