From wdunlap at tibco.com  Fri May  1 17:25:42 2009
From: wdunlap at tibco.com (William Dunlap)
Date: Fri, 1 May 2009 08:25:42 -0700
Subject: [Rd] NA_real_ <op> NaN -> NA or NaN, should we care?
In-Reply-To: <77EB52C6DD32BA4D87471DCD70C8D700011DF87F@NA-PA-VBE03.na.tibco.com>
References: <77EB52C6DD32BA4D87471DCD70C8D700011DF636@NA-PA-VBE03.na.tibco.com><18938.59330.930913.863408@cmath-5.math.ethz.ch>
	<77EB52C6DD32BA4D87471DCD70C8D700011DF87F@NA-PA-VBE03.na.tibco.com>
Message-ID: <77EB52C6DD32BA4D87471DCD70C8D700011DF89A@NA-PA-VBE03.na.tibco.com>

The optimizer in gcc 4.2 (but not 4.1) on Linux seems to get this
issue "right" on one of my test machines (a 32-bit Ubuntu box).
4.1 fails on a 64-bit Linux but I don't have a newer gcc on any
64-bit Linux machine I can find.

A cleaner version of the test is:
% cat t.c
#include <stdio.h>
#include <stdint.h>
#include <string.h>

void print_double(char *text, double x_double)
{
    int64_t x_int64 ;
    memcpy((void*)&x_int64, (void*)&x_double, 8) ;
    printf("%s: %Lx (%g)\n", text, x_int64, x_double) ;
}
int main(int argc, char *argv[])
{
    int64_t NA_int64 = 0x7ff00000000007a2LL ;
    int64_t NaN_int64 = 0xfff8000000000000LL ;
    double NA_double, NaN_double, sum_double ;

    memcpy((void*)&NA_double, (void*)&NA_int64, 8) ;
    memcpy((void*)&NaN_double, (void*)&NaN_int64, 8) ;

    print_double(" NA", NA_double);
    print_double("NaN", NaN_double);
    sum_double = NA_double + NaN_double ;
    print_double("NA+NaN", sum_double) ;
    sum_double = NaN_double + NA_double ;
    print_double("NaN+NA", sum_double);
    return 0 ;
}

Bill Dunlap
TIBCO Software Inc - Spotfire Division
wdunlap tibco.com  

> -----Original Message-----
> From: r-devel-bounces at r-project.org 
> [mailto:r-devel-bounces at r-project.org] On Behalf Of William Dunlap
> Sent: Friday, May 01, 2009 7:50 AM
> To: Martin Maechler
> Cc: r-devel at r-project.org
> Subject: Re: [Rd] NA_real_ <op> NaN -> NA or NaN, should we care?
> 
> > From: Martin Maechler [mailto:maechler at stat.math.ethz.ch] 
> > Sent: Friday, May 01, 2009 5:15 AM
> > To: William Dunlap
> > Cc: r-devel at r-project.org
> > Subject: Re: [Rd] NA_real_ <op> NaN -> NA or NaN, should we care?
> > 
> > >>>>> William Dunlap <wdunlap at tibco.com>
> > >>>>>     on Thu, 30 Apr 2009 10:51:43 -0700 writes:
> > 
> >     > On Linux when I compile R 2.10.0(devel) 
> > (src/main/arithmetic.c in
> >     > particular)
> >     > with gcc 3.4.5 using the flags -g -O2 I get 
> > noncommutative behavior when
> > 
> > is this really gcc 3.4.5  (which is quite old) ?
> 
> Yes, it was 3.4.5, but here is a self-contained example of the same
> issue using gcc 4.1.3 on an Ubuntu Linux machine:
> 
> % gcc -O2 t.c -o a.out ; ./a.out
> NA : 7ff00000000007a2
> NaN: fff8000000000000
> NA+NaN: 7ff80000000007a2
> NaN+NA: fff8000000000000
> % gcc  t.c -o a.out ; ./a.out
> NA : 7ff00000000007a2
> NaN: fff8000000000000
> NA+NaN: 7ff80000000007a2
> NaN+NA: 7ff80000000007a2
> % gcc -v
> Using built-in specs.
> Target: i486-linux-gnu
> Configured with: ../src/configure -v 
> --enable-languages=c,c++,fortran,objc,obj-c++,treelang 
> --prefix=/usr --enable-shared --with-system-zlib 
> --libexecdir=/usr/lib --without-included-gettext 
> --enable-threads=posix --enable-nls 
> --with-gxx-include-dir=/usr/include/c++/4.1.3 
> --program-suffix=-4.1 --enable-__cxa_atexit 
> --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr 
> --enable-checking=release i486-linux-gnu
> Thread model: posix
> gcc version 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)
> % cat t.c
> #include <stdio.h>
> #include <stdint.h>
> #include <string.h>
> 
> int main(int argc, char *argv[])
> {
>     int64_t NA_int64 = 0x7ff00000000007a2LL ;
>     int64_t NaN_int64 = 0xfff8000000000000LL ;
>     int64_t sum_int64 ;
>     double NA_double, NaN_double, sum_double ;
> 
>     memcpy((void*)&NA_double, (void*)&NA_int64, 8) ;
>     memcpy((void*)&NaN_double, (void*)&NaN_int64, 8) ;
> 
>     NaN_double = 1/0.0 - 1/0.0 ;
> 
>     printf("NA : %Lx\n", *(int64_t*)&NA_double);
>     printf("NaN: %Lx\n", *(int64_t*)&NaN_double);
>     sum_double = NA_double + NaN_double ;
>     memcpy((void*)&sum_int64, (void*)&sum_double, 8) ;
>     printf("NA+NaN: %Lx\n", sum_int64) ;
>     sum_double = NaN_double + NA_double ;
>     memcpy((void*)&sum_int64, (void*)&sum_double, 8) ;
>     printf("NaN+NA: %Lx\n", sum_int64);
>     return 0 ;
> }
> 
> When I add -Wall to the -O2 then it gives me some warnings about the
> *(int64_t)&doubleVal in the printf statements for the inputs, 
> but I used
> memcpy() to avoid the warnings when printing the outputs.
> 
> % gcc -Wall -O2 t.c -o a.out ; ./a.out
> t.c: In function ?main?:
> t.c:17: warning: dereferencing type-punned pointer will break 
> strict-aliasing rules
> t.c:18: warning: dereferencing type-punned pointer will break 
> strict-aliasing rules
> NA : 7ff00000000007a2
> NaN: fff8000000000000
> NA+NaN: 7ff80000000007a2
> NaN+NA: fff8000000000000
> 
> Bill Dunlap
> TIBCO Software Inc - Spotfire Division
> wdunlap tibco.com  
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
> 



[Rd] NA_real_ <op> NaN -> NA or NaN, should we care?
William Dunlap