Rcpp: Syntactic sugar for * gives unexpected results when working with NumericMatrix

Recently, a question has led me to the fact that syntactic sugar for *to Rcppnot work as expected. In a related question, the user is trying to multiply the matrix by a scalar.

R code

Here we are trying to reach in Rcpp, but now in plain R:

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

Rcpp Code

I have created some minimal examples demonstrating both the problem described above and some unexpected behavior along the way. First of all, note that I consistently use it Listas the return type, because it eliminates the need for me to declare the corresponding 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 select a file, we get an odd behavior:

# 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(), .

+3
2

, , 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> 

, . , .

: rcpp-devel - .

( 2016 2 1/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 .

+4

, Rcpp Rcpp.

, , Rcpp, : Rcpp11 Rcpp98. , - , Matrix Vector, CRTP, .

+2

All Articles