Rcpp:* 的语法糖在处理 NumericMatrix 时会产生意想不到的结果 [英] Rcpp: Syntactic sugar for * produces unexpected results when dealing with NumericMatrix

查看:36
本文介绍了Rcpp:* 的语法糖在处理 NumericMatrix 时会产生意想不到的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近提出的一个问题 使我相信 Rcpp* 语法糖不能按预期工作.在链接的问题中,用户试图将矩阵乘以标量.

A recently asked question has lead me to believe the syntactic sugar for * by Rcpp does not work as intended. In the linked question, the user is trying to multiply a matrix by a scalar.

R 代码

以下是我们试图在 Rcpp 中实现的目标,但现在在普通的 R 中:

Here's what we're trying to achieve in Rcpp, but for now in plain R:

> m <- matrix(0:3, 2, 2)
> m * 3
     [,1] [,2]
[1,]    0    6
[2,]    3    9

Rcpp 代码

我创建了一些最小的示例来演示上述问题,以及一些意外的行为.首先请注意,我一直使用 List 作为返回类型,因为它不需要我提前声明适当的类型:

I've created some minimal examples demonstrating both the problem above, and also some unexpected behaviour along the way. First note that I'm consistently using List as a return type, because it removes the need for me to declare the appropriate type in advance:

#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); 
}

现在,如果我们获取文件,我们会得到一些奇怪的行为:

Now if we source the file we get some odd behaviour:

# 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() 会导致不安全的行为.

One, the syntactic sugar for * provided by Rcpp does not seem to correctly handle multiplication of Matrices with scalars. Two, multiplying by a whole NumericVector, as in FooMat2() leads to unsafe behaviour.

推荐答案

正如我在之前的回答中所述,当我需要对矩阵进行实际数学运算时,我使用 Armadillo 对象:

As I stated in previous answers, when I need to do actual math on matrices, I use Armadillo objects:

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 operations are nice, but not complete. We will certainly take patches, though.

正如我们之前多次说过的:rcpp-devel 是合适的支持渠道.

And as we said a few times before: rcpp-devel is the proper support channel.

编辑(2016 年 10 月或 2 1/2 年后):搜索其他东西让我回到了这里.在 Rcpp 0.12.* 系列中,一些在矩阵和向量之间的运算中起作用,因此基本的矩阵乘以标量"现在按您的预期工作:

Edit (Oct 2016 or 2 1/2 years later): Searching for something else just got me back here. In the Rcpp 0.12.* series, some work when into operations between matrix and vector so the basic 'matrix times scalar' now works as you'd expect:

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 进行矩阵的数学运算.

I'd probably still use RcppArmadillo for math on matrices though.

这篇关于Rcpp:* 的语法糖在处理 NumericMatrix 时会产生意想不到的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆