谁能解释以下行为?

当声明一个新的 NumericMatrix y 作为原始矩阵 x 乘以标量 c 时,标量/矩阵乘法的顺序很重要。如果我将左侧的标量和右侧的矩阵相乘(例如 NumericMatrix y = c * x; ),则会出现奇怪的行为。原始矩阵 x 已更改!

但是,如果我将原始矩阵放在左侧并在右侧乘以标量(例如 NumericMatrix y = x * c; ),则 x 保持不变。

这似乎不会影响其他数据类型。我已经用 intNumericVector 进行了测试。

示例:使用 NumericMatrix 时出现问题

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericMatrix testfun(NumericMatrix x) {

  NumericMatrix y(x.rows(), x.cols());

  y = x * 2;

  std::cout << x; // x is unmodified

  y = 2 * x;

  std::cout << x; // x is now modified

  return x;
}



/*** R
x <- matrix(2, nrow = 3, ncol = 3)

print(x)

y <- testfun(x = x)

print(y)

print(x)

*/

输出如下。
> x <- matrix(2, nrow = 3, ncol = 3)

> print(x)
     [,1] [,2] [,3]
[1,]    2    2    2
[2,]    2    2    2
[3,]    2    2    2

> y <- testfun(x = x)
2.00000 2.00000 2.00000
2.00000 2.00000 2.00000
2.00000 2.00000 2.00000
4.00000 4.00000 4.00000
4.00000 4.00000 4.00000
4.00000 4.00000 4.00000

> print(y)
     [,1] [,2] [,3]
[1,]    4    4    4
[2,]    4    4    4
[3,]    4    4    4

> print(x)
     [,1] [,2] [,3]
[1,]    4    4    4
[2,]    4    4    4
[3,]    4    4    4

这是我的 session 信息
> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Catalina 10.15.1

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

loaded via a namespace (and not attached):
[1] compiler_3.6.1            tools_3.6.1               RcppArmadillo_0.9.800.1.0
[4] Rcpp_1.0.2                RcppProgress_0.4.1        packrat_0.5.0
[7] RcppParallel_4.4.4

.

最佳答案

这个问题太长了,并隐藏了它的观点。我们不需要第二个和第三个例子。我们只需要这个代码:

代码

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericMatrix testfun(NumericMatrix x) {
  NumericMatrix y(x.rows(), x.cols());
  y = x * 2;
  std::cout << x; // x is unmodified
  y = 2 * x;      // contrast with x * 2
  std::cout << x; // x is now modified
  return x;
}

/*** R
print(x <- matrix(2, nrow = 2, ncol = 2))
print(y <- testfun(x = x))
print(x)
*/

输出
R> Rcpp::sourceCpp("~/git/stackoverflow/59515517/question.cpp")

R> print(x <- matrix(2, nrow = 2, ncol = 2))
     [,1] [,2]
[1,]    2    2
[2,]    2    2

R> print(y <- testfun(x = x))
2.00000 2.00000
2.00000 2.00000
4.00000 4.00000
4.00000 4.00000
     [,1] [,2]
[1,]    4    4
[2,]    4    4

R> print(x)
     [,1] [,2]
[1,]    4    4
[2,]    4    4
R>

问题
x * 2 的行为与 2 * x 不同。后者有副作用。这很可能是一个错误,

更大的问题

用 Rcpp 做矩阵代数真的没有意义。实现是基本的和不完整的。如果您想做“数学”,请使用 RcppArmadillo 或 RcppEigen。

Arma 实现
#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::mat testfun(arma::mat x) {
  arma::mat y(x.n_rows, x.n_cols);
  y = x * 2;
  std::cout << x; // x is unmodified
  y = 2 * x;      // contrast with x * 2
  std::cout << x; // x is now modified
  return x;
}

/*** R
print(x <- matrix(2, nrow = 2, ncol = 2))
print(y <- testfun(x = x))
print(x)
*/

武装输出
R> Rcpp::sourceCpp("~/git/stackoverflow/59515517/answer.cpp")

R> print(x <- matrix(2, nrow = 2, ncol = 2))
     [,1] [,2]
[1,]    2    2
[2,]    2    2

R> print(y <- testfun(x = x))
   2.0000   2.0000
   2.0000   2.0000
   2.0000   2.0000
   2.0000   2.0000
     [,1] [,2]
[1,]    2    2
[2,]    2    2

R> print(x)
     [,1] [,2]
[1,]    2    2
[2,]    2    2
R>

我会看看我是否能找到你在这里找到的 Rcpp 错误。

编辑:这是一个错误,我还不太明白,但我在代码起源的问题中添加了一些内容:https://github.com/RcppCore/Rcpp/issues/365

编辑 2:该修复程序现已掌握。感谢 KK 的公关,感谢其他人在评论中暗示这可能背后的原因,特别是感谢拉尔夫让我们所有人尝试修复。

关于rcpp - Rcpp NumericMatrix 在左/右乘以标量时的奇怪行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59515517/

10-12 20:33