Rcpp调用的c++计数算法模板

c++ count algorithm template called by Rcpp

Rcpp 调用的 C++ 计数算法可以计算向量中特定元素的出现次数。 应该使用模板。 我的尝试:

countRcpp <-'
#include<iostream>
#include<vector>
using namespace std;

  int val = as<int>(y);
  NumericVector xx(x);
  NumericVector::iterator iter;
  int m = 0;

  for(iter = xx.begin(); iter < xx.end(); iter++){
    if(*iter == val) ++m;}

  return(wrap(m));
'
countf <- cxxfunction(signature(x = "numeric", y = "numeric"),
                      body = countRcpp,
                      plugin = "Rcpp")

set.seed (1005) # set seed for sampling
x <- sample(1:5L, size = 10, replace = T) #L is Long integer. Keep the nunmber as integer. 
x # [1] 1 3 1 3 3 4 1 3 1 2
y <- 3L
y
countf(x,y) 


incl <- '
#include<iostream>
#include <algorithm>  
#include <vector> 
using namespace std;

  template <typename S_Type, typename T>
  typename iterator_traits<S_Type>::difference_type 

  S_Type countR(S_Type first, S_Type last, const T & val){
    typename iterator_traits<S_Type>::difference_type ret=0;
    while (first !=last){
    if(*first == val) ++ret;
    ++first;
    }
  return ret;
  }
'
body_count <- '
#include<iostream>
#include<vector>
#include <algorithm>    

using namespace std;

  NumericVector xx(x);
  int n = xx.size();
  NumericVector yy = xx + n;
  int val = as<int>(y);
  int pos = countR(xx, yy, val);
  return wrap(pos);
'
countRcpp3 <- cxxfunction(signature(x = "numeric", y = "numeric"),
              body = body_count,
              includes = incl,
              plugin = "Rcpp")

你能给我一些建议吗?或者你会推荐这个任务的其他逻辑吗?提前致谢。

作为第一步,您可以提取带有签名的函数

int foo(Rcpp::IntegerVector x, int val)

来自您的工作代码。然后,您可以将其概括为作用于任何可迭代类型。签名:

template <typename T>
int foo(T x, typename std::iterator_traits<typename T::iterator>::value_type val) 

不过,不能从 R 中调用它。如果 R 中的函数要作用于不同的类型,它必须以 SEXP 作为参数。 TYPEOF() 然后可用于确定 R 数据类型。将其放在一起以获得整数向量:

#include <Rcpp.h>

template <typename T>
int iter_count(T x, typename std::iterator_traits<typename T::iterator>::value_type val) { 
  int m = 0;

  for(typename T::iterator iter = x.begin(); iter < x.end(); ++iter) {
    if(*iter == val) ++m;
 }

  return m;
}


// [[Rcpp::export]]
int count(SEXP x, SEXP val) {
  switch( TYPEOF(x) ) {
  case INTSXP: {
    return iter_count(Rcpp::as<Rcpp::IntegerVector>(x),
              Rcpp::as<Rcpp::IntegerVector>(val)(0));
  }
  default: {
    Rcpp::stop("incompatible SEXP encountered");
  }
  }  
}


/*** R
set.seed (1005)
x <- sample(1:5L, size = 10, replace = T)
y <- 3L
count(x,y) 
*/

我在这里使用 Rcpp 属性:将其另存为 .cpp 文件并在其上使用 Rcpp::sourceCpp("...")

顺便说一句,在你的代码中这看起来很可疑:

  NumericVector xx(x);
  int n = xx.size();
  NumericVector yy = xx + n;

你想要xx的终点吗?然后使用 xx.end()end(xx),这不是 NumericVector。您的代码创建了一个新的 NumericVector,其中 xx 的内容增加了 xx 的大小。这里使用 Rcpp 属性的等效代码:

Rcpp::cppFunction('NumericVector foo(NumericVector xx) {
  int n = xx.size();
  NumericVector yy = xx + n;
  return yy;
}
')

set.seed(42)
foo(runif(3))
# [1] 3.914806 3.937075 3.286140