[Rcpp-devel] Dispatch on sparse and dense matrices...

Søren Højsgaard sorenh at math.aau.dk
Sun Dec 8 23:08:23 CET 2013


Thanks, Dirk! 

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?

Cheers
Søren


-----Original Message-----
From: Dirk Eddelbuettel [mailto:edd at debian.org] 
Sent: 8. december 2013 22:59
To: Søren Højsgaard
Cc: rcpp-devel at lists.r-forge.r-project.org
Subject: Re: [Rcpp-devel] Dispatch on sparse and dense matrices...


Hi Søren,

On 8 December 2013 at 21:47, Søren Højsgaard wrote:
| Dear all,
| 
| 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. 
| 
| To do so I use a template
| 
| template <typename TT>
| SEXP do_compute( SEXP XX_ ){
|   const TT X(as<TT>(XX_));
|   return wrap(X.sum()); // some computation on X...
| };
| 
| I then dispatch depending on input type with
| 
| // [[Rcpp::export]]
| SEXP compute ( SEXP XX_ ){
|   int type = TYPEOF(XX_) ;
|   Rf_PrintValue(wrap(type));
|   switch( type ){
|   case 13 : return do_compute<MapMati>(XX_); // matrix - integer 
|   case 14 : return do_compute<MapMatd>(XX_); // matrix - double
|   case 25 : return do_compute<MSpMat>(XX_); // dgCMatrix
|   }
|   return R_NilValue ;
| }
| 
| 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":
| 
| // [[Rcpp::export]]
| SEXP compute2 ( SEXP XX_ ){
|   int type = TYPEOF(XX_) ;
|   Rf_PrintValue(wrap(type));
|   switch( type ){
|   case INTSXP : return do_compute<MapMati>(XX_); // matrix - integer 
|   case REALSXP : return do_compute<MapMatd>(XX_); // matrix - double
|   case 25 : return do_compute<MSpMat>(XX_); // dgCMatrix
|   }
|   return R_NilValue ;
| }
| 
| Questions:
| 
| Is there a similar keyword for sparse matrices?? 

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.
 
| If not, is the "code" 25 safe to use in an R-package??

No, it simply says 'S4'. You can get that for lots of things which are not Sparse matrices. From Rinternals:

  #define S4SXP       25    /* S4, non-vector */

So you could replace '25' with 'S4SXP' but that does not protect you from
S4 types which are not sparse matrices.

| Are there more elegant ways of handling the dispatch ??

Not sure. The TYPEOF() idiom used to be the standard; I think a few nicer 
C++ wrappers for is<> were added more recently.  Those will still 
C++ dispatch on
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 ...

Dirk

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


More information about the Rcpp-devel mailing list