Если вы повторно посмотрите пример basi c в R cpp Gallery и настроите один или два разреженных объекта Matrix, станет очевидно, что высокое значение для j
приводит к полному расширение в слоте p
(проверьте объект, возвращенный из sparseMatrix
).
Итак, вот более простой пример с (довольно высоким) значением i
, но низким j
. Я думаю, что вы должны быть в состоянии взять это отсюда:
Код
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp ;
// [[Rcpp::export]]
void convertSparse(S4 mat) {
// obtain dim, i, p. x from S4 object
IntegerVector dims = mat.slot("Dim");
arma::urowvec i = Rcpp::as<arma::urowvec>(mat.slot("i"));
arma::urowvec p = Rcpp::as<arma::urowvec>(mat.slot("p"));
arma::vec x = Rcpp::as<arma::vec>(mat.slot("x"));
int nrow = dims[0], ncol = dims[1];
// use Armadillo sparse matrix constructor
arma::sp_mat res(i, p, x, nrow, ncol);
Rcout << "SpMat res:\n" << res << std::endl;
}
// [[Rcpp::export]]
void convertSparse2(S4 mat) { // slight improvement with two non-nested loops
IntegerVector dims = mat.slot("Dim");
arma::urowvec i = Rcpp::as<arma::urowvec>(mat.slot("i"));
arma::urowvec p = Rcpp::as<arma::urowvec>(mat.slot("p"));
arma::vec x = Rcpp::as<arma::vec>(mat.slot("x"));
int nrow = dims[0], ncol = dims[1];
arma::sp_mat res(nrow, ncol);
// create space for values, and copy
arma::access::rw(res.values) = arma::memory::acquire_chunked<double>(x.size() + 1);
arma::arrayops::copy(arma::access::rwp(res.values), x.begin(), x.size() + 1);
// create space for row_indices, and copy
arma::access::rw(res.row_indices) = arma::memory::acquire_chunked<arma::uword>(i.size() + 1);
arma::arrayops::copy(arma::access::rwp(res.row_indices), i.begin(), i.size() + 1);
// create space for col_ptrs, and copy
arma::access::rw(res.col_ptrs) = arma::memory::acquire<arma::uword>(p.size() + 2);
arma::arrayops::copy(arma::access::rwp(res.col_ptrs), p.begin(), p.size() + 1);
// important: set the sentinel as well
arma::access::rwp(res.col_ptrs)[p.size()+1] = std::numeric_limits<arma::uword>::max();
// set the number of non-zero elements
arma::access::rw(res.n_nonzero) = x.size();
Rcout << "SpMat res:\n" << res << std::endl;
}
/*** R
suppressMessages({
library(methods)
library(Matrix)
})
i <- c(1,3:6)
j <- c(2,9,6:8)
x <- 5 * (1:5)
A <- sparseMatrix(i, j, x = x)
print(A)
convertSparse(A)
i <- 56789
j <- 87
x <- 42
B <- sparseMatrix(i, j, x=x)
#print(B)
convertSparse(B)
convertSparse2(B)
*/
Выход
R> Rcpp::sourceCpp("~/git/stackoverflow/60838958/answer.cpp")
R> suppressMessages({library(methods); library(Matrix)})
R> i <- c(1,3:6)
R> j <- c(2,9,6:8)
R> x <- 5 * (1:5)
R> A <- sparseMatrix(i, j, x = x)
R> print(A)
6 x 9 sparse Matrix of class "dgCMatrix"
[1,] . 5 . . . . . . .
[2,] . . . . . . . . .
[3,] . . . . . . . . 10
[4,] . . . . . 15 . . .
[5,] . . . . . . 20 . .
[6,] . . . . . . . 25 .
R> convertSparse(A)
SpMat res:
[matrix size: 6x9; n_nonzero: 5; density: 9.26%]
(0, 1) 5.0000
(3, 5) 15.0000
(4, 6) 20.0000
(5, 7) 25.0000
(2, 8) 10.0000
R> i <- 56789
R> j <- 87
R> x <- 42
R> B <- sparseMatrix(i, j, x=x)
R> #print(B)
R> convertSparse(B)
SpMat res:
[matrix size: 56789x87; n_nonzero: 1; density: 2.02e-05%]
(56788, 86) 42.0000
R> convertSparse2(B)
SpMat res:
[matrix size: 56789x87; n_nonzero: 1; density: 2.02e-05%]
(56788, 86) 42.0000
R>
Редактировать Действительно, хорошее напоминание. Если мы добавим
#define ARMA_64BIT_WORD 1
перед включением заголовка RcppArmadillo.h
, то с большими значениями i
и j
все будет хорошо. Хвост вывода ниже.
Обновлен вывод (только хвост)
R> i <- 56789
R> j <- 87654
R> x <- 42
R> B <- sparseMatrix(i, j, x=x)
R> #print(B)
R> convertSparse(B)
SpMat res:
[matrix size: 56789x87654; n_nonzero: 1; density: 2.01e-08%]
(56788, 87653) 42.0000
R> convertSparse2(B)
SpMat res:
[matrix size: 56789x87654; n_nonzero: 1; density: 2.01e-08%]
(56788, 87653) 42.0000
R>