Re: When 1e-298L != 1e-298L
by BrowserUk (Patriarch) on Oct 24, 2013 at 14:23 UTC
|
unpack "b64", pack "D", 1e-298;
I suspect - but cannot verify as MSC maps long double to double -- that (a part of) the problem is the way you are inspecting the values.
On intel, gcc maps long double to an 80-bit floating point number -- though it may store it in either 12- or 16-bytes for alignment -- and you are only inspecting 64-bits of that 80-bit value.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
Re: When 1e-298L != 1e-298L
by kcott (Archbishop) on Oct 24, 2013 at 14:41 UTC
|
G'day Rob,
I don't have an explanation.
For what it's worth, here's the output from running your code under v5.18.1 (darwin):
Here's my full perl -V:
$ perl -V
Summary of my perl5 (revision 5 version 18 subversion 1) configuration
+:
Platform:
osname=darwin, osvers=11.4.2, archname=darwin-thread-multi-2level
uname='darwin ganymede 11.4.2 darwin kernel version 11.4.2: thu au
+g 23 16:25:48 pdt 2012; root:xnu-1699.32.7~1release_x86_64 x86_64 '
config_args='-de -Dprefix=/Users/ken/perl5/perlbrew/perls/perl-5.1
+8.1t -Dusethreads'
hint=recommended, useposix=true, d_sigaction=define
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=und
+ef
use64bitint=define, use64bitall=define, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-fno-common -DPERL_DARWIN -fno-strict-aliasing
+-pipe -fstack-protector -I/usr/local/include -I/opt/local/include',
optimize='-O3',
cppflags='-fno-common -DPERL_DARWIN -fno-strict-aliasing -pipe -fs
+tack-protector -I/usr/local/include -I/opt/local/include'
ccversion='', gccversion='4.2.1 (Based on Apple Inc. build 5658) (
+LLVM build 2336.1.00)', gccosandvers=''
intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1
+6
ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
+ lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries:
ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-prot
+ector -L/usr/local/lib -L/opt/local/lib'
libpth=/usr/local/lib /opt/local/lib /usr/lib
libs=-lgdbm -ldbm -ldl -lm -lutil -lc
perllibs=-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=' -bundle -undefined dynamic_lookup -L/u
+sr/local/lib -L/opt/local/lib -fstack-protector'
Characteristics of this binary (from libperl):
Compile-time options: HAS_TIMES MULTIPLICITY PERLIO_LAYERS
PERL_DONT_CREATE_GVSV
PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP
PERL_PRESERVE_IVUV PERL_SAWAMPERSAND USE_64_BI
+T_ALL
USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES
USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE
USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF
USE_REENTRANT_API
Built under darwin
Compiled at Aug 28 2013 15:25:59
%ENV:
PERL5LIB="/Users/ken/local/lib/perl"
PERLBREW_BASHRC_VERSION="0.30"
PERLBREW_HOME="/Users/ken/.perlbrew"
PERLBREW_PATH="/Users/ken/perl5/perlbrew/bin:/Users/ken/perl5/perl
+brew/perls/perl-5.18.1t/bin"
PERLBREW_PERL="perl-5.18.1t"
PERLBREW_ROOT="/Users/ken/perl5/perlbrew"
PERLBREW_VERSION="0.30"
@INC:
/Users/ken/local/lib/perl
/Users/ken/perl5/perlbrew/perls/perl-5.18.1t/lib/site_perl/5.18.1/
+darwin-thread-multi-2level
/Users/ken/perl5/perlbrew/perls/perl-5.18.1t/lib/site_perl/5.18.1
/Users/ken/perl5/perlbrew/perls/perl-5.18.1t/lib/5.18.1/darwin-thr
+ead-multi-2level
/Users/ken/perl5/perlbrew/perls/perl-5.18.1t/lib/5.18.1
.
| [reply] [d/l] [select] |
|
|
Interesting that there's also a discrepancy with 1e-298 on perl's (such as yours) whose nvtype is 'double'. When I check on my 'double' build of perl 5.18.0, I also find a discrepancy. The script I originally posted is not properly portable to 'double' builds of perl. This rendition of the script should work as intended for both nvtypes:
#!perl -l
use warnings;
use strict;
use Config;
use Inline C => Config =>
USING => 'ParseRegExp',
BUILD_NOISY => 1;
use Inline C => <<'EOC';
SV * get_problem_val(long nvsize) {
if(nvsize == 8) return newSVnv(1e-298);
return newSVnv(1e-298L);
}
EOC
my $s = $Config{nvsize};
print "\n\$Config{nvtype}: $Config{nvtype}";
print "Different values" if 1e-298 != get_problem_val($s);
if($Config{nvsize} != 8) {
print scalar reverse unpack "b64", pack "D", 1e-298;
print scalar reverse unpack "b64", pack "D", get_problem_val($s);
}
else {
print scalar reverse unpack "b53", pack "F", 1e-298;
print scalar reverse unpack "b53", pack "F", get_problem_val($s);
}
Thanks, Ken.
Cheers, Rob | [reply] [d/l] |
|
|
| [reply] [d/l] |
Re: When 1e-298L != 1e-298L
by BrowserUk (Patriarch) on Oct 24, 2013 at 17:27 UTC
|
C:\test>r80test
1e-298
1e-298 : 00111100 00100001 10000101 11110000 01000110 10
+000010 10010011 11110000 11101011 01001110
smmmmmmm mmmmmmmm ffffffff ffffffff ffffffff ff
+ffffff ffffffff ffffffff ffffffff ffffffff
s = sign bit
m = 15-bit mantissa
f = 64-bit fraction
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
|
C:\test>r80test
Is "r80test" readily available ? (Could be handy.)
kcott's post demonstrates that the discrepancy also occurs when the nvtype is 'double' - but not universally according to some quick testing that I've just done. (The discrepancy occurs with gcc-4.6.3 on linux, and MSVC++ 7.0 on MS Windows, but not gcc-4.7.0 on MS Windows. In all instances the compiler I've used is the compiler that actually built perl. It seems that the behaviour does depend upon the compiler in use, not upon the version number of perl, but that's not properly tested yet.)
I've just rewritten the demo code so that it's also portable to perls whose nvtype is 'double'. (See my reply to kcott's post.)
And now I find that the mpfr library is providing varying results on linux and windows. It shouldn't do that, but I'll have to check the versions of mpfr that I'm running. (It may simply be a bug in an earlier version that has been fixed.)
Thanks Buk.
Cheers, Rob
| [reply] |
|
|
import std.stdio;
import std.format;
void main( string[] args ) {
real r;
ubyte *ubp = cast(ubyte*)&r;
foreach( line; stdin.byLine ) {
formattedRead( line, " %f ", &r );
writef( "%20.18g : ", r );
for( int i = r.sizeof -1; i >= 0; --i ) {
writef( "%08.8b ", ubp[i] );
}
writeln();
}
}
If you don't want to be bothered with installing/learning D, I can send you the executable?
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
|
Re: When 1e-298L != 1e-298L
by syphilis (Archbishop) on Oct 25, 2013 at 11:09 UTC
|
Is there a sound reason for this variation in value ?
When I finally got my thinking straightened out, it became obvious to me that this is a perl bug.
However, just because it's "obvious to me" doesn't really prove that it *is* a bug, so I've sent off a perlbug report (ticket #120363) ... if I don't forget, I'll update this node with the outcome of that report.
Thanks again Ken and Buk.
Cheers, Rob | [reply] |
|
|
I'll update this node with the outcome of that report
Seems it's a known bug (ticket #41202 from nearly 3 years ago) - and perhaps it's worthy of a separate post instead of an update.
I haven't found a build of perl that's not affected (and I've got quite a few) across intel (MS Windows), amd64 (Ubuntu) and PowerPC (debian) machines.
However, on some systems it's an off-by-one discrepancy , whereas on other systems it's off-by-two. (These could well be different bugs.)
And it seems to not occur across the full range of exponents ... so, for most perl purposes it's probably not much of an issue.
Still, it annoyed me enough to write a Math::NV module whose nv($str) function will assign the "C" value of $str to an NV - the assumption being that "C" gets it right. (It's an assumption I've tested against what both Data::Float and the mpfr library reckon is the correct representation but, with so many different versions of compiler/libc around, there's always a possibility of a bug to muddy the waters.)
Cheers, Rob
| [reply] |