Search code examples
c++rperformancematrixrcpp

Can I modify a row in-place with Rcpp?


Say, I would like to increase the first row of a matrix by one. The obvious approach is A.row(0) = A.row(0) + 1;, but it creates a new row instead of modifying the existing one, and may cause some performance issue when the matrix is large.

From a previous answer, I learned that I can do a point aliasing, but it only works for the whole matrix, not for individual rows.

library(Rcpp)
cppFunction('
void increaseFirstRow(NumericMatrix& A) {
    NumericVector B = A.row(0);
    B = B + 1;
}')
A <- diag(c(1.0, 2.0, 3.0))
increaseFirstRow(A)

The output is shown below. Note that the first row is not changed.

> A
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    2    0
[3,]    0    0    3

Solution

  • Under the formulation above, I think you wanted to obtain a reference to specific parts of the matrix. The following work across matrix types:

    *Matrix::Row = x( 0 , Rcpp::_);  // first row
    *Matrix::Column = x( Rcpp::_ , 0); // first column
    *Matrix::Sub = x( Rcpp::Range(0, 1) , Rcpp::Range(2, 3)); // first 2 rows and 3 -4th column.
    

    In your case, that would be:

    #include <Rcpp.h>
    
    // [[Rcpp::export]]
    void row_ref(Rcpp::NumericMatrix M) {
        // Create a reference to the 1st row in M.
        Rcpp::NumericMatrix::Row x = M.row(0);
        // Increase the first row in M.
        x = x + 10; 
    }
    

    Example:

    (A <- diag(c(1.0, 2.0, 3.0)))
    #      [,1] [,2] [,3]
    # [1,]    1    0    0
    # [2,]    0    2    0
    # [3,]    0    0    3
    
    row_ref(A)
    
    A
    #      [,1] [,2] [,3]
    # [1,]   11   10   10
    # [2,]    0    2    0
    # [3,]    0    0    3