Le 07/06/13 15:14, Simon Zehnder a écrit :
Hi Romain, hi Dirk,

sorry for posting here again, but I found something in some way connected to this 
discussion - and pretty interesting concerning the Rcpp::as<>() function:

1. I create a class containing a list:

setClass("myclass", representation(par = "list"))

l <- list(lambda = array(0, dim = c(10,2)))

mclass <- new("myclass", par = l)

2. I compile a C++ function, that should reuse the memory of 'lambda' inside 
the list:

library(inline)
cfunction <- cxxfunction(signature(myClass_R = "array"), body = 'Rcpp::S4 myclass(myClass_R); Rcpp::List 
parL((SEXP) myclass.slot("par")); arma::mat armaPar(parL["lambda"].begin(), 10, 2, false, true); 
armaPar(0,0) = 1.2 ;return Rcpp::wrap(myclass);', plugin = "RcppArmadillo")

I get an error:

Error in compileCode(f, code, language = language, verbose = verbose) :
   Compilation ERROR, function(s)/method(s) not created! file6fc2ab39965.cpp: 
In function ‘SEXPREC* file6fc2ab39965(SEXP)’:
file6fc2ab39965.cpp:30:109: error: ‘Rcpp::Vector<19>::NameProxy’ has no member 
named ‘begin’
  Rcpp::S4 myclass(myClass_R); Rcpp::List parL((SEXP) myclass.slot("par")); arma::umat 
armaPar(parL["lambda"].begin(), 100, 10, false, true); armaPar(0,0) = 1.2 ;return 
Rcpp::wrap(myclass);

What you get from doing parL["lambda"] is an object of class NameProxy, it will be converted to the appropioate class later. NameProxy have no .begin method.

Do this:

NumericVector tmp = parL["lambda"] ;
arma::mat armaPar(tmp.begin(), 10, 2, false, true);

This will not make copies of the data.

If thius feels like too much to type, just stuff this into a function:

inline arma::mat convert( SEXP x ){
   NumericVector tmp = parL["lambda"] ;
   return arma::mat(tmp.begin(), 10, 2, false, true);
}

and call :

arma::mat armaPar = convert( parL["lambda"] ) ;

There is a chance convert won't make a copy thanks to RVO.

                              ^
make: *** [file6fc2ab39965.o] Error 1
In addition: Warning message:
running command '/Library/Frameworks/R.framework/Resources/bin/R CMD SHLIB 
file6fc2ab39965.cpp 2> file6fc2ab39965.cpp.err.txt' had status 1

-----------------------------------------------------------

It seems, that the SEXP inside the List is not yet an Rcpp::NumericMatrix, so I 
make it explicit to the arma::mat() constructor:

cfunction <- cxxfunction(signature(myClass_R = "array"), body = 'Rcpp::S4 myclass(myClass_R); Rcpp::List 
parL((SEXP) myclass.slot("par")); arma::mat 
armaPar(Rcpp::as<Rcpp::NumericMatrix>(parL["lambda"]).begin(), 100, 10, false, true); armaPar(0,0) = 1.2 ;return 
Rcpp::wrap(myclass);', plugin = "RcppArmadillo")

That compiles.

If we let it run it gives us:

cfunction(mclass)
An object of class "myclass"
Slot "par":
$lambda
       [,1] [,2]
  [1,]  1.2    0
  [2,]  0.0    0
  [3,]  0.0    0
  [4,]  0.0    0
  [5,]  0.0    0
  [6,]  0.0    0
  [7,]  0.0    0
  [8,]  0.0    0
  [9,]  0.0    0
[10,]  0.0    0

So, we can see, that implicitly calling Rcpp::as<>() inside the constructor 
arma::mat() avoids a copy by Rcpp::as<>() - which is just beautiful!


Best

Simon





On Jun 7, 2013, at 1:19 PM, Simon Zehnder <szehn...@uni-bonn.de> wrote:

Thank you Romain!

All clear now!


Best

Simon

On Jun 7, 2013, at 1:13 PM, Romain Francois <rom...@r-enthusiasts.com> wrote:

Le 07/06/13 13:09, Simon Zehnder a écrit :
HI Dirk, hi Romain,

allright, this is now clear to me, if I want to reuse memory, the allocated 
memory from R (so implicitly in C) must of course have the same type - 
otherwise the memory has a different size.

so far, this is obvious.

On the other side I then assume, that the Rcpp:as<class M>() function makes a 
cast and therefore creates a copy with new allocated memory of the type included in 
M? Therefore a reuse of memory with this function is not possible.

Depends what is M, but most of the time yes, as<> copies data.

Best

Simon


On Jun 6, 2013, at 8:31 PM, Dirk Eddelbuettel <e...@debian.org> wrote:


On 6 June 2013 at 13:17, Dirk Eddelbuettel wrote:
|
| On 6 June 2013 at 19:05, Simon Zehnder wrote:
| | sorry I had overseen this message from you. Okay, so the explicit cast to 
SEXP together with the assignment operator makes the deal. But it still 
includes the reuse of memory right, i.e. the '=' does not call the copy 
constructor?
|
| But how could an _unsigned int_ from Armadillo possibly have the same value
| as a _signed int_ in R?
|
| Either you are efficient (no copy), or you are correct (with a copy). I do
| not see how you could have both.

Sorry -- please ignore this message.

I had mistakenly assumed that you were still thinking about arma::umat to
integer.  For direct int-to-int this is indeed efficient just like the
double-to-double is for arma::mat to NumericMatrix (and dito for vectors).  I
though that was a given -- maybe need to make this (even) more explicit in
the documentation.

So in sum: you get correct and efficient behaviour if and only if you stick
with the types natively supported in Armadillo and R.

Dirk

--
Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com




--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30

R Graph Gallery: http://gallery.r-enthusiasts.com

blog:            http://blog.r-enthusiasts.com
|- http://bit.ly/Zs97qg  : highlight 0.4.1
`- http://bit.ly/10X94UM : Mobile version of the graph gallery


_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel




--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30

R Graph Gallery: http://gallery.r-enthusiasts.com

blog:            http://blog.r-enthusiasts.com
|- http://bit.ly/Zs97qg  : highlight 0.4.1
`- http://bit.ly/10X94UM : Mobile version of the graph gallery

_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to