简而言之,是的,这是可能的,但它需要技巧,涉及创建中间函数或在主函数中嵌入排序逻辑。
总而言之,Rcpp属性只支持有限的特征值集。这些值列在Rcpp FAQ 3.12入口
- 用引号分隔的字符串文字(例如“foo”)
- 整数和小数数值(例如 10 或 4.5)
- Pre-defined constants including:
- 布尔值:真与假
- 空值:R_NilValue、NA_STRING、NA_INTEGER、NA_REAL 和 NA_LOGICAL。
- Selected vector types can be instantiated using the
empty form of the ::create static member function.
- Matrix types instantiated using the rows, cols constructor Rcpp::Matrix n(rows,cols)
如果您要指定数值LLONG_MAX
and LLONG_MIN
这将满足在函数上直接使用 Rcpp 属性的标准。然而,这些值是特定于实现的。因此,对它们进行硬编码并不理想。因此,我们必须寻求外部解决方案:Rcpp::Nullable<T>
类以启用默认值NULL
价值。我们必须用以下内容包装参数类型的原因Rcpp::Nullable<T>
就是它NULL
是一个很特殊的东西,一不小心就会让人心痛。
The NULL
与实数线上的其他值不同,在这种情况下,值不会用于限制您的值。因此,它是在函数调用上使用的完美候选者。然后您必须做出两个选择:使用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;
}
测试输出
cumsum_bounded(a, 5)
## [1] 1 2 3 4 5 5 5
cumsum_bounded(a, 5, 2)
## [1] 2 3 4 5 5 5 5