0

My Rcpp code is shown here, I have used sourceCpp to compile the cpp file. No error is reported, just some warnings there. When I tried to implement the function softImpute using softImpute(m1, NULL, mr1, mr2, 0, -1), the reported error is Not compatible with requested type: [type=NULL; target=double].

Note: m1 is a numeric matrix, mr1 and mr2 are two logical matrix. For example, we can generate m1, mr1, mr2 as below:

m1 <- matrix(rnorm(30),5,6)
mr1 <- matrix(runif(30) > 0.5,5,6)
mr2 <- !mr1

Do you have any idea to address this error? Thank you in advance!

Rcpp code:

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
Rcpp::List dcSVD(arma::mat X) {
  arma::mat u, v;
  arma::vec d;
  arma::svd(u, d, v, X, "dc");
  return Rcpp::List::create(Rcpp::Named("u") = u,
                            Rcpp::Named("d") = d,
                            Rcpp::Named("v") = v);
}

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]] 
Rcpp::List svd_st(arma::mat X, double lambda){
  
  Rcpp::List mysvd = dcSVD(X);
  arma::mat U = mysvd["u"];
  arma::mat V = mysvd["v"];
  arma::mat VT = V.t();
  arma::vec d = mysvd["d"];
  arma::mat D = arma::diagmat(d);
  arma::uvec index_list = arma::find(d >= lambda);
  arma::vec w;
  arma::mat W;
  arma::mat L;
  if(index_list.n_elem > 1){
    w = d.elem(index_list) - lambda;
    W = arma::diagmat(w);
    arma::mat U1 = U.cols(index_list);
    arma::mat VT1 = VT.rows(index_list);
    L = U1 * W * VT1; 
  }else if(index_list.n_elem == 1){
    w = d.elem(index_list) - lambda;
    W = arma::diagmat(w);
    L = U.cols(index_list) * W * VT.rows(index_list);
  }else if(index_list.n_elem == 0){
    W = arma::zeros(1,1);
    L = arma::zeros(X.n_rows, X.n_cols);
  }
  return Rcpp::List::create(Rcpp::Named("L") = L, Rcpp::Named("W") = W); 
}

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
Rcpp::List soft(arma::mat X, Rcpp::Nullable<Rcpp::NumericMatrix> Z_ = R_NilValue, Rcpp::Nullable<Rcpp::LogicalMatrix> Ome_ = R_NilValue, 
                      Rcpp::Nullable<Rcpp::LogicalMatrix> Ome1_ = R_NilValue, Rcpp::Nullable<Rcpp::LogicalMatrix> Ome2_ = R_NilValue, 
                      Rcpp::Nullable<Rcpp::NumericVector> alpha0_ = R_NilValue, Rcpp::Nullable<Rcpp::NumericVector> maxRank_ = R_NilValue){
  
  Rcpp::NumericMatrix ZH = R_NilValue;
  double alpha = 0; 
  int maxRank = -1; 
  arma::mat Z;
  if (Ome_.isNotNull() && Ome1_.isNotNull() && Ome2_.isNotNull()){
    Rcpp::LogicalMatrix Ome(Ome_);
    arma::umat Omega = Rcpp::as<arma::umat>(Ome);
    Rcpp::LogicalMatrix Ome1(Ome1_);
    arma::umat Omega1 = Rcpp::as<arma::umat>(Ome1);
    Rcpp::LogicalMatrix Ome2(Ome2_);
    arma::umat Omega2 = Rcpp::as<arma::umat>(Ome2);
    arma::mat X_0 = X % Omega;
    if (!Z_.isNotNull()){
      Rcpp::NumericMatrix ZH = Rcpp::wrap(X_0);     
    }else{  
      Rcpp::NumericMatrix ZH = Rcpp::as<Rcpp::NumericMatrix>(Z_);
    }
    if (!alpha0_.isNotNull()){
      Rcpp::List my_svd = dcSVD(X_0);
      arma::vec d = my_svd["d"];
      double alpha = arma::as_scalar(d(1));  
    }else{
      Rcpp::NumericVector aa(alpha0_);
      double alpha = arma::as_scalar(aa(0)); 
    }
    if (!maxRank_.isNotNull()){
      int maxRank = -1;  
    }else{
      Rcpp::NumericVector bb(maxRank_);
      int maxRank = arma::as_scalar(bb(0));  
    }    
    Z = Rcpp::as<arma::mat>(ZH);
  }
  return Rcpp::List::create(Rcpp::Named("Z") = Z, 
                            Rcpp::Named("alpha") = alpha, 
                            Rcpp::Named("maxRank") = maxRank);
}  
cheng
  • 85
  • 1
  • 11
  • 2
    This is a little long, make your questions _shorter_ and people may have more incentive to dive in. As this appears to be about `Rcpp::Nullable<>` you want want to look at the [previous questions about it](https://stackoverflow.com/search?q=%5Brcpp%5D+Nullable). – Dirk Eddelbuettel Sep 23 '20 at 03:27
  • @DirkEddelbuettel Yes, it's a little long. My question is that the compilation of the cpp file has succeeded, why I got the error when I implemented the function. I am very curious about the essential reason. It should be about `Rcpp::Nullable<>`, I will try to look at more previous questions about it. Thank you! – cheng Sep 23 '20 at 03:49
  • 1
    Some things happe at compile-time, something only happen at run time. For example you can compile fine and then get an error if the argument does does match. – Dirk Eddelbuettel Sep 23 '20 at 12:21
  • @DirkEddelbuettel The Rcpp code is now much simplified, it still cannot work. In the code, there is no problem with the first two functions `dcSVD` and `svd_st`, the problem is only in the last function `soft`. I have looked at several previous questions, my code should work, however, it failed. – cheng Sep 23 '20 at 17:32
  • 1
    Please simplify further, and/or look at the existing `Rcpp::Nullable<>` examples as I asked you to do. You do not need three functions to check if / how one incoming matrix is, or is not, null. That is a five-liner. I recommend you make it one, maybe you will even be able to answer your own question that way. – Dirk Eddelbuettel Sep 23 '20 at 19:19

0 Answers0