更新时间:2022-04-03 02:08:16
简而言之,是的,这是可能的,但它需要技巧,包括创建中间函数或在主函数中嵌入排序逻辑.
In short, yes its possible but it requires finesse that involves creating an intermediary function or embedding sorting logic within the main function.
总而言之,Rcpp 属性仅支持值的限制特征集.这些值列在 Rcpp 常见问题解答中3.12入口
In long, Rcpp attributes only supports a limit feature set of values. These values are listed in the Rcpp FAQ 3.12 entry
如果您要为 LLONG_MAX
和 LLONG_MIN
指定数值,这将满足直接在函数上使用 Rcpp 属性的条件.但是,这些值是特定于实现的.因此,对它们进行硬编码并不理想.因此,我们必须寻求外部解决方案:Rcpp::Nullable
类以启用默认的 NULL
值.之所以要用Rcpp::Nullable
来包裹参数类型,是因为NULL
很特殊,不小心会让人心痛.
If you were to specify numerical values for LLONG_MAX
and LLONG_MIN
this would meet the criteria to directly use Rcpp attributes on the function. However, these values are implementation specific. Thus, it would not be ideal to hardcode them. Thus, we have to seek an outside solution: the Rcpp::Nullable<T>
class to enable the default NULL
value. The reason why we have to wrap the parameter type with Rcpp::Nullable<T>
is that NULL
is a very special and can cause heartache if not careful.
NULL
值与实数轴上的其他值不同,在这种情况下将不会用于绑定您的值.因此,它是用于函数调用的完美候选者.然后您必须做出两个选择:使用 Rcpp::Nullable
作为主函数的参数,或者创建一个具有正确参数并可在其他地方使用的逻辑"辅助函数在您的应用程序中,无需担心.我选择了下面的后者.
The NULL
value, unlike others on the real number line, will not be used to bound your values in this case. As a result, it is the perfect candidate to use on the function call. There are two choices you then have to make: use Rcpp::Nullable<T>
as the parameters on the main function or create a "logic" helper function that has the correct parameters and can be used elsewhere within your application without worry. I've opted for the later below.
#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;
}
测试输出
Test Output
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