I've put it in with some text explaining it.

// long long and unssigned long long support.
//
// given the current restriction of what might go to CRAN
// we can only use long long if we are running a gcc compatible (e.g. clang)
// compiler and the type is actually available (hence the test for __LONG_LONG_MAX__)
// even then, we cannot use long long as is, we first have to "hide" it
// behind the __extension__ so that -pedantic stops giving warnings about
// compliance with C++98
//
// client code may use the facilities we provide for long long (wrap, etc ...)
// but not using long long directly, because then it is not CRAN proof.
// So client code must use the rcpp_long_long_type and rcpp_ulong_long_type
// types
//
// e.g. code like this is not good:
//
// long long x = 2 ;
//
// but code like this is CRAN proof
//
// rcpp_long_long_type x = 2 ;
//
// Note that if you don't distribute your code to CRAN and you don't use the
// -pedantic option, then you can use long long
#if defined(__GNUC__) &&  defined(__LONG_LONG_MAX__)
    __extension__ typedef long long int rcpp_long_long_type;
    __extension__ typedef unsigned long long int rcpp_ulong_long_type;
    #define RCPP_HAS_LONG_LONG_TYPES
#endif

I'll start a discussion on R-devel if needed.



For now this gives us wrap<rcpp_long_long_type> and wrap< vector<rcpp_long_long_type> >, etc ... that for now generate numeric vector (so for a precision going up to 52 or 53(I can never remember this one) bits of precision, so better than what it used to be (32).

It might be worth investigating generating something compatible with the bit64 or the int64 package.

int64 stores a long long vector as a list of integer vectors of length 2.

bit64 is smarter and uses the bits of a double. And it is faster, as its documentation cares to show in great detail.

Other packages (e.g. data.table) have adopted the way bit64 does it. And it does not require that we depend on bit64. That's what data.table::fread does when reading integer64 columns: it stores them as a numeric vector with the appropriate class suitabe for bit64. Then if bit64 is loaded then the object is treated as a 64 bit integer vector. If it is not loaded, the values are just weird looking numeric vector.

Even though I wrote int64, I might actually lean towards generating something to play along with bit64 rather than int64.

However bit64 does not seem to implement unsigned 64 bit vectors (i.e. rcpp_ulong_long_type, aka unsigned long long).

Romain

Le 19/09/13 15:48, Romain Francois a écrit :
Le 19/09/13 15:30, Dirk Eddelbuettel a écrit :

On 19 September 2013 at 14:18, Romain Francois wrote:
| (rebrand as a Rcpp-devel question)

I just re-explained it on our internal rcpp-core list. The same points
were
all made here too circa 2010 and are in the list archives.

Sure. You explained what you think is right. I disagree. Let me explain
a bit more then.

In short, we are up against a CRAN Policy which wants

   i)   "standards compliant code" put unfortunately insists on a 15
year old
        standard (C++98)

   ii)  "portable code" as it maintains that there are compilers not
named g++
        or clang++ which matter (which I sort of agree with on
theoretical
        grounds, in practice I'd be ready to differ).

But in short it is not our call.  If we want Rcpp to be on CRAN (and I
maintain that we do) then we do NOT get long long.  At least not yet.

But I guess by the time we all are retired CRAN may allow the C++11
standard.

Dirk

What I want is to change this:

#if defined(__GNUC__)
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined (__clang__) &&
defined(__LP64__))
#ifdef __LONG_LONG_MAX__
     __extension__ typedef long long int rcpp_long_long_type;
     __extension__ typedef unsigned long long int rcpp_ulong_long_type;
     #define RCPP_HAS_LONG_LONG_TYPES
#endif
#endif
#endif


to this:

#if defined(__GNUC__) &&  defined(__LONG_LONG_MAX__)
     __extension__ typedef long long int rcpp_long_long_type;
     __extension__ typedef unsigned long long int rcpp_ulong_long_type;
     #define RCPP_HAS_LONG_LONG_TYPES
#endif


In both cases, we have artifacts of non portability, i.e. the
__extension__ thing, but in both cases they are hidden behind
defined(__GNUC__) so only enabled for gcc compatible compiler (so gcc
and clang).


But in what I propose, we can actually make something useful for long
long types, which we would have to use as rcpp_long_long_type for more
settings. For example, with this version of gcc on the mac, I have long
long but I can't use it:

$ gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build
5658) (LLVM build 2336.11.00)

If I follow your argument, neither what is currently in Rcpp not what I
propose should be in Rcpp.

Writing portable code is about settling on the lowest common denominator
but enable more things for more capable compilers when we know we use them.


Anyway, i can install Rcpp on both my OSX machine and your ubuntu with
gcc 4.4.7-2, compiling it with -pedantic in both cases and not get these
warnings.

And as long as we don't actually have "long long" in code, but use
"rcpp_long_long_type" then we are fine :

 > demangle( "rcpp_long_long_type" )
[1] "long long"
 >
 > demangle( "long long" )
file76776fc6e118.cpp: In function ‘SEXPREC* manipulate_this_type()’:
file76776fc6e118.cpp:8: warning: ISO C++ 1998 does not support ‘long long’
[1] "long long"

So we get the warnings because we explicitely write "long long" in code.


What I propose is as much (un)portable as what we have, it just is more
useful when it can be.

Romain



--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30

_______________________________________________
Rcpp-devel mailing list
[email protected]
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to