Я пытаюсь определить шаблонную функцию, которая может обрабатывать входные данные как с разреженной, так и с плотной матрицей, используя RcppArmadillo
. У меня есть очень простой случай отправки плотной или разреженной матрицы в C ++ и обратно в R, чтобы он работал следующим образом:
library(inline); library(Rcpp); library(RcppArmadillo)
sourceCpp(code = "
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp ;
using namespace arma ;
template <typename T> T importexport_template(const T X) {
T ret = X ;
return ret ;
};
//[[Rcpp::export]]
SEXP importexport(SEXP X) {
return wrap( importexport_template(X) ) ;
}")
library(Matrix)
X <- diag(3)
X_sp <- as(X, "dgCMatrix")
importexport(X)
## [,1] [,2] [,3]
##[1,] 1 0 0
##[2,] 0 1 0
##[3,] 0 0 1
importexport(X_sp)
##3 x 3 sparse Matrix of class "dgCMatrix"
##
##[1,] 1 . .
##[2,] . 1 .
##[3,] . . 1
и я интерпретирую это как означающее, что шаблон в основном работает (т. е. плотная R-матрица превращается в arma::mat
, а разреженная R-матрица превращается в arma::sp_mat
-объект неявными вызовами Rcpp::as
, а соответствующие подразумеваемые Rcpp:wrap
s затем сделайте то же самое и верните плотный вместо плотного и разреженный на разреженный).
Фактическая функция, которую я пытаюсь написать, конечно же, требует нескольких аргументов, и вот где я терплю неудачу - выполняю что-то вроде:
sourceCpp(code ="
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp ;
using namespace arma ;
template <typename T> T scalarmult_template(const T X, double scale) {
T ret = X * scale;
return ret;
};
//[[Rcpp::export]]
SEXP scalarmult(SEXP X, double scale) {
return wrap(scalarmult_template(X, scale) ) ;
}")
терпит неудачу, потому что компилятор не знает, как разрешить *
во время компиляции для SEXPREC* const
. Думаю, мне нужно что-то вроде оператора-переключателя в этом фрагменте Rcpp Gallery для правильной отправки конкретным функциям шаблона, но я не знаю, как написать это для типов, которые кажутся более сложными, чем INTSXP
и т. д.
Думаю, я знаю, как получить доступ к типу, который мне понадобится для такого оператора switch, например:
sourceCpp(code ="
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp ;
using namespace arma ;
//[[Rcpp::export]]
SEXP printtype(SEXP Xr) {
Rcpp::Rcout << TYPEOF(Xr) << std::endl ;
return R_NilValue;
}")
printtype(X)
##14
##NULL
printtype(X_sp)
##25
##NULL
но я не понимаю, что дальше делать. Как будет выглядеть версия scalarmult_template
, которая работает с разреженными и плотными матрицами?
if (Rf_isS4(Xr) && Rf_inherits(Xr, "<MatrixClass>")) {...}
- person Kevin Ushey   schedule 19.03.2014