<div dir="ltr">I think the safest bet would be to handle dispatch at the R level, which would then call your internal C++ implementations. At least, it would be easier / cleaner. Otherwise, you're right, you need to perform an 'ad-hoc' dispatch based on the internal type / class and such.<div>
<br></div><div>-Kevin</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Dec 8, 2013 at 2:08 PM, Søren Højsgaard <span dir="ltr"><<a href="mailto:sorenh@math.aau.dk" target="_blank">sorenh@math.aau.dk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Thanks, Dirk!<br>
<br>
Follow up: That also means (I guess) that to be on the safe side I should write a check-function that will check that the INTSXP and REALSXP really is a matrix, i.e. that it has a dim attribute; right? Or are there facilities for that?<br>

<br>
Cheers<br>
Søren<br>
<div><div class="h5"><br>
<br>
-----Original Message-----<br>
From: Dirk Eddelbuettel [mailto:<a href="mailto:edd@debian.org">edd@debian.org</a>]<br>
Sent: 8. december 2013 22:59<br>
To: Søren Højsgaard<br>
Cc: <a href="mailto:rcpp-devel@lists.r-forge.r-project.org">rcpp-devel@lists.r-forge.r-project.org</a><br>
Subject: Re: [Rcpp-devel] Dispatch on sparse and dense matrices...<br>
<br>
<br>
Hi Søren,<br>
<br>
On 8 December 2013 at 21:47, Søren Højsgaard wrote:<br>
| Dear all,<br>
|<br>
| I want to do some computation on a matrix, irrespective of whether it is a numeric matrix, an integer matrix or a sparse matrix (a dgCMatrix which can be handled with RcppEigen). For simplicity, I want to compute the sum of the elements.<br>

|<br>
| To do so I use a template<br>
|<br>
| template <typename TT><br>
| SEXP do_compute( SEXP XX_ ){<br>
|   const TT X(as<TT>(XX_));<br>
|   return wrap(X.sum()); // some computation on X...<br>
| };<br>
|<br>
| I then dispatch depending on input type with<br>
|<br>
| // [[Rcpp::export]]<br>
| SEXP compute ( SEXP XX_ ){<br>
|   int type = TYPEOF(XX_) ;<br>
|   Rf_PrintValue(wrap(type));<br>
|   switch( type ){<br>
|   case 13 : return do_compute<MapMati>(XX_); // matrix - integer<br>
|   case 14 : return do_compute<MapMatd>(XX_); // matrix - double<br>
|   case 25 : return do_compute<MSpMat>(XX_); // dgCMatrix<br>
|   }<br>
|   return R_NilValue ;<br>
| }<br>
|<br>
| and the numbers 13, 14, 25 are disclosed to by simply printing the type. I know that for integers and doubles I can do something "nicer":<br>
|<br>
| // [[Rcpp::export]]<br>
| SEXP compute2 ( SEXP XX_ ){<br>
|   int type = TYPEOF(XX_) ;<br>
|   Rf_PrintValue(wrap(type));<br>
|   switch( type ){<br>
|   case INTSXP : return do_compute<MapMati>(XX_); // matrix - integer<br>
|   case REALSXP : return do_compute<MapMatd>(XX_); // matrix - double<br>
|   case 25 : return do_compute<MSpMat>(XX_); // dgCMatrix<br>
|   }<br>
|   return R_NilValue ;<br>
| }<br>
|<br>
| Questions:<br>
|<br>
| Is there a similar keyword for sparse matrices??<br>
<br>
I don't think so as sparse matrices do not have a first-class representation in a SEXP. So no TYPEOF(...) that uniquely identifies them.<br>
<br>
| If not, is the "code" 25 safe to use in an R-package??<br>
<br>
No, it simply says 'S4'. You can get that for lots of things which are not Sparse matrices. From Rinternals:<br>
<br>
  #define S4SXP       25    /* S4, non-vector */<br>
<br>
So you could replace '25' with 'S4SXP' but that does not protect you from<br>
S4 types which are not sparse matrices.<br>
<br>
| Are there more elegant ways of handling the dispatch ??<br>
<br>
Not sure. The TYPEOF() idiom used to be the standard; I think a few nicer<br>
C++ wrappers for is<> were added more recently.  Those will still<br>
</div></div>C++ dispatch on<br>
<div class="HOEnZb"><div class="h5">base types, and sparse matrices are not base types.  So you may have to go via S4SXP _and_ checking that the required slots exist.  Which you could then encode is a isSpMat() helper ...<br>

<br>
Dirk<br>
<br>
| The source file is attached. Thanks in advance.<br>
|<br>
| Søren<br>
|<br>
|<br>
|<br>
| ----------------------------------------------------------------------<br>
| #include <RcppEigen.h><br>
| //[[Rcpp::depends(RcppEigen)]]<br>
|<br>
| using namespace Rcpp;<br>
|<br>
| typedef Eigen::Map<Eigen::MatrixXd> MapMatd; typedef<br>
| Eigen::Map<Eigen::MatrixXi> MapMati; typedef<br>
| Eigen::MappedSparseMatrix<double> MSpMat;<br>
|<br>
| // [[Rcpp::export]]<br>
| SEXP getType ( SEXP XX_ ){<br>
|   int type = TYPEOF(XX_) ;<br>
|   return wrap(type);<br>
| }<br>
|<br>
| template <typename TT><br>
| SEXP do_compute( SEXP XX_ ){<br>
|   const TT X(as<TT>(XX_));<br>
|   return wrap(X.sum()); // some computation on X...<br>
| };<br>
|<br>
| // [[Rcpp::export]]<br>
| SEXP compute ( SEXP XX_ ){<br>
|   int type = TYPEOF(XX_) ;<br>
|   Rf_PrintValue(wrap(type));<br>
|   switch( type ){<br>
|   case 13 : return do_compute<MapMati>(XX_); // matrix - integer<br>
|   case 14 : return do_compute<MapMatd>(XX_); // matrix - double<br>
|   case 25 : return do_compute<MSpMat>(XX_); // dgCMatrix<br>
|   }<br>
|   return R_NilValue ;<br>
| }<br>
|<br>
| // [[Rcpp::export]]<br>
| SEXP compute2 ( SEXP XX_ ){<br>
|   int type = TYPEOF(XX_) ;<br>
|   Rf_PrintValue(wrap(type));<br>
|   switch( type ){<br>
|   case INTSXP : return do_compute<MapMati>(XX_); // matrix - integer<br>
|   case REALSXP : return do_compute<MapMatd>(XX_); // matrix - double<br>
|   case 25 : return do_compute<MSpMat>(XX_); // dgCMatrix<br>
|   }<br>
|   return R_NilValue ;<br>
| }<br>
|<br>
| /*** R<br>
|<br>
| library(Matrix)<br>
| m <- matrix(1:9, nrow=3)<br>
| M <- as(m, "dgCMatrix")<br>
|<br>
| getType( m ); getType( M ); getType( 1 ); getType( 1L )<br>
|<br>
| compute( m )   # integer<br>
| compute( 1*m ) # double<br>
| compute( M )   # sparse dgCMatrix<br>
| */<br>
|<br>
|<br>
|<br>
| ----------------------------------------------------------------------<br>
| _______________________________________________<br>
| Rcpp-devel mailing list<br>
| <a href="mailto:Rcpp-devel@lists.r-forge.r-project.org">Rcpp-devel@lists.r-forge.r-project.org</a><br>
| <a href="https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-deve" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-deve</a><br>
| l<br>
--<br>
Dirk Eddelbuettel | <a href="mailto:edd@debian.org">edd@debian.org</a> | <a href="http://dirk.eddelbuettel.com" target="_blank">http://dirk.eddelbuettel.com</a><br>
_______________________________________________<br>
Rcpp-devel mailing list<br>
<a href="mailto:Rcpp-devel@lists.r-forge.r-project.org">Rcpp-devel@lists.r-forge.r-project.org</a><br>
<a href="https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a><br>
</div></div></blockquote></div><br></div>