[Rcpp-devel] Rcpp: Distinguishing between input types to function call
Romain Francois
romain at r-enthusiasts.com
Mon Dec 3 23:17:54 CET 2012
Hello,
I have not tested this, but I think you are looking for templates. So
you'd put generic code in this template function:
template <typename T>
SEXP topoSort( SEXP XX_ ){
const T X = Rcpp::as<T>(XX_) ;
...
}
and two other functions to instantiate the template:
RcppExport SEXP C_topoSort_st ( SEXP XX_ ){
return topoSort< Eigen::Map<Eigen::MatrixXi> >( XX_ ) ;
}
RcppExport SEXP C_topoSort_sp ( SEXP XX_ ){
return topoSort< Eigen::MappedSparseMatrix<double> >( XX_ ) ;
}
or Perhaps you would have one instead of the two, something like this:
RcppExport SEXP topoSort_facade ( SEXP XX_ ){
if( Rf_inherits( XX_, "dgCMatrix" ) ){
return topoSort< Eigen::MappedSparseMatrix<double> >( XX_ ) ;
} else {
return topoSort< Eigen::Map<Eigen::MatrixXi> >( XX_ ) ;
}
}
Le 03/12/12 22:58, Søren Højsgaard a écrit :
> Dear list,
>
> I represent a directed acyclic graph (DAG) as an adjacency matrix. This can be either a "standard matrix" in R or as a sparse matrix (dgCMatrix from the matrix package). I have implemented a topological sort function for DAGs for these two representations (using the RcppEigen package):
>
> // standard matrix
> RcppExport SEXP C_topoSort_st ( SEXP XX_ ){
> typedef Eigen::Map<Eigen::MatrixXi> MapMati;
> const MapMati X(Rcpp::as<MapMati>(XX_));
> //typedef Eigen::MappedSparseMatrix<double> MSpMat;
> //const MSpMat X(as<MSpMat>(XX_));
> .... some code
> }
>
> // sparse matrix
> RcppExport SEXP C_topoSort_sp ( SEXP XX_ ){
> // typedef Eigen::Map<Eigen::MatrixXi> MapMati;
> // const MapMati X(Rcpp::as<MapMati>(XX_));
> typedef Eigen::MappedSparseMatrix<double> MSpMat;
> const MSpMat X(as<MSpMat>(XX_));
> .... some code
> }
>
> Notice: The functions only differ with respect to the first four lines.
>
> Question: Is there any way in which I can "reduce" these two functions to only one which then checks the "type" of XX_ at the entry and then creates the appropriate "type" of X?
Templates.
> Question: Is it correct (haven't tried, just guessing from what I've read) that I can not directly store 'some code' in an inline function (because the correct type of X would need to be known?
I think I understand what you mean, and that you are fine.
> Apologies for trivial C++ questions - I am working on learning it...
Those are good kind of questions to ask yourself. I hope this will give
you enough motivation to find out more about C++ templates.
Romain
> The functions are listed below.
>
> Best regards
> Søren
>
> ----------------------------------
>
> # include <RcppEigen.h>
> # include <Rcpp.h>
>
> #ifndef BEGIN_RCPP
> #define BEGIN_RCPP
> #endif
>
> #ifndef END_RCPP
> #define END_RCPP
> #endif
>
> using namespace Rcpp;
>
> // standard matrix
> RcppExport SEXP C_topoSort_st ( SEXP XX_ ){
> typedef Eigen::Map<Eigen::MatrixXi> MapMati;
> const MapMati X(Rcpp::as<MapMati>(XX_));
> //typedef Eigen::MappedSparseMatrix<double> MSpMat;
> //const MSpMat X(as<MSpMat>(XX_));
> int ii, jj, kk=0, count=0, ll=0, flagsum=0;
> int ncX(X.rows());
> Eigen::VectorXi indegree(ncX);
> Eigen::VectorXi flag(ncX);
> Eigen::VectorXi ans(ncX);
>
> for (ii = 0; ii < ncX; ii++) {
> indegree[ii] = 0; flag[ii] = 0; ans[ii] = 0;
> }
> for (jj = 0; jj < ncX; jj++)
> for (ii = 0; ii < ncX; ii++)
> indegree[jj] = indegree[jj] + X.coeff(ii,jj);
>
> /* Rcout<<"indegree: ";for (ii=0;ii<ncX;ii++) Rcout << indegree[ii]<<" " ; Rcout << std::endl;*/
> /* Rcout<<"flag : ";for (ii=0;ii<ncX;ii++) Rcout << flag[ii]<<" " ; Rcout << std::endl;*/
> while (count < ncX){
> /* Rcout << "count=" << count << std::endl;*/
> for (kk = 0; kk < ncX; kk++){
> /* Rcout <<" kk="<<kk<<" indeg="<<indegree[kk]<<" flag="<<flag[kk] << std::endl;*/
> if ((indegree[kk] == 0) && (flag[kk] == 0)){
> /*Rcout << " no incomming:" << kk << std::endl;*/
> ans[ll++] = kk+1;
> flag[kk] = 1;
> flagsum++;
> for (jj = 0; jj < ncX; jj++){
> /* Rcout <<"kk,jj="<<kk<<","<<jj<<" entry=" << X.coeff(kk,jj) << std::endl;*/
> if (X.coeff(kk,jj) == 1){
> indegree[jj]--;
> /* Rcout <<" updating indegree at entry="<<jj<<std::endl;*/
> }
> }
> }
> /* Rcout<<"indegree: ";for (ii=0;ii<ncX;ii++) Rcout << indegree[ii]<<" " ; Rcout << std::endl; */
> }
> if (flagsum==ncX)
> break;
> count++;
> /* Rcout<<"flag : ";for (ii=0;ii<ncX;ii++) Rcout << flag[ii]<<" " ; Rcout << std::endl; */
> }
> if (flagsum<ncX)
> ans[0] = -1;
> return(wrap(ans));
> }
>
> // sparse matrix
> RcppExport SEXP C_topoSort_sp ( SEXP XX_ ){
> // typedef Eigen::Map<Eigen::MatrixXi> MapMati;
> // const MapMati X(Rcpp::as<MapMati>(XX_));
> typedef Eigen::MappedSparseMatrix<double> MSpMat;
> const MSpMat X(as<MSpMat>(XX_));
> int ii, jj, kk=0, count=0, ll=0, flagsum=0;
> int ncX(X.rows());
> Eigen::VectorXi indegree(ncX);
> Eigen::VectorXi flag(ncX);
> Eigen::VectorXi ans(ncX);
>
> for (ii = 0; ii < ncX; ii++) {
> indegree[ii] = 0; flag[ii] = 0; ans[ii] = 0;
> }
> for (jj = 0; jj < ncX; jj++)
> for (ii = 0; ii < ncX; ii++)
> indegree[jj] = indegree[jj] + X.coeff(ii,jj);
>
> /* Rcout<<"indegree: ";for (ii=0;ii<ncX;ii++) Rcout << indegree[ii]<<" " ; Rcout << std::endl;*/
> /* Rcout<<"flag : ";for (ii=0;ii<ncX;ii++) Rcout << flag[ii]<<" " ; Rcout << std::endl;*/
> while (count < ncX){
> /* Rcout << "count=" << count << std::endl;*/
> for (kk = 0; kk < ncX; kk++){
> /* Rcout <<" kk="<<kk<<" indeg="<<indegree[kk]<<" flag="<<flag[kk] << std::endl;*/
> if ((indegree[kk] == 0) && (flag[kk] == 0)){
> /*Rcout << " no incomming:" << kk << std::endl;*/
> ans[ll++] = kk+1;
> flag[kk] = 1;
> flagsum++;
> for (jj = 0; jj < ncX; jj++){
> /* Rcout <<"kk,jj="<<kk<<","<<jj<<" entry=" << X.coeff(kk,jj) << std::endl;*/
> if (X.coeff(kk,jj) == 1){
> indegree[jj]--;
> /* Rcout <<" updating indegree at entry="<<jj<<std::endl;*/
> }
> }
> }
> /* Rcout<<"indegree: ";for (ii=0;ii<ncX;ii++) Rcout << indegree[ii]<<" " ; Rcout << std::endl; */
> }
> if (flagsum==ncX)
> break;
> count++;
> /* Rcout<<"flag : ";for (ii=0;ii<ncX;ii++) Rcout << flag[ii]<<" " ; Rcout << std::endl; */
> }
> if (flagsum<ncX)
> ans[0] = -1;
> return(wrap(ans));
> }
--
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