[Rcpp-devel] Dispatching based on SEXPTYPE

Romain Francois romain at r-enthusiasts.com
Thu Nov 22 15:17:06 CET 2012


Got it now. With a fresh version of Rcpp (rev 4018), you can do:

#include <Rcpp.h>
using namespace Rcpp;

template<int RTYPE>
SEXP unique_generic( const Vector<RTYPE> vector ) {
     typedef RCPP_UNORDERED_SET< typename Vector<RTYPE>::stored_type > 
SET ;
     SET set(vector.begin(), vector.end());
     return Vector<RTYPE>( set.begin(), set.end() ) ;
}

#define DISPATCH_METHOD(method, x)  \
   switch( TYPEOF(x) ){          \
     case REALSXP:                   \
       return method<REALSXP>(x);    \
     case INTSXP:                    \
       return method<INTSXP>(x);     \
     case STRSXP:                    \
       return method<STRSXP>(x);     \
     case LGLSXP:                    \
       return method<LGLSXP>(x);     \
     default:                        \
       Rf_error("Unsupported type"); \
       return x;                     \
   }


// [[Rcpp::export]]
SEXP unique2(SEXP x) {
   DISPATCH_METHOD(unique_generic, x)
}


/*** R

unique2(c(1.0,2.4,5.3))
unique2(c(1L, 2L, 1L))
unique2(c("a", "b", "a"))

***/

The constructor of Vector based in iterator takes care of the business. 
So you don't need to write a dispatch.


I like the idea of DISPATCH_METHOD, we would need extras at least for 
RAWSXP, CPLXSXP and VECSXP .



I have this as RcppScript now on my ~/bin:

#!/usr/bin/Rscript
require(Rcpp, quietly = TRUE)

args <- commandArgs(TRUE)
file <- tail( args, 1 )
sourceCpp( file )

So I run this file as


$ RcppScript /tmp/unique2.cpp
[1] 2.4 1.0 5.3
[1] 1 2
[1] "b" "a"

which is nice.

Romain

Le 22/11/12 14:17, Romain Francois a écrit :
> Le 22/11/12 13:42, JJ Allaire a écrit :
>> Would something like this work? (Romain you probably know best whether
>> this will actually work out over a large range of scenarios as well as
>> if the std::string specialization would work)
>>
>>
>> #include <Rcpp.h>
>> using namespace Rcpp;
>>
>> template<int RTYPE>
>> RObject unique_generic(RObject x) {
>>      Vector<RTYPE> vector = as<Vector<RTYPE> >(x);
>>      std::tr1::unordered_set<typename Vector<RTYPE>::stored_type >
>>                                          set(vector.begin(),
>> vector.end());
>>      return wrap(set);
>> }
>>
>> template<> RObject unique_generic<CHARSXP>(RObject x) {
>>    // TODO: appropriate specialization for CHARSXP (std::string)
>>    return x;
>> }
>>
>> #define DISPATCH_METHOD(method, x) \
>>     switch(x.sexp_type()) { \
>>      case REALSXP: \
>>        return method<REALSXP>(x); \
>>      case INTSXP: \
>>        return method<INTSXP>(x); \
>>      case CHARSXP: \
>>        return method<CHARSXP>(x); \
>>      case LGLSXP: \
>>        return method<LGLSXP>(x); \
>>      default: \
>>        Rf_error("Unsupported type"); \
>>        return x; \
>>    }
>>
>>
>> // [[Rcpp::export]]
>> RObject unique2(RObject x) {
>>    DISPATCH_METHOD(unique_generic, x)
>> }
>>
>> /*** R
>>
>> unique2(c(1.0,2.4,3.3,3.3,3.3,3.3,2,2,6))
>>
>> unique2(c(1,5,5,6,7))
>>
>> */
>
> the case CHARSXP is not going to be useful. You need to handle the
> STRSXP case.
>
> I've been looking at related things this morning. Right now, I can
> propose this:
>
> #include <Rcpp.h>
> using namespace Rcpp;
>
> template<int RTYPE>
> SEXP unique_generic( const Vector<RTYPE> vector ) {
>      typedef RCPP_UNORDERED_SET< typename Vector<RTYPE>::stored_type >
> SET ;
>      SET set(vector.begin(), vector.end());
>      Vector<RTYPE> out( set.size() ) ;
>      std::copy( set.begin(), set.end(), out.begin() ) ;
>      return out ;
> }
>
> #define DISPATCH_METHOD(method, x)  \
>    switch( TYPEOF(x) ){          \
>      case REALSXP:                   \
>        return method<REALSXP>(x);    \
>      case INTSXP:                    \
>        return method<INTSXP>(x);     \
>      case STRSXP:                    \
>        return method<STRSXP>(x);     \
>      case LGLSXP:                    \
>        return method<LGLSXP>(x);     \
>      default:                        \
>        Rf_error("Unsupported type"); \
>        return x;                     \
>    }
>
>
> // [[Rcpp::export]]
> SEXP unique2(SEXP x) {
>    DISPATCH_METHOD(unique_generic, x)
> }
>
>
> I'm not fully satisfied with this, and I'd like to have this instead:
>
> template<int RTYPE>
> SEXP unique_generic( const Vector<RTYPE> vector ) {
>      typedef RCPP_UNORDERED_SET< typename Vector<RTYPE>::stored_type >
> SET ;
>      SET set(vector.begin(), vector.end());
>      return Vector<RTYPE> out( set.begin(), set.end() ) ;
> }
>
> But the range constructor for Vector does not do what I want. I'm
> looking into it.
>
> Romain
>


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

R Graph Gallery: http://gallery.r-enthusiasts.com
`- http://bit.ly/SweN1Z : SuperStorm Sandy

blog:            http://romainfrancois.blog.free.fr
|- http://bit.ly/RE6sYH : OOP with Rcpp modules
`- http://bit.ly/Thw7IK : Rcpp modules more flexible



More information about the Rcpp-devel mailing list