gpt4 book ai didi

c++ - 将 Rcpp 函数扩展到任何类型的输入 vector

转载 作者:搜寻专家 更新时间:2023-10-31 00:28:06 24 4
gpt4 key购买 nike

我有以下函数,它在 NumericVector 上执行一个简单的循环并返回 int 类型的值。

  Rcpp::cppFunction({'
int calc_streak( NumericVector x, int i1, int i2){
int cur_streak=1;

if (NumericVector::is_na(x[0])){
cur_streak = NumericVector::get_na();
} else {
cur_streak = 1;
}

for(int j = i1; j <= i2 ; ++j) {
if( x[ j ] == x[ j-1 ]){
cur_streak += 1;

} else if(NumericVector::is_na( x[ j ] )){
cur_streak = NumericVector::get_na();

} else {
cur_streak = 1;

}
}
return cur_streak;
}
"})

calc_streak(c(1,1,1,1),i1=0,i2=3)
# [1] 4

功能对我来说工作正常,但真正的问题是当我试图在其他输入类型上扩展此功能。我一直在搜索堆栈 herehere ,但这些示例不适用于我的情况,或者我不知道如何正确使用示例。我尝试了几种处理未知输入类型的方法,但在我的案例中没有一个成功。下面三个例子


  1. 最简单的一个灵感来自 this - 创建了主函数,该函数根据参数 TYPEOF(x) 的类型运行先前定义的函数之一。 此函数返回integernumeric 的期望值。对于 character session 崩溃

    Rcpp::cppFunction('
    #include <Rcpp.h>
    using namespace Rcpp;

    int streak_run_int(IntegerVector x, int i1, int i2){
    int cur_streak=1;

    if (IntegerVector::is_na(x[0])){
    cur_streak = NumericVector::get_na();
    } else {
    cur_streak = 1;
    }

    for(int j = i1; j <= i2 ; ++j) {
    if( x[ j ] == x[ j-1 ]){
    cur_streak += 1;

    } else if(IntegerVector::is_na( x[ j ] )){
    cur_streak = NumericVector::get_na();

    } else {
    cur_streak = 1;

    }
    }
    return cur_streak;
    }

    int streak_run_char(CharacterVector x, int i1, int i2){
    int cur_streak=1;

    if (CharacterVector::is_na(x[0])){
    cur_streak = NumericVector::get_na();
    } else {
    cur_streak = 1;
    }

    for(int j = i1; j <= i2 ; ++j) {
    if( x[ j ] == x[ j-1 ]){
    cur_streak += 1;

    } else if(CharacterVector::is_na( x[ j ] )){
    cur_streak = NumericVector::get_na();

    } else {
    cur_streak = 1;

    }
    }
    return cur_streak;
    }


    // [[Rcpp::export]]
    int streak_run4(SEXP x, int i1, int i2) {
    switch (TYPEOF(x)) {
    case INTSXP: {
    return streak_run_int(as<IntegerVector>(x), i1, i2);
    }
    case STRSXP: {
    return streak_run_char(as<CharacterVector>(x), i1, i2);
    }
    default: { return 0; }
    }
    }
    ')

    # expected results for int and real - for character session crashes
    streak_run4( c(1,1,1,1),i1=0, i2=3)
    streak_run4( as.integer(c(1,1,1,1)),i1=0, i2=3)
    streak_run4( as.character(c(1,1,1,1)),i1=0, i2=3)

  1. 第二个函数的想法完全相同,但使用模板而不是定义多个函数。结果与上面相同 - character 输入 session 崩溃

    Rcpp::cppFunction('
    #include <Rcpp.h>
    using namespace Rcpp;

    namespace impl {

    template <int RTYPE>
    int streak_run_impl(const Vector<RTYPE>& x, int i1, int i2)
    {
    int cur_streak=1;

    if (Vector<RTYPE>::is_na(x[0])){
    cur_streak = NumericVector::get_na();
    } else {
    cur_streak = 1;
    }

    for(int j = i1; j <= i2 ; ++j) {
    if( x[ j ] == x[ j-1 ]){
    cur_streak += 1;

    } else if(Vector<RTYPE>::is_na( x[ j ] )){
    cur_streak = NumericVector::get_na();

    } else {
    cur_streak = 1;

    }
    }
    return cur_streak;
    }

    }

    // [[Rcpp::export]]
    int streak_run3(SEXP x, int i1, int i2) {
    switch (TYPEOF(x)) {
    case INTSXP: {
    return impl::streak_run_impl(as<IntegerVector>(x), i1, i2);
    }
    case REALSXP: {
    return impl::streak_run_impl(as<NumericVector>(x), i1, i2);
    }
    case STRSXP: {
    return impl::streak_run_impl(as<CharacterVector>(x), i1, i2);
    }
    case LGLSXP: {
    return impl::streak_run_impl(as<LogicalVector>(x), i1, i2);
    }
    case CPLXSXP: {
    return impl::streak_run_impl(as<ComplexVector>(x), i1, i2);
    }
    default: {
    return 0;
    }
    }
    }
    ')

    streak_run3( c(1,1,1,1),i1=0, i2=3)
    streak_run3( as.integer(c(1,1,1,1)),i1=0, i2=3)
    streak_run3( as.character(c(1,1,1,1)),i1=0, i2=3)

  1. 另一个灵感来自 this article ,这次我什至无法编译 C++ 函数,同时出现错误 use of overloaded operator '==' is ambiguous。无论如何,在检查了上述两个示例之后,我不希望有任何其他结果。

    Rcpp::cppFunction('
    #include <Rcpp.h>
    using namespace Rcpp;

    class streak_run2_impl {
    private:
    int i1;
    int i2;

    public:
    streak_run2_impl(int i1, int i2) : i1(i1), i2(i2) {}

    template <int RTYPE>
    IntegerVector operator()(const Vector<RTYPE>& x)
    {

    int cur_streak=1;

    if (Vector<RTYPE>::is_na(x[0])){
    cur_streak = NumericVector::get_na();
    } else {
    cur_streak = 1;
    }

    for(int j = i1; j <= i2 ; ++j) {
    if( x[ j ] == x[ j-1 ] ){
    cur_streak += 1;

    } else if(Vector<RTYPE>::is_na( x[ j ] )){

    cur_streak = NumericVector::get_na();

    } else {
    cur_streak = 1;
    }
    }
    return cur_streak;
    }
    };


    // [[Rcpp::export]]
    RObject streak_run2(RObject x, int i1 = 0, int i2=6){
    RCPP_RETURN_VECTOR(streak_run2_impl(i1, i2), x);
    }
    ')

所以我的问题是:如何正确定义此函数以获得任何 R 类输入 vector 的结果?
我很乐意提供任何建议。

最佳答案

首先,好帖子!不幸的是,您链接的上述资源均与您的问题无关,因为它是由于原型(prototype)函数中未发现的完全不同的错误所致。 为什么 原型(prototype)在调用时返回了一个有效值,这纯属运气。

正如@BenjaminChristoffersen 指出的那样,代码运行到 undefined behavior (UB)由于 out-of-bounds (OOB)发生错误。他的解决方案将有效地“解决”问题。

但是,要在将来自行诊断此问题,请从使用元素访问器 [] 切换到 (),它会检查您请求的元素是否是范围内。例如j 是否在 0n - 1 之间?

例如

  if (Vector<RTYPE>::is_na( x( 0 ) )){
// ------------------------^---^

cur_streak = NumericVector::get_na();
} else {
cur_streak = 1;
}

for(int j = i1; j <= i2 ; ++j) {
if( x( j ) == x( j-1 )){
// ^---^-----^-----^
cur_streak += 1;

} else if(Vector<RTYPE>::is_na( x( j ) )){
// --------------------------- ^ ^

cur_streak = NumericVector::get_na();

} else {
cur_streak = 1;

}
}

运行相同的命令然后给出:

streak_run3( c(1,1,1,1),i1=0, i2=3)

输出:

Error in streak_run3(c(1, 1, 1, 1), i1 = 0, i2 = 3) : 
Index out of bounds: [index=-1; extent=4].

输入:

streak_run3( as.integer(c(1,1,1,1)),i1=0, i2=3)

输出:

Error in streak_run3(as.integer(c(1, 1, 1, 1)), i1 = 0, i2 = 3) : 
Index out of bounds: [index=-1; extent=4].

输入:

streak_run3( as.character(c(1,1,1,1)),i1=0, i2=3)

输出:

Error in streak_run3(as.character(c(1, 1, 1, 1)), i1 = 0, i2 = 3) : 
Index out of bounds: [index=-1; extent=4].

关于c++ - 将 Rcpp 函数扩展到任何类型的输入 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46515052/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com