0

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!

AndreasNearchou
  • 128
  • 1
  • 6
  • The [Armadillo documentation](http://arma.sourceforge.net/docs.html) under the paragraph "The following subset of operations & functions is available for sparse matrices" does not suggest to me the operator is implemented. Hence the error you are getting may be expected? – Dirk Eddelbuettel Feb 05 '21 at 15:00
  • The first point "fundamental arithmetic operations (such as addition and multiplication)" it brings you to "operators", which includes `/`. – AndreasNearchou Feb 08 '21 at 07:22
  • That may be misleading. That 'operations' section is AFAICT for dense matrices as are all the examples _in that section_. Notice how the very sentence about sparse matrices you refer to qualifies to 'such as addition and multiplication' and how the examples _for sparse matrices_ just a few lines below show only multiplication. Using those four example lines compile. But as soon as you replace `*` with `/` it fails. Because, as I suggested, the operator is simply not implemented _for sparse matrices_. FWIW it works with `+` so I think the docs are fine as they are (modulo maybe the link). – Dirk Eddelbuettel Feb 08 '21 at 13:34
  • Understood, thanks! – AndreasNearchou Feb 08 '21 at 15:17
  • Element-wise division of two sparse matrices is ill advised. Most of the elements in a sparse matrix are zero, so element-wise division of all elements will result in a matrix dominated by NaN due to division by zero. The resulting matrix is not sparse, which is undesirable. – hbrerkere Feb 10 '21 at 02:29
  • @hbrerkere What do you mean? I am using sparse matrix to avoid all the zeros. The problem would have been if I transform it to a normal matrix and then divide. Doesn't mean that by avoiding the zeros I also avoid any operations on them? – AndreasNearchou Feb 10 '21 at 07:27
  • @AndreasNearchou Element-wise division would apply to all elements, including the zeros. In a sparse matrix the zero elements still logically exist, but they are just not stored. – hbrerkere Feb 22 '21 at 05:22

1 Answers1

3

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.

thc
  • 9,527
  • 1
  • 24
  • 39