将 Rcpp 函数扩展到任何类型的输入向量

2024-01-11

我有以下函数,它执行一个简单的循环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

功能对我来说工作正常,但真正的问题是何时我正在尝试将此功能扩展到其他输入类型。我一直在堆栈上搜索here https://stackoverflow.com/questions/42363850/template-for-class-returning-elements-of-rcppvectorrtype and here https://stackoverflow.com/questions/19823915/how-can-i-handle-vectors-without-knowing-the-type-in-rcpp,但这些示例不适用于我的情况,或者我不知道如何正确使用示例。我尝试了几种处理未知输入类型的方法,但在我的案例中没有一个成功。 下面三个例子


  1. 最简单的一个灵感来自this http://gallery.rcpp.org/articles/rcpp-wrap-and-recurse/- 创建主函数,根据参数类型运行先前定义的函数之一TYPEOF(x). 该函数返回预期值integer and numeric. For character会话崩溃

    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 input

    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. 另一件作品的灵感来自于本文 http://gallery.rcpp.org/articles/rcpp-return-macros/,这次我什至无法编译 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 类的输入向量的结果?
我将非常感谢任何建议。


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

正如 @BenjaminChristoffersen 指出的,代码运行到了一个未定义行为 (UB) https://en.wikipedia.org/wiki/Undefined_behavior由于出界 (OOB) https://en.wikipedia.org/wiki/Bounds_checking发生错误。他的解决方案将有效地“解决”问题。

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

e.g.

  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)

Output:

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

Input:

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

Output:

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

Input:

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

Output:

Error in streak_run3(as.character(c(1, 1, 1, 1)), i1 = 0, i2 = 3) : 
  Index out of bounds: [index=-1; extent=4].
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 Rcpp 函数扩展到任何类型的输入向量 的相关文章

  • ClickOnce 应用程序错误:部署和应用程序没有匹配的安全区域

    我在 IE 中使用 FireFox 和 Chrome 的 ClickOnce 应用程序时遇到问题 它工作正常 异常的详细信息是 PLATFORM VERSION INFO Windows 6 1 7600 0 Win32NT Common
  • 复制 std::function 的成本有多高?

    While std function是可移动的 但在某些情况下不可能或不方便 复制它会受到重大处罚吗 它是否可能取决于捕获变量的大小 如果它是使用 lambda 表达式创建的 它依赖于实现吗 std function通常被实现为值语义 小缓
  • 在 C 中匹配二进制模式

    我目前正在开发一个 C 程序 需要解析一些定制的数据结构 幸运的是我知道它们是如何构造的 但是我不确定如何在 C 中实现我的解析器 每个结构的长度都是 32 位 并且每个结构都可以通过其二进制签名来识别 举个例子 有两个我感兴趣的特定结构
  • 如何区分用户点击链接和页面自动重定向?

    拥有 C WebBrowser control http msdn microsoft com en us library system windows forms webbrowser aspx在我的 WinForms 应用程序中 并意识
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 为什么调用非 const 成员函数而不是 const 成员函数?

    为了我的目的 我尝试包装一些类似于 Qt 共享数据指针的东西 经过测试 我发现当应该调用 const 函数时 会选择它的非 const 版本 我正在使用 C 0x 选项进行编译 这是一个最小的代码 struct Data int x con
  • 使用predictNLS围绕R中的拟合值创建置信区间?

    我想使用 R 中 propogate 包中的 PredictNLS 围绕一大组拟合值构建置信区间 作为示例 我将使用它们在函数描述中引用的数据集 https rdrr io github anspiess propagate man pre
  • 是否有实用的理由使用“if (0 == p)”而不是“if (!p)”?

    我倾向于使用逻辑非运算符来编写 if 语句 if p some code 我周围的一些人倾向于使用显式比较 因此代码如下所示 if FOO p some code 其中 FOO 是其中之一false FALSE 0 0 0 NULL etc
  • 具有交替类型的可变参数模板参数包

    我想知道是否可以使用参数包捕获交替参数模式 例如 template
  • 我可以使用 moq Mock 来模拟类而不是接口吗?

    正在经历https github com Moq moq4 wiki Quickstart https github com Moq moq4 wiki Quickstart 我看到它 Mock 一个接口 我的遗留代码中有一个没有接口的类
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • 如何检测表单的任何控件的变化?

    如何检测 C 中表单的任何控件的更改 由于我在一个表单上有许多控件 并且如果表单中的任何控件值发生更改 我需要禁用按钮 我正在寻找一些内置函数 事件处理程序 属性 并且不想为此创建自定义函数 不 我不知道任何时候都会触发任何事件any控制表
  • R 中的 Websocket

    我设法在 R 中建立到 Mtgox websocket 的连接 规格如下 url https socketio mtgox com mtgox Currency USD https socketio mtgox com mtgox Curr
  • 等待进程释放文件

    我如何等待文件空闲以便ss Save 可以用新的覆盖它吗 如果我紧密地运行两次 左右 我会得到一个generic GDI error
  • GGPLOT2:如何在 ggplot() 脚本中绘制特定选择

    这是一个名为的大型数据集的峰值P 其中有 10 个优惠 CS 有不同的商店 SHP 具有多个数值 数据集列出了按周排序的它们 WK 2 tm 52 它创建一个大文件 仅前 6 行出现峰值 WK MND CS SHP RevCY RevLY
  • 如何在非控制台应用程序中查看 cout 输出?

    输出到调试窗口似乎相当繁琐 我在哪里可以找到cout如果我正在编写非控制台信息 则输出 Like double i a b cout lt lt b lt lt endl I want to check out whether b is z
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且
  • Oracle Data Provider for .NET 不支持 Oracle 19.0.48.0.0

    我们刚刚升级到 Oracle 19c 19 3 0 所有应用程序都停止工作并出现以下错误消息 Oracle Data Provider for NET 不支持 Oracle 19 0 48 0 0 我将 Oracle ManagedData
  • 如何将 PostgreSql 与 EntityFramework 6.0.2 集成? [复制]

    这个问题在这里已经有答案了 我收到以下错误 实体框架提供程序类型的 实例 成员 Npgsql NpgsqlServices Npgsql 版本 2 0 14 2 文化 中性 PublicKeyToken 5d8b90d52f46fda7 没

随机推荐