我使用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;
}
答案 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 * width
和LLONG_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;
}