<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">Hi Romain,</span><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">
<br></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">Just wanted to give you a thanks for putting together this answer. It's a really great example of more generic programming with Rcpp by templating over the RTYPEs. </div>
<div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)"><br></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">
You should consider submitting some version of this to the Rcpp gallery; I think it has a lot of use cases.</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">
<br></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">-Kevin</div><br><div class="gmail_quote">On Wed, Feb 20, 2013 at 12:53 AM, Romain Francois <span dir="ltr"><<a href="mailto:romain@r-enthusiasts.com" target="_blank">romain@r-enthusiasts.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello,<br>
<br>
Here is a shorter version of your code. The key idea was to use TYPEOF instead of Rf_inherits which uses the class attribute (simple vectors don't have them).<br>
<br>
#include <Rcpp.h><br>
using namespace Rcpp;<br>
<br>
template <int RTYPE><div class="im"><br>
SEXP allpairsXtemplate_( SEXP XX_ ){<br></div>
Vector<RTYPE> X(XX_);<br>
Matrix<RTYPE> ans(2, X.size()*(X.size()-1)/2);<div class="im"><br>
int col=0;<br>
for (int ii=0; ii<X.size(); ii++){<br>
for (int jj=ii+1; jj<X.size(); jj++){<br>
ans(0,col) = X(ii);<br>
ans(1,col++) = X(jj);<br>
}<br>
}<br></div>
return ans ;<br>
};<br>
<br>
// [[Rcpp::export]]<div class="im"><br>
SEXP allpairsX_ ( SEXP XX_ ){<br></div>
int type = TYPEOF(XX_) ;<br>
switch( type ){<br>
case INTSXP : return allpairsXtemplate_<INTSXP> ( XX_ ) ;<br>
case REALSXP: return allpairsXtemplate_<REALSXP>( XX_ ) ;<br>
case STRSXP : return allpairsXtemplate_<STRSXP> ( XX_ ) ;<br>
}<br>
return R_NilValue ;<br>
}<br>
<br>
<br>
/*** R<div class="im"><br>
<br>
XX1 <- letters[1:4] # character<br>
XX2 <- 1:4 # integer<br>
XX3 <- (1:4)+.5 # numeric<br>
<br></div>
allpairsX_( XX1 )<br>
allpairsX_( XX2 )<br>
allpairsX_( XX3 )<br>
<br>
***/<br>
<br>
Also, I'm templating allpairsXtemplate_ on the R type rather than the actual classes, because NumericVector = Vector<REALSXP>, etc ...<br>
<br>
<br>
About your code, with e.g. TT = NumericVector, you don't need as in :<div class="im"><br>
<br>
TT X = as<TT>(XX_);<br>
<br></div>
because NumericVector already has a SEXP constructor, that is why I do: Vector<RTYPE> X(XX_);<br>
<br>
<br>
<br>
Same for return(wrap(ans)); you don't need to call wrap here because ans can convert itself to SEXP.<br>
<br>
<br>
<br>
Another way to write this using Rcpp's builtin dispatch mechanism is to use RCPP_RETURN_VECTOR. For example :<br>
<br>
#include <Rcpp.h><br>
using namespace Rcpp;<br>
<br>
template <typename T><br>
SEXP allpairsXtemplate_( const T& X){<br>
const int RTYPE = T::r_type::value ;<br>
Matrix<RTYPE> ans(2, X.size()*(X.size()-1)/2);<div class="im"><br>
int col=0;<br>
for (int ii=0; ii<X.size(); ii++){<br>
for (int jj=ii+1; jj<X.size(); jj++){<br>
ans(0,col) = X(ii);<br>
ans(1,col++) = X(jj);<br>
}<br>
}<br></div>
return ans ;<br>
};<br>
<br>
// [[Rcpp::export]]<div class="im"><br>
SEXP allpairsX_ ( SEXP XX_ ){<br></div>
RCPP_RETURN_VECTOR( allpairsXtemplate_, XX_ ) ;<br>
return R_NilValue ; // never used<br>
}<br>
<br>
<br>
So we call one of the generated overloads of allpairsXtemplate_ which takes a Vector as input. From this vector, we can deduce the RTYPE (at compile time):<br>
<br>
const int RTYPE = T::r_type::value ;<br>
<br>
use it to get the correct Matrix type : Matrix<RTYPE>.<br>
<br>
<br>
<br>
Yet another way, probably the one I would use:<br>
<br>
template <int RTYPE><br>
Matrix<RTYPE> allpairsXtemplate_( const Vector<RTYPE>& X){<br>
Matrix<RTYPE> ans(2, X.size()*(X.size()-1)/2);<div class="im"><br>
int col=0;<br>
for (int ii=0; ii<X.size(); ii++){<br>
for (int jj=ii+1; jj<X.size(); jj++){<br>
ans(0,col) = X(ii);<br>
ans(1,col++) = X(jj);<br>
}<br>
}<br></div>
return ans ;<br>
};<br>
<br>
This works because RCPP_RETURN_VECTOR will cast to the appropriate Vector type.<br>
<br>
And knowing the RTYPE at first lets us use it on the output signture.<br>
<br>
<br>
RCPP_RETURN_VECTOR is defined in dispatch.h (macro haters beware):<br>
<br>
#define ___RCPP_HANDLE_CASE___( ___RTYPE___ , ___FUN___ , ___OBJECT___ , ___RCPPTYPE___ ) \<br>
case ___RTYPE___ : \<br>
return ___FUN___( ::Rcpp::___RCPPTYPE___< ___RTYPE___ >( ___OBJECT___ ) ) ; <br>
<br>
#define ___RCPP_RETURN___( __FUN__, __SEXP__ , __RCPPTYPE__ ) \<br>
SEXP __TMP__ = __SEXP__ ; \<br>
switch( TYPEOF( __TMP__ ) ){ \<br>
___RCPP_HANDLE_CASE___( INTSXP , __FUN__ , __TMP__ , __RCPPTYPE__ ) \<br>
___RCPP_HANDLE_CASE___( REALSXP , __FUN__ , __TMP__ , __RCPPTYPE__ ) \<br>
___RCPP_HANDLE_CASE___( RAWSXP , __FUN__ , __TMP__ , __RCPPTYPE__ ) \<br>
___RCPP_HANDLE_CASE___( LGLSXP , __FUN__ , __TMP__ , __RCPPTYPE__ ) \<br>
___RCPP_HANDLE_CASE___( CPLXSXP , __FUN__ , __TMP__ , __RCPPTYPE__ ) \<br>
___RCPP_HANDLE_CASE___( STRSXP , __FUN__ , __TMP__ , __RCPPTYPE__ ) \<br>
___RCPP_HANDLE_CASE___( VECSXP , __FUN__ , __TMP__ , __RCPPTYPE__ ) \<br>
___RCPP_HANDLE_CASE___( EXPRSXP , __FUN__ , __TMP__ , __RCPPTYPE__ ) \<br>
default: \<br>
throw std::range_error( "not a vector" ) ; \<br>
}<br>
<br>
#define RCPP_RETURN_VECTOR( _FUN_, _SEXP_ ) ___RCPP_RETURN___( _FUN_, _SEXP_ , Vector )<br>
#define RCPP_RETURN_MATRIX( _FUN_, _SEXP_ ) ___RCPP_RETURN___( _FUN_, _SEXP_ , Matrix )<br>
<br>
<br>
<br>
Romain<br></blockquote><div><br></div><div><snip> </div><div><br></div><div><br></div></div>