允许C ++常量使用Rcpp属性作为默认函数参数

时间:2017-04-18 18:00:44

标签: r rcpp

我使用rcpp在R包中创建了一个cumsum函数,该函数将累积求和向量,直到达到用户定义的上限或下限。但是,如果想要将cumsum限制在上面,则用户仍必须指定一个楼层。

示例:

a = c(1, 1, 1, 1, 1, 1, 1)

如果我想要积累a并且上限为3,我可以cumsum_bounded(a, lower = 1, upper = 3)。我宁愿不必指定下限。

我的代码:

#include <Rcpp.h>
#include <float.h>
#include <cmath>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector cumsum_bounded(NumericVector x, int upper, int lower) {
  NumericVector res(x.size());
  double acc = 0;
  for (int i=0; i < x.size(); ++i) {
    acc += x[i];
    if (acc < lower)  acc = lower;
    else if (acc > upper)  acc = upper;
    res[i] = acc;
  }
  return res;
}

我想要的是什么:

#include <Rcpp.h>
#include <float.h>
#include <cmath>
#include <climits> //for LLONG_MIN and LLONG_MAX
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector cumsum_bounded(NumericVector x, long long int upper = LLONG_MAX, long long int lower = LLONG_MIN) {
  NumericVector res(x.size());
  double acc = 0;
  for (int i=0; i < x.size(); ++i) {
    acc += x[i];
    if (acc < lower)  acc = lower;
    else if (acc > upper)  acc = upper;
    res[i] = acc;
  }
  return res;
}

1 个答案:

答案 0 :(得分:4)

简而言之,是可能的,但它需要精巧,包括创建中间函数或在主函数中嵌入排序逻辑。

总之,Rcpp属性仅支持限制功能值集。这些值列在Rcpp FAQ 3.12 entry

  
      
  • 用引号分隔的字符串文字(例如&#34; foo&#34;)
  •   
  • 整数和十进制数值(例如10或4.5)
  •   
  • 预定义的常量包括:      
        
    • 布尔:真假
    •   
    • 空值:R_NilValue,NA_STRING,NA_INTEGER,NA_REAL和NA_LOGICAL。
    •   
  •   
  • 可以使用。实例化选定的矢量类型   :: create静态成员函数的空形式。      
        
    • CharacterVector,IntegerVector和NumericVector
    •   
  •   
  • 使用rows,cols构造函数Rcpp :: Matrix n(rows,cols)实例化的矩阵类型      
        
    • CharacterMatrix,IntegerMatrix和NumericMatrix)
    •   
  •   

如果要为height * widthLLONG_MAX指定数值,则这将符合直接在函数上使用Rcpp属性的条件。但是,这些值是特定于实现的。因此,对它们进行硬编码并不理想。因此,我们必须寻求外部解决方案:LLONG_MIN类以启用默认的Rcpp::Nullable<T>值。我们必须用NULL包装参数类型的原因是Rcpp::Nullable<T>非常特殊,如果不小心可能会引起心痛。

NULL值与实数行上的其他值不同,在这种情况下不会用于绑定值。因此,它是在函数调用上使用的完美候选者。然后你必须做出两个选择:使用NULL作为主函数的参数或创建一个&#34;逻辑&#34;辅助函数具有正确的参数,可以在应用程序的其他地方使用而无需担心。我选择了下面的内容。

Rcpp::Nullable<T>

测试输出

#include <Rcpp.h>
#include <float.h>
#include <cmath>
#include <climits> //for LLONG_MIN and LLONG_MAX
using namespace Rcpp;

NumericVector cumsum_bounded_logic(NumericVector x,
                                   long long int upper = LLONG_MAX,
                                   long long int lower = LLONG_MIN) {

    NumericVector res(x.size());
    double acc = 0;
    for (int i=0; i < x.size(); ++i) {
        acc += x[i];
        if (acc < lower)  acc = lower;
        else if (acc > upper)  acc = upper;
        res[i] = acc;
    }

    return res;
}

// [[Rcpp::export]]
NumericVector cumsum_bounded(NumericVector x,
                             Rcpp::Nullable<long long int> upper = R_NilValue, 
                             Rcpp::Nullable<long long int> lower = R_NilValue) {

    if(upper.isNotNull() && lower.isNotNull()){
        return cumsum_bounded_logic(x, Rcpp::as< long long int >(upper), Rcpp::as< long long int >(lower));
    } else if(upper.isNull() && lower.isNotNull()){
        return cumsum_bounded_logic(x, LLONG_MAX, Rcpp::as< long long int >(lower));
    } else if(upper.isNotNull() && lower.isNull()) {
        return cumsum_bounded_logic(x, Rcpp::as< long long int >(upper), LLONG_MIN);
    } else {
        return cumsum_bounded_logic(x, LLONG_MAX, LLONG_MIN);
    }

    // Required to quiet compiler
    return x;
}