我有一些 Rcpp 代码来填充矩阵中的条目,这是它的作用的 MWE:
#include <Rcpp.h>
using namespace Rcpp;
void invert_tri(NumericMatrix &M, int K) {
for(int i=0 ; i<K ; ++i) {
for(int j=i+1 ; j<K ; ++j) {
M(j, i) = M(i, j);
}
}
}
// [[Rcpp::export]]
NumericMatrix multiply_entries(NumericMatrix M, int factor) {
int K = M.ncol();
for(int i=0 ; i<K ; ++i) {
for(int j=0 ; j<K ; ++j) {
M(i, j) = M(i, j) * factor;
}
}
invert_tri(M, K);
return M;
}
然后在 R 中我会像这样使用它:
M = matrix(c(1,NA,2,4), nrow = 2, ncol = 2)
multiply_entries(M, 2L)
此更改
[,1] [,2]
[1,] 1 2
[2,] NA 4
到
[,1] [,2]
[1,] 2 4
[2,] 4 8
然后,使用 cpp11,我将绘制以下代码
#include <cpp11.hpp>
#include <cpp11/doubles.hpp>
using namespace cpp11;
void invert_tri(writable::doubles_matrix<> &M, int K) {
for(int i=0 ; i<K ; ++i) {
for(int j=i+1 ; j<K ; ++j) {
M(j, i) = M(i, j);
}
}
}
[[cpp11::register]]
doubles_matrix<> multiply_entries(writable::doubles_matrix<> M, int factor) {
int K = M.ncol();
for(int i=0 ; i<K ; ++i) {
for(int j=0 ; j<K ; ++j) {
M(i, j) = M(i, j) * factor;
}
}
invert_tri(M, K);
return M;
}
但是在这里做M(j, i) += M(i, j)
会失败,并且由于隐式删除而失败=
。您对翻译工作代码的替代方法有什么想法吗?
原始代码失败,因为编译器无法解析要在语句中执行的赋值类型M(j, i) = M(i ,j)
解释:
- 左侧和右侧均为
r_vector<double>::proxy
型。 - 右侧的值可以转换为
double
,左侧有一个有效的赋值。 - 此类型(
r_vector<double>proxy>
)的复制和移动赋值运算符都因成员上的常量限定符而被删除。 - 虽然您会认为,因为只有一个未删除的赋值,所以不会有问题 - 但是 - 在重载解析期间仍会考虑已删除的赋值运算符。
我能想到的最简单的解决方案是通过将右侧转换为双精度来强制编译器进入角落,例如
void invert_tri(writable::doubles_matrix<> &M, int K) {
for(int i=0 ; i<K ; ++i) {
for(int j=i+1 ; j<K ; ++j) {
M(j, i) = (double)M(i, j);
}
}
}
也许不是大型矩阵的最佳方法,但这只是有效
void invert_tri(writable::doubles_matrix<> &M, int K) {
for(int i=0 ; i<K ; ++i) {
for(int j=i+1 ; j<K ; ++j) {
M(j, i) += (-1.0 * M(j, i)) + M(i, j);
}
}
}