[Rcpp-devel] long long

Romain Francois romain at r-enthusiasts.com
Thu Sep 19 17:30:22 CEST 2013


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



More information about the Rcpp-devel mailing list