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
_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel