[R] Call by reference or suggest workaround
Chidambaram Annamalai
quantumelixir at gmail.com
Sat Jun 19 17:48:48 CEST 2010
On 6/19/10, Romain Francois <romain.francois at dbmail.com> wrote:
>
> Le 19/06/10 16:32, Chidambaram Annamalai a écrit :
>>
>> I have written code to compute multi-indices in R [1] and due to the
>> recursive nature of the computation I need to pass around the *same*
>> matrix object (where each row corresponds to one multi-index). As pass
>> by reference wasn't the default behavior I declared a global matrix
>> (mat) and used the<<- operator to write to the global matrix. So the
>> usage would be to call genMultiIndices(3,2) for side effects to
>> generate all multi-indices of length 3 and sum 2. And then access the
>> global matrix.
>>
>> However, after coding this I can't seem to export the global matrix
>> object (in the NAMESPACE file) and still retain mutability since its
>> binding is "locked" (R throws an error). Can I somehow unlock this?
>>
>> Ideally I would want to pass around the same matrix to the recursive
>> function. Is that possible? If not, could someone please suggest a
>> workaround to use the code in an R package?
>>
>> [1]: http://dpaste.com/209186/
>
> Hi,
>
> You can use lexical scoping and you might like ?Recall as well.
>
> genMultiIndices <- function(N, V) {
> mat <- matrix(nrow=choose(N + V - 1, V), ncol=N)
> fillMultiIndices <- function(i, j, n, v) {
> if (n == 1) {
> mat[i, j] <<- v
> }
> else if (v == 0) {
> mat[i, j:(j + n - 1)] <<- 0L
> }
> else {
> rowOffset <- 0
> # the first element of each multi-index can be any of 0, 1, ..., v
> for (k in v:0) {
> times <- choose((n - 1) + (v - k) - 1, (v - k))
> mat[(i + rowOffset):(i + rowOffset + times - 1), j] <<- k
> Recall(i + rowOffset, j + 1, n - 1, v - k)
> rowOffset <- rowOffset + times
> }
> }
> }
> fillMultiIndices(1, 1, N, V)
> mat
> }
Following David Murdoch's advice that's *exactly* what I did :)
> Also, you can consider writing your code in a language that supports
> references, e.g. C++. Here is a start with inline/Rcpp :
>
> require( inline )
> require( Rcpp )
>
> genMultiIndices_internal <- local({
> inc <- '
> void fillMultiIndices( Rcpp::IntegerMatrix& mat, int i, int j, int n,
> int v ){
> if( n == 1 ){
> mat( (i-1), (j-1) ) = v ;
> } else if( v == 0 ){
> for( int k=j; k < j+n; k++){
> mat( (i-1), (k-1) ) = 0 ;
> }
> } else {
>
> // using the R function
> // I leave it to you to use a C implementation
> Function choose( "choose" ) ;
>
> int rowOffset = 0 ;
> int times ;
> for( int k=v; k>=0; k--){
> times = as<int>( choose( (n-1) + (v-k) - 1, (v-k) ) );
> int start = i + rowOffset ;
> int end = i + rowOffset + times ;
> for( int z = start; z < end; z++ ){
> mat( z-1 , j-1 ) = k ;
> }
> fillMultiIndices( mat, i + rowOffset, j+1, n-1, v-k ) ;
> rowOffset += times ;
> }
> }
> }
> '
> code <- '
> int N = as<int>( N_) ;
> int V = as<int>( V_) ;
> int NR = as<int>( NR_) ;
> Rcpp::IntegerMatrix mat( NR, N ) ;
> fillMultiIndices( mat, 1, 1, N, V ) ;
> return mat ;
> '
> .genMultiIndices <- cxxfunction(
> signature( N_ = "integer", V_ = "integer", NR_ = "integer" ),
> code, include = inc, plugin = "Rcpp" )
> function( N, V){
> .genMultiIndices( N, V, choose(N + V - 1, V) )
> }
> } )
Thanks for the C++ version! I will look into this if the symbol lookup
due to <<- is too much of a performance issue.
Chillu
More information about the R-help
mailing list