A recently asked question让我相信*
Rcpp
的句法糖不能按预期工作。在链接的问题中,用户试图将矩阵乘以标量。
R代码
以下是我们在Rcpp
中尝试实现的目标,但现在只需R
:
> m <- matrix(0:3, 2, 2)
> m * 3
[,1] [,2]
[1,] 0 6
[2,] 3 9
Rcpp代码
我已经创建了一些最小的例子,展示了上面的问题,以及一些意想不到的行为。首先请注意,我一直使用List
作为返回类型,因为它不需要我提前声明适当的类型:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
List FooMat() {
// Create a fill a 2x2 matrix
NumericMatrix tmp(2,2);
for (int i = 0; i < 4; i++) {
tmp[i] = i;
}
return List::create(tmp);
}
// [[Rcpp::export]]
List FooMat2() {
// Create a fill a 2x2 matrix
NumericMatrix tmp(2,2);
for (int i = 0; i < 4; i++) {
tmp[i] = i;
}
NumericVector x(1);
x[1] = 3;
return List::create(tmp * x);
}
// [[Rcpp::export]]
List FooMat3() {
// Create a fill a 2x2 matrix
NumericMatrix tmp(2,2);
for (int i = 0; i < 4; i++) {
tmp[i] = i;
}
NumericVector x(1);
x[1] = 3;
return List::create(tmp * x[1]);
}
// [[Rcpp::export]]
List FooMat4() {
// Create a fill a 2x2 matrix
NumericMatrix tmp(2,2);
for (int i = 0; i < 4; i++) {
tmp[i] = i;
}
return List::create(tmp * 3);
}
现在,如果我们获取文件,我们会得到一些奇怪的行为:
# Proof that we can return a NumericMatrix in a List:
> FooMat()
[[1]]
[,1] [,2]
[1,] 0 2
[2,] 1 3
# Multiply the whole NumericMatrix by a whole NumericVector
# whose size is 1. Unsafe behaviour?
> FooMat2()
[[1]]
[1] 0.000000e+00 3.000000e+00 1.388988e-309 2.083483e-309
# Multiply the whole NumericMatrix by the first element of
# The NumericVector. Results are correct, but `*` converts
# the answer to a NumericVector instead of a NumericMatrix
> FooMat3()
[[1]]
[1] 0 3 6 9
# Same as FooMat3() except now we just multiply the NumericMatrix
# by an integer
> FooMat4()
[[1]]
[1] 0 3 6 9
其中,*
提供的Rcpp
的句法糖似乎不能正确处理矩阵与标量的乘法。二,乘以整数NumericVector
,与FooMat2()
一样,会导致不安全的行为。
答案 0 :(得分:4)
正如我在之前的答案中所述,当我需要对矩阵进行实际数学运算时,我使用Armadillo对象:
R> cppFunction('arma::mat scott(arma::mat x, double z) {
+ return(x*z); }',
+ depends="RcppArmadillo")
R> scott(matrix(1:4,2), 2)
[,1] [,2]
[1,] 2 6
[2,] 4 8
R>
Sugar操作很好,但不完整。不过,我们肯定会接受补丁。
正如我们之前所说的那样:rcpp-devel是适当的支持渠道。
编辑(2016年10月或2年半后):搜索其他内容让我回到这里。在Rcpp 0.12。*系列中,有些在矩阵和向量之间进行操作时有效,因此基本的“矩阵时间标量”现在可以按照您的预期运行:
R> cppFunction("NumericMatrix testmat(NumericMatrix m, double multme) {
+ NumericMatrix n = m * multme;
+ return n; }")
R> testmat(matrix(1:4,2), 1)
[,1] [,2]
[1,] 1 3
[2,] 2 4
R> testmat(matrix(1:4,2), 3)
[,1] [,2]
[1,] 3 9
[2,] 6 12
R>
我可能仍然会使用RcppArmadillo来计算矩阵数学。
答案 1 :(得分:2)
这是一个糟糕的设计决策的不幸后果,即使Rcpp矩阵来自Rcpp向量。
我可能会在我现在维护的Rcpp实现中恢复这个决定:Rcpp11和Rcpp98。我不再认为让Matrix从Vector派生出来有任何好处,它会妨碍在this file结束时使用的CRTP。