【发布时间】:2014-01-06 13:18:46
【问题描述】:
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() 会导致不安全的行为。
【问题讨论】: