Hi,
I've just started using Rcpp with the hopes of speeding up some R loops
through replacement with C++ code. I've been struggling with
understanding the behavior of the NumericMatrix datatype and more
generally how to pass matrices between R and C++.
I seem to be getting bizarre behavior when I pass default parameters to
my C++ functions. For example, take this C++ function and the
corresponding R wrapper function:
______________________________________
//testRcppMatrix.cpp
#include <Rcpp.h>
RcppExport SEXP plusonediag_RcppMatrix(SEXP matrix)
{
Rcpp::NumericMatrix orig(matrix);
Rcpp::NumericMatrix plus(matrix);
int n = orig.rows();
int k = orig.cols();
for (int i=0; i<n; i++)
{
if(i <= k)
{
plus(i,i) = plus(i,i) + 1;
}
}
Rcpp::Pairlist res(Rcpp::Named( "original", orig),
Rcpp::Named( "plus", plus)
);
return res;
}
______________________________________
#testRcpp.r
plusonediag_RcppMatrix_wrapper <- function(mat=matrix(seq(1,9)^2, ncol=3))
{
## Make the call...
val <- .Call("plusonediag_RcppMatrix",
mat)
return(val)
}
______________________________________
If I pass actual values to the plusonediag_RcppMatrix_wrapper, then I
get correct output; however, if I try to use the default parameter (mat)
or pass a matrix equal to the default matrix, then the original matrix
appears to be overwritten. See the session output below.
Anyone have any idea what I'm doing wrong? I'd appreciate any help or
insight into this problem.
I've attached the test files if that's helpful.
Thanks and best wishes,
--Erica Tsai
> # main.r
>
> library(Rcpp)
Loading required package: inline
> dyn.load("testRcppMatrix.so")
> source("testRcppMatrix.r")
>
> foo <- matrix(1:9, 3, 3)
> bar <- foo ^ 2
>
> plusonediag_RcppMatrix_wrapper #default mat is same as bar
function(mat=matrix(seq(1,9)^2, ncol=3))
{
## Make the call...
val <- .Call("plusonediag_RcppMatrix",
mat)
return(val)
}
> plusonediag_RcppMatrix_wrapper() #does not produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
> plusonediag_RcppMatrix_wrapper(foo) #produces correct output
$original
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$plus
[,1] [,2] [,3]
[1,] 2 4 7
[2,] 2 6 8
[3,] 3 6 10
> plusonediag_RcppMatrix_wrapper(bar) #does not produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
> plusonediag_RcppMatrix_wrapper(matrix((1:9), 3, 3)) #produces
correct output
$original
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$plus
[,1] [,2] [,3]
[1,] 2 4 7
[2,] 2 6 8
[3,] 3 6 10
> plusonediag_RcppMatrix_wrapper(matrix((1:9)^2, 3, 3)) #does not
produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
>
Sorry, I forgot to mention my installation details:
I'm running R version 2.11.0, Rcpp 0.8.0, on Ubuntu Hardy Heron.
Best,
--Erica
On 5/24/2010 8:58 PM, Yi-Hsin Erica Tsai wrote:
Hi,
I've just started using Rcpp with the hopes of speeding up some R loops
through replacement with C++ code. I've been struggling with
understanding the behavior of the NumericMatrix datatype and more
generally how to pass matrices between R and C++.
I seem to be getting bizarre behavior when I pass default parameters to
my C++ functions. For example, take this C++ function and the
corresponding R wrapper function:
______________________________________
//testRcppMatrix.cpp
#include <Rcpp.h>
RcppExport SEXP plusonediag_RcppMatrix(SEXP matrix)
{
Rcpp::NumericMatrix orig(matrix);
Rcpp::NumericMatrix plus(matrix);
int n = orig.rows();
int k = orig.cols();
for (int i=0; i<n; i++)
{
if(i <= k)
{
plus(i,i) = plus(i,i) + 1;
}
}
Rcpp::Pairlist res(Rcpp::Named( "original", orig),
Rcpp::Named( "plus", plus)
);
return res;
}
______________________________________
#testRcpp.r
plusonediag_RcppMatrix_wrapper <- function(mat=matrix(seq(1,9)^2, ncol=3))
{
## Make the call...
val <- .Call("plusonediag_RcppMatrix",
mat)
return(val)
}
______________________________________
If I pass actual values to the plusonediag_RcppMatrix_wrapper, then I
get correct output; however, if I try to use the default parameter (mat)
or pass a matrix equal to the default matrix, then the original matrix
appears to be overwritten. See the session output below.
Anyone have any idea what I'm doing wrong? I'd appreciate any help or
insight into this problem.
I've attached the test files if that's helpful.
Thanks and best wishes,
--Erica Tsai
> # main.r
>
> library(Rcpp)
Loading required package: inline
> dyn.load("testRcppMatrix.so")
> source("testRcppMatrix.r")
>
> foo <- matrix(1:9, 3, 3)
> bar <- foo ^ 2
>
> plusonediag_RcppMatrix_wrapper #default mat is same as bar
function(mat=matrix(seq(1,9)^2, ncol=3))
{
## Make the call...
val <- .Call("plusonediag_RcppMatrix",
mat)
return(val)
}
> plusonediag_RcppMatrix_wrapper() #does not produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
> plusonediag_RcppMatrix_wrapper(foo) #produces correct output
$original
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$plus
[,1] [,2] [,3]
[1,] 2 4 7
[2,] 2 6 8
[3,] 3 6 10
> plusonediag_RcppMatrix_wrapper(bar) #does not produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
> plusonediag_RcppMatrix_wrapper(matrix((1:9), 3, 3)) #produces correct
output
$original
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$plus
[,1] [,2] [,3]
[1,] 2 4 7
[2,] 2 6 8
[3,] 3 6 10
> plusonediag_RcppMatrix_wrapper(matrix((1:9)^2, 3, 3)) #does not
produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
>
_______________________________________________
Rcpp-devel mailing list
Rcpp-devel at lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
Hi Erica,
Thanks for your interest in Rcpp, and for posting on the list!
On 24 May 2010 at 20:58, Yi-Hsin Erica Tsai wrote:
| Hi,
|
| I've just started using Rcpp with the hopes of speeding up some R loops
| through replacement with C++ code. I've been struggling with
| understanding the behavior of the NumericMatrix datatype and more
| generally how to pass matrices between R and C++.
|
| I seem to be getting bizarre behavior when I pass default parameters to
| my C++ functions. For example, take this C++ function and the
| corresponding R wrapper function:
|
| ______________________________________
|
| //testRcppMatrix.cpp
|
| #include <Rcpp.h>
|
| RcppExport SEXP plusonediag_RcppMatrix(SEXP matrix)
| {
| Rcpp::NumericMatrix orig(matrix);
| Rcpp::NumericMatrix plus(matrix);
I think I once tried something like that and learned that you can get into
trouble with two matrices copied that way -- there is only one underlying
SEXP and pointer, so if you need two distinct ones you can't use it this way
but may need so called 'deep copies' (ie distinct memory).
| int n = orig.rows();
| int k = orig.cols();
|
| for (int i=0; i<n; i++)
| {
| if(i <= k)
| {
| plus(i,i) = plus(i,i) + 1;
| }
| }
|
| Rcpp::Pairlist res(Rcpp::Named( "original", orig),
| Rcpp::Named( "plus", plus)
| );
|
| return res;
| }
| ______________________________________
|
| #testRcpp.r
|
| plusonediag_RcppMatrix_wrapper <- function(mat=matrix(seq(1,9)^2, ncol=3))
| {
| ## Make the call...
| val <- .Call("plusonediag_RcppMatrix",
| mat)
| return(val)
| }
|
| ______________________________________
|
| If I pass actual values to the plusonediag_RcppMatrix_wrapper, then I
What do you mean by 'actual values' ?
| get correct output; however, if I try to use the default parameter (mat)
| or pass a matrix equal to the default matrix, then the original matrix
| appears to be overwritten. See the session output below.
Yes it would be overwritten as there is only one matrix here.
| Anyone have any idea what I'm doing wrong? I'd appreciate any help or
| insight into this problem.
|
| I've attached the test files if that's helpful.
|
| Thanks and best wishes,
| --Erica Tsai
|
| > # main.r
| >
| > library(Rcpp)
| Loading required package: inline
| > dyn.load("testRcppMatrix.so")
| > source("testRcppMatrix.r")
| >
| > foo <- matrix(1:9, 3, 3)
| > bar <- foo ^ 2
| >
| > plusonediag_RcppMatrix_wrapper #default mat is same as bar
| function(mat=matrix(seq(1,9)^2, ncol=3))
| {
| ## Make the call...
| val <- .Call("plusonediag_RcppMatrix",
| mat)
| return(val)
| }
| > plusonediag_RcppMatrix_wrapper() #does not produce correct output!!
|
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| > plusonediag_RcppMatrix_wrapper(foo) #produces correct output
| $original
| [,1] [,2] [,3]
| [1,] 1 4 7
| [2,] 2 5 8
| [3,] 3 6 9
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 4 7
| [2,] 2 6 8
| [3,] 3 6 10
|
| > plusonediag_RcppMatrix_wrapper(bar) #does not produce correct output!!
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| > plusonediag_RcppMatrix_wrapper(matrix((1:9), 3, 3)) #produces
| correct output
| $original
| [,1] [,2] [,3]
| [1,] 1 4 7
| [2,] 2 5 8
| [3,] 3 6 9
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 4 7
| [2,] 2 6 8
| [3,] 3 6 10
|
| > plusonediag_RcppMatrix_wrapper(matrix((1:9)^2, 3, 3)) #does not
| produce correct output!!
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| >
Some of these are indeed goofy!!
I wonder if this may also be related to a bug that Doug Bates reported a few
days ago and which Romain has fixed in SVN -- it had to do with evaluations
of environment related to function calls.
When I do this (using current SVN sources) I get:
src <- '
+ Rcpp::NumericMatrix orig(matrix);
+ Rcpp::NumericMatrix plus(matrix);
+
+ int n = orig.rows();
+ int k = orig.cols();
+
+ for (int i=0; i<n; i++) {
+ if(i <= k) {
+ plus(i,i) = plus(i,i) + 1;
+ }
+ }
+
+ Rcpp::List res = Rcpp::List::create(Rcpp::Named( "original", orig),
+ Rcpp::Named( "plus", plus));
+ return res;
+ '
fun <- cppfunction(signature(matrix="numeric"), src)
fun( matrix(1:9, ncol=3))
Hi Erica,
Thanks for your interest in Rcpp, and for posting on the list!
On 24 May 2010 at 20:58, Yi-Hsin Erica Tsai wrote:
| Hi,
|
| I've just started using Rcpp with the hopes of speeding up some R loops
| through replacement with C++ code. I've been struggling with
| understanding the behavior of the NumericMatrix datatype and more
| generally how to pass matrices between R and C++.
|
| I seem to be getting bizarre behavior when I pass default parameters to
| my C++ functions. For example, take this C++ function and the
| corresponding R wrapper function:
|
| ______________________________________
|
| //testRcppMatrix.cpp
|
| #include <Rcpp.h>
|
| RcppExport SEXP plusonediag_RcppMatrix(SEXP matrix)
| {
| Rcpp::NumericMatrix orig(matrix);
| Rcpp::NumericMatrix plus(matrix);
I think I once tried something like that and learned that you can get into
trouble with two matrices copied that way -- there is only one underlying
SEXP and pointer, so if you need two distinct ones you can't use it this way
but may need so called 'deep copies' (ie distinct memory).
| int n = orig.rows();
| int k = orig.cols();
|
| for (int i=0; i<n; i++)
| {
| if(i <= k)
| {
| plus(i,i) = plus(i,i) + 1;
| }
| }
|
| Rcpp::Pairlist res(Rcpp::Named( "original", orig),
| Rcpp::Named( "plus", plus)
| );
|
| return res;
| }
| ______________________________________
|
| #testRcpp.r
|
| plusonediag_RcppMatrix_wrapper <- function(mat=matrix(seq(1,9)^2, ncol=3))
| {
| ## Make the call...
| val <- .Call("plusonediag_RcppMatrix",
| mat)
| return(val)
| }
|
| ______________________________________
|
| If I pass actual values to the plusonediag_RcppMatrix_wrapper, then I
What do you mean by 'actual values' ?
| get correct output; however, if I try to use the default parameter (mat)
| or pass a matrix equal to the default matrix, then the original matrix
| appears to be overwritten. See the session output below.
Yes it would be overwritten as there is only one matrix here.
| Anyone have any idea what I'm doing wrong? I'd appreciate any help or
| insight into this problem.
|
| I've attached the test files if that's helpful.
|
| Thanks and best wishes,
| --Erica Tsai
|
| > # main.r
| >
| > library(Rcpp)
| Loading required package: inline
| > dyn.load("testRcppMatrix.so")
| > source("testRcppMatrix.r")
| >
| > foo <- matrix(1:9, 3, 3)
| > bar <- foo ^ 2
| >
| > plusonediag_RcppMatrix_wrapper #default mat is same as bar
| function(mat=matrix(seq(1,9)^2, ncol=3))
| {
| ## Make the call...
| val <- .Call("plusonediag_RcppMatrix",
| mat)
| return(val)
| }
| > plusonediag_RcppMatrix_wrapper() #does not produce correct output!!
|
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| > plusonediag_RcppMatrix_wrapper(foo) #produces correct output
| $original
| [,1] [,2] [,3]
| [1,] 1 4 7
| [2,] 2 5 8
| [3,] 3 6 9
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 4 7
| [2,] 2 6 8
| [3,] 3 6 10
|
| > plusonediag_RcppMatrix_wrapper(bar) #does not produce correct output!!
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| > plusonediag_RcppMatrix_wrapper(matrix((1:9), 3, 3)) #produces
| correct output
| $original
| [,1] [,2] [,3]
| [1,] 1 4 7
| [2,] 2 5 8
| [3,] 3 6 9
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 4 7
| [2,] 2 6 8
| [3,] 3 6 10
|
| > plusonediag_RcppMatrix_wrapper(matrix((1:9)^2, 3, 3)) #does not
| produce correct output!!
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| >
Some of these are indeed goofy!!
I wonder if this may also be related to a bug that Doug Bates reported a few
days ago and which Romain has fixed in SVN -- it had to do with evaluations
of environment related to function calls.
When I do this (using current SVN sources) I get:
src <- '
+ Rcpp::NumericMatrix orig(matrix);
+ Rcpp::NumericMatrix plus(matrix);
+
+ int n = orig.rows();
+ int k = orig.cols();
+
+ for (int i=0; i<n; i++) {
+ if(i <= k) {
+ plus(i,i) = plus(i,i) + 1;
+ }
+ }
+
+ Rcpp::List res = Rcpp::List::create(Rcpp::Named( "original", orig),
+ Rcpp::Named( "plus", plus));
+ return res;
+ '
fun <- cppfunction(signature(matrix="numeric"), src)
fun( matrix(1:9, ncol=3))
Hello,
This has nothing to do with default arguments, wrappers, etc ... on the
R side.
The issue is the difference between :
> typeof( matrix((1:9), 3, 3) )
[1] "integer"
> typeof( matrix(seq(1,9)^2, ncol=3) )
[1] "double"
The constructor of NumericMatrix has no choice but to cast the input
matrix to a numeric matrix if it is passed an integer matrix, therefore
when "matrix" is an integer matrix, there are three R objects involved,
giving you what you call "correct output".
When you pass it a numeric matrix, no cast is required, so there is only
one R object, shared by matrix, orig and plus. which gives you what you
call "incorrect output".
Further comments:
- don't use Pairlist unless you understand what a pairlist is in R, e.g.
what the R functions pairlist, as.pairlist, etc ... do. If you really
want to return a list, then use List::create, something like:
using namespace Rcpp;
return List::create( _["original"] = orig, _["plus"] = plus ) ;
This way, you'll get a real list (i.e. what the R function "list"
produces) which is more likely to be what you want
- Rcpp objects (Rcpp::NumericMatrix) don't copy data if they don't need
to, they just alter the way the data is perceived, so that you can
manipulate the matrix using c++ syntax, operators, etc ... hence Dirk's
comments. If you really wanted two distinct objects, you can use the
clone function:
Rcpp::NumericMatrix orig( matrix ) ;
Rcpp::NumerixMatrix plus = Rcpp::clone( orig ) ;
This will give you the deep copy Dirk teased you with.
Romain
Le 25/05/10 03:58, Yi-Hsin Erica Tsai a ?crit :
Hi,
I've just started using Rcpp with the hopes of speeding up some R loops
through replacement with C++ code. I've been struggling with
understanding the behavior of the NumericMatrix datatype and more
generally how to pass matrices between R and C++.
I seem to be getting bizarre behavior when I pass default parameters to
my C++ functions. For example, take this C++ function and the
corresponding R wrapper function:
______________________________________
//testRcppMatrix.cpp
#include <Rcpp.h>
RcppExport SEXP plusonediag_RcppMatrix(SEXP matrix)
{
Rcpp::NumericMatrix orig(matrix);
Rcpp::NumericMatrix plus(matrix);
int n = orig.rows();
int k = orig.cols();
for (int i=0; i<n; i++)
{
if(i <= k)
{
plus(i,i) = plus(i,i) + 1;
}
}
Rcpp::Pairlist res(Rcpp::Named( "original", orig),
Rcpp::Named( "plus", plus)
);
return res;
}
______________________________________
#testRcpp.r
plusonediag_RcppMatrix_wrapper <- function(mat=matrix(seq(1,9)^2, ncol=3))
{
## Make the call...
val <- .Call("plusonediag_RcppMatrix",
mat)
return(val)
}
______________________________________
If I pass actual values to the plusonediag_RcppMatrix_wrapper, then I
get correct output; however, if I try to use the default parameter (mat)
or pass a matrix equal to the default matrix, then the original matrix
appears to be overwritten. See the session output below.
Anyone have any idea what I'm doing wrong? I'd appreciate any help or
insight into this problem.
I've attached the test files if that's helpful.
Thanks and best wishes,
--Erica Tsai
> # main.r
>
> library(Rcpp)
Loading required package: inline
> dyn.load("testRcppMatrix.so")
> source("testRcppMatrix.r")
>
> foo <- matrix(1:9, 3, 3)
> bar <- foo ^ 2
>
> plusonediag_RcppMatrix_wrapper #default mat is same as bar
function(mat=matrix(seq(1,9)^2, ncol=3))
{
## Make the call...
val <- .Call("plusonediag_RcppMatrix",
mat)
return(val)
}
> plusonediag_RcppMatrix_wrapper() #does not produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
> plusonediag_RcppMatrix_wrapper(foo) #produces correct output
$original
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$plus
[,1] [,2] [,3]
[1,] 2 4 7
[2,] 2 6 8
[3,] 3 6 10
> plusonediag_RcppMatrix_wrapper(bar) #does not produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
> plusonediag_RcppMatrix_wrapper(matrix((1:9), 3, 3)) #produces correct
output
$original
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$plus
[,1] [,2] [,3]
[1,] 2 4 7
[2,] 2 6 8
[3,] 3 6 10
> plusonediag_RcppMatrix_wrapper(matrix((1:9)^2, 3, 3)) #does not
produce correct output!!
$original
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
$plus
[,1] [,2] [,3]
[1,] 2 16 49
[2,] 4 26 64
[3,] 9 36 82
>
_______________________________________________
Rcpp-devel mailing list
Rcpp-devel at lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
Hi Erica,
Thanks for your interest in Rcpp, and for posting on the list!
On 24 May 2010 at 20:58, Yi-Hsin Erica Tsai wrote:
| Hi,
|
| I've just started using Rcpp with the hopes of speeding up some R loops
| through replacement with C++ code. I've been struggling with
| understanding the behavior of the NumericMatrix datatype and more
| generally how to pass matrices between R and C++.
|
| I seem to be getting bizarre behavior when I pass default parameters to
| my C++ functions. For example, take this C++ function and the
| corresponding R wrapper function:
|
| ______________________________________
|
| //testRcppMatrix.cpp
|
| #include<Rcpp.h>
|
| RcppExport SEXP plusonediag_RcppMatrix(SEXP matrix)
| {
| Rcpp::NumericMatrix orig(matrix);
| Rcpp::NumericMatrix plus(matrix);
I think I once tried something like that and learned that you can get into
trouble with two matrices copied that way -- there is only one underlying
SEXP and pointer, so if you need two distinct ones you can't use it this way
but may need so called 'deep copies' (ie distinct memory).
It depends.
If "matrix" is a numeric matrix, there is only one object. If it is an
integer matrix, there are 3 objects.
I agree though that wrapping up one SEXP into two distinct Rcpp objects
is looking for trouble.
| int n = orig.rows();
| int k = orig.cols();
|
| for (int i=0; i<n; i++)
| {
| if(i<= k)
| {
| plus(i,i) = plus(i,i) + 1;
| }
| }
|
| Rcpp::Pairlist res(Rcpp::Named( "original", orig),
| Rcpp::Named( "plus", plus)
| );
|
| return res;
| }
| ______________________________________
|
| #testRcpp.r
|
| plusonediag_RcppMatrix_wrapper<- function(mat=matrix(seq(1,9)^2, ncol=3))
| {
| ## Make the call...
| val<- .Call("plusonediag_RcppMatrix",
| mat)
| return(val)
| }
|
| ______________________________________
|
| If I pass actual values to the plusonediag_RcppMatrix_wrapper, then I
What do you mean by 'actual values' ?
| get correct output; however, if I try to use the default parameter (mat)
| or pass a matrix equal to the default matrix, then the original matrix
| appears to be overwritten. See the session output below.
Yes it would be overwritten as there is only one matrix here.
| Anyone have any idea what I'm doing wrong? I'd appreciate any help or
| insight into this problem.
|
| I've attached the test files if that's helpful.
|
| Thanks and best wishes,
| --Erica Tsai
|
|> # main.r
|>
|> library(Rcpp)
| Loading required package: inline
|> dyn.load("testRcppMatrix.so")
|> source("testRcppMatrix.r")
|>
|> foo<- matrix(1:9, 3, 3)
|> bar<- foo ^ 2
|>
|> plusonediag_RcppMatrix_wrapper #default mat is same as bar
| function(mat=matrix(seq(1,9)^2, ncol=3))
| {
| ## Make the call...
| val<- .Call("plusonediag_RcppMatrix",
| mat)
| return(val)
| }
|> plusonediag_RcppMatrix_wrapper() #does not produce correct output!!
|
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
|> plusonediag_RcppMatrix_wrapper(foo) #produces correct output
| $original
| [,1] [,2] [,3]
| [1,] 1 4 7
| [2,] 2 5 8
| [3,] 3 6 9
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 4 7
| [2,] 2 6 8
| [3,] 3 6 10
|
|> plusonediag_RcppMatrix_wrapper(bar) #does not produce correct output!!
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
|> plusonediag_RcppMatrix_wrapper(matrix((1:9), 3, 3)) #produces
| correct output
| $original
| [,1] [,2] [,3]
| [1,] 1 4 7
| [2,] 2 5 8
| [3,] 3 6 9
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 4 7
| [2,] 2 6 8
| [3,] 3 6 10
|
|> plusonediag_RcppMatrix_wrapper(matrix((1:9)^2, 3, 3)) #does not
| produce correct output!!
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
|>
Some of these are indeed goofy!!
I wonder if this may also be related to a bug that Doug Bates reported a few
days ago and which Romain has fixed in SVN -- it had to do with evaluations
of environment related to function calls.
Unrelated.
When I do this (using current SVN sources) I get:
src<- '
+ Rcpp::NumericMatrix orig(matrix);
+ Rcpp::NumericMatrix plus(matrix);
+
+ int n = orig.rows();
+ int k = orig.cols();
+
+ for (int i=0; i<n; i++) {
+ if(i<= k) {
+ plus(i,i) = plus(i,i) + 1;
+ }
+ }
+
+ Rcpp::List res = Rcpp::List::create(Rcpp::Named( "original", orig),
+ Rcpp::Named( "plus", plus));
+ return res;
+ '
Hi Dirk and Romain,
Thanks for your help. I see now that I was treating the NumericMatrix
declarations as copy constructors, but rather should be thinking of them
as wrapper objects, and I need to be careful to only assign one Rcpp
variable to each SEXP. Also, a good catch of the difference between the
integer and numeric matrix; I would definitely not have spotted that for
a long time.
Thanks again for the helpful replies. It's sometimes difficult to be a
newbie learning a new package, especially when my c++ is so rusty! :)
Best,
--Erica
On 5/25/2010 2:42 AM, Romain Francois wrote:
Le 25/05/10 04:38, Dirk Eddelbuettel a ?crit :
Hi Erica,
Thanks for your interest in Rcpp, and for posting on the list!
On 24 May 2010 at 20:58, Yi-Hsin Erica Tsai wrote:
| Hi,
|
| I've just started using Rcpp with the hopes of speeding up some R loops
| through replacement with C++ code. I've been struggling with
| understanding the behavior of the NumericMatrix datatype and more
| generally how to pass matrices between R and C++.
|
| I seem to be getting bizarre behavior when I pass default parameters to
| my C++ functions. For example, take this C++ function and the
| corresponding R wrapper function:
|
| ______________________________________
|
| //testRcppMatrix.cpp
|
| #include<Rcpp.h>
|
| RcppExport SEXP plusonediag_RcppMatrix(SEXP matrix)
| {
| Rcpp::NumericMatrix orig(matrix);
| Rcpp::NumericMatrix plus(matrix);
I think I once tried something like that and learned that you can get
into
trouble with two matrices copied that way -- there is only one underlying
SEXP and pointer, so if you need two distinct ones you can't use it
this way
but may need so called 'deep copies' (ie distinct memory).
It depends.
If "matrix" is a numeric matrix, there is only one object. If it is an
integer matrix, there are 3 objects.
I agree though that wrapping up one SEXP into two distinct Rcpp objects
is looking for trouble.
| int n = orig.rows();
| int k = orig.cols();
|
| for (int i=0; i<n; i++)
| {
| if(i<= k)
| {
| plus(i,i) = plus(i,i) + 1;
| }
| }
|
| Rcpp::Pairlist res(Rcpp::Named( "original", orig),
| Rcpp::Named( "plus", plus)
| );
|
| return res;
| }
| ______________________________________
|
| #testRcpp.r
|
| plusonediag_RcppMatrix_wrapper<- function(mat=matrix(seq(1,9)^2,
ncol=3))
| {
| ## Make the call...
| val<- .Call("plusonediag_RcppMatrix",
| mat)
| return(val)
| }
|
| ______________________________________
|
| If I pass actual values to the plusonediag_RcppMatrix_wrapper, then I
What do you mean by 'actual values' ?
| get correct output; however, if I try to use the default parameter
(mat)
| or pass a matrix equal to the default matrix, then the original matrix
| appears to be overwritten. See the session output below.
Yes it would be overwritten as there is only one matrix here.
| Anyone have any idea what I'm doing wrong? I'd appreciate any help or
| insight into this problem.
|
| I've attached the test files if that's helpful.
|
| Thanks and best wishes,
| --Erica Tsai
|
|> # main.r
|>
|> library(Rcpp)
| Loading required package: inline
|> dyn.load("testRcppMatrix.so")
|> source("testRcppMatrix.r")
|>
|> foo<- matrix(1:9, 3, 3)
|> bar<- foo ^ 2
|>
|> plusonediag_RcppMatrix_wrapper #default mat is same as bar
| function(mat=matrix(seq(1,9)^2, ncol=3))
| {
| ## Make the call...
| val<- .Call("plusonediag_RcppMatrix",
| mat)
| return(val)
| }
|> plusonediag_RcppMatrix_wrapper() #does not produce correct output!!
|
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
|> plusonediag_RcppMatrix_wrapper(foo) #produces correct output
| $original
| [,1] [,2] [,3]
| [1,] 1 4 7
| [2,] 2 5 8
| [3,] 3 6 9
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 4 7
| [2,] 2 6 8
| [3,] 3 6 10
|
|> plusonediag_RcppMatrix_wrapper(bar) #does not produce correct output!!
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
|> plusonediag_RcppMatrix_wrapper(matrix((1:9), 3, 3)) #produces
| correct output
| $original
| [,1] [,2] [,3]
| [1,] 1 4 7
| [2,] 2 5 8
| [3,] 3 6 9
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 4 7
| [2,] 2 6 8
| [3,] 3 6 10
|
|> plusonediag_RcppMatrix_wrapper(matrix((1:9)^2, 3, 3)) #does not
| produce correct output!!
| $original
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
| $plus
| [,1] [,2] [,3]
| [1,] 2 16 49
| [2,] 4 26 64
| [3,] 9 36 82
|
|>
Some of these are indeed goofy!!
I wonder if this may also be related to a bug that Doug Bates reported
a few
days ago and which Romain has fixed in SVN -- it had to do with
evaluations
of environment related to function calls.
Unrelated.
When I do this (using current SVN sources) I get:
src<- '
+ Rcpp::NumericMatrix orig(matrix);
+ Rcpp::NumericMatrix plus(matrix);
+
+ int n = orig.rows();
+ int k = orig.cols();
+
+ for (int i=0; i<n; i++) {
+ if(i<= k) {
+ plus(i,i) = plus(i,i) + 1;
+ }
+ }
+
+ Rcpp::List res = Rcpp::List::create(Rcpp::Named( "original", orig),
+ Rcpp::Named( "plus", plus));
+ return res;
+ '