Search code examples
c++rrcpparmadillorcpparmadillo

How to element-wise divide 2 sparse matrices in Armadillo?


I am new to C++ but I am working with R and RcppArmadillo and my goal is to divide element-wise 2 sparse matrices. I have read in the documentation of Armadillo that the operator is / but when I source my code with sourceCpp I am getting this error:

no match for 'operator/' (operand types are 'arma::sp_mat' {aka 'arma::SpMat'} and 'arma::sp_mat' {aka 'arma::SpMat'})

I have write a small example of code. Please note that when I remove the division function from the script, the multiplication function works fine.

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>

using namespace Rcpp;

//' Sparse Matrix element-wise multiplication
//'
//' @param X sp_mat 
// [[Rcpp::export]]
arma::sp_mat sp_mat_mul(arma::sp_mat X){
  
  arma::sp_mat Y = X % X;
  return Y;
  
}


//' Sparse Matrix element-wise division
//'
//' @param X sp_mat 
// [[Rcpp::export]]
arma::sp_mat sp_mat_div(arma::sp_mat X){
  
  arma::sp_mat Y = X / X;
  return Y;
  
}

Thank you for your time, I really appreciate it!


Solution

  • Use transform/foreach to calculate the inverse then multiply.

    //' Sparse Matrix element-wise division
    //'
    //' @param X sp_mat 
    // [[Rcpp::export]]
    arma::sp_mat sp_mat_div(arma::sp_mat X){
      arma::sp_mat x_inverse(X);
      x_inverse.transform([](double val) {return (1.0/val);});
      arma::sp_mat Y = X % x_inverse;
      return Y;
    }
    

    R:

    i <- c(1,3:8)
    j <- c(2,9,6:10)
    x <- 7 * (1:7)
    A <- sparseMatrix(i, j, x = x)
    
    sp_mat_div(A)
    [1,] . 1 . . . . . . . .
    [2,] . . . . . . . . . .
    [3,] . . . . . . . . 1 .
    [4,] . . . . . 1 . . . .
    [5,] . . . . . . 1 . . .
    [6,] . . . . . . . 1 . .
    [7,] . . . . . . . . 1 .
    [8,] . . . . . . . . . 1
    

    As an aside, are you sure this operation makes sense?

    You are ignoring all the zeroes in the matrix (since it is sparse), and if this were a non-sparse matrix, you'd be dividing by zero a lot.