Skip to content

Commit 472514d

Browse files
committed
improved example by using block copies instead of loops
1 parent 60faa92 commit 472514d

File tree

2 files changed

+51
-59
lines changed

2 files changed

+51
-59
lines changed

_posts/2012-12-25-armadillo-sparse-matrix.md

+26-30
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ Let's start with creating a sparse matrix.
1818

1919

2020
{% highlight r %}
21-
suppressMessages(library(Matrix))
22-
i <- c(1,3:8)
23-
j <- c(2,9,6:10)
24-
x <- 7 * (1:7)
25-
A <- sparseMatrix(i, j, x = x)
26-
print(A)
21+
suppressMessages(library(Matrix))
22+
i <- c(1,3:8)
23+
j <- c(2,9,6:10)
24+
x <- 7 * (1:7)
25+
A <- sparseMatrix(i, j, x = x)
26+
print(A)
2727
{% endhighlight %}
2828

2929

3030

3131
<pre class="output">
32-
8 x 10 sparse Matrix of class "dgCMatrix"
32+
8 x 10 sparse Matrix of class &quot;dgCMatrix&quot;
3333

3434
[1,] . 7 . . . . . . . .
3535
[2,] . . . . . . . . . .
@@ -53,35 +53,29 @@ using namespace Rcpp ;
5353

5454
// [[Rcpp::export]]
5555
void convertSparse(S4 mat) { // slight improvement with two non-nested loops
56+
5657
IntegerVector dims = mat.slot("Dim");
57-
IntegerVector i = mat.slot("i");
58-
IntegerVector p = mat.slot("p");
59-
NumericVector x = mat.slot("x");
60-
58+
arma::urowvec i = Rcpp::as<arma::urowvec>(mat.slot("i"));
59+
arma::urowvec p = Rcpp::as<arma::urowvec>(mat.slot("p"));
60+
arma::vec x = Rcpp::as<arma::vec>(mat.slot("x"));
61+
6162
int nrow = dims[0], ncol = dims[1];
6263
arma::sp_mat res(nrow, ncol);
6364

6465
// create space for values, and copy
65-
arma::access::rw(res.values) =
66-
arma::memory::acquire_chunked<double>(x.size() + 1);
67-
arma::arrayops::copy(arma::access::rwp(res.values),
68-
x.begin(), x.size() + 1);
69-
70-
// create space for row_indices, and copy -- so far in a lame loop
71-
arma::access::rw(res.row_indices) =
72-
arma::memory::acquire_chunked<arma::uword>(x.size() + 1);
73-
for (int j=0; j<i.size(); j++)
74-
arma::access::rwp(res.row_indices)[j] = i[j];
66+
arma::access::rw(res.values) = arma::memory::acquire_chunked<double>(x.size() + 1);
67+
arma::arrayops::copy(arma::access::rwp(res.values), x.begin(), x.size() + 1);
68+
69+
// create space for row_indices, and copy
70+
arma::access::rw(res.row_indices) = arma::memory::acquire_chunked<arma::uword>(i.size() + 1);
71+
arma::arrayops::copy(arma::access::rwp(res.row_indices), i.begin(), i.size() + 1);
7572

76-
// create space for col_ptrs, and copy -- so far in a lame loop
77-
arma::access::rw(res.col_ptrs) =
78-
arma::memory::acquire<arma::uword>(p.size() + 2);
79-
for (int j=0; j<p.size(); j++)
80-
arma::access::rwp(res.col_ptrs)[j] = p[j];
73+
// create space for col_ptrs, and copy
74+
arma::access::rw(res.col_ptrs) = arma::memory::acquire<arma::uword>(p.size() + 2);
75+
arma::arrayops::copy(arma::access::rwp(res.col_ptrs), p.begin(), p.size() + 1);
8176

8277
// important: set the sentinel as well
83-
arma::access::rwp(res.col_ptrs)[p.size()+1] =
84-
std::numeric_limits<arma::uword>::max();
78+
arma::access::rwp(res.col_ptrs)[p.size()+1] = std::numeric_limits<arma::uword>::max();
8579

8680
// set the number of non-zero elements
8781
arma::access::rw(res.n_nonzero) = x.size();
@@ -95,7 +89,7 @@ Running this example shows the same matrix printed to `stdout` by
9589
Armadillo.
9690

9791
{% highlight r %}
98-
convertSparse(A)
92+
convertSparse(A)
9993
{% endhighlight %}
10094

10195

@@ -116,5 +110,7 @@ SpMat res:
116110

117111
Support for sparse matrix is currently still limited in Armadillo,
118112
but expected to grow. Likewise, RcppArmadillo does not yet have
119-
`as<>()` and `wrap()` converters but we expect to add these
113+
converters such as `as<>()` (though the example above does
114+
essentially everything that is needed) and `wrap()` converters.
115+
But we expect to add these
120116
eventually --- at which point this example will be much simpler.

src/2012-12-25-armadillo-sparse-matrix.cpp

+25-29
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
*/
1717

1818
/*** R
19-
suppressMessages(library(Matrix))
20-
i <- c(1,3:8)
21-
j <- c(2,9,6:10)
22-
x <- 7 * (1:7)
23-
A <- sparseMatrix(i, j, x = x)
24-
print(A)
25-
*/
19+
suppressMessages(library(Matrix))
20+
i <- c(1,3:8)
21+
j <- c(2,9,6:10)
22+
x <- 7 * (1:7)
23+
A <- sparseMatrix(i, j, x = x)
24+
print(A)
25+
*/
2626

2727
/**
2828
* The following C++ function access the corresponding slots of the
@@ -37,35 +37,29 @@ using namespace Rcpp ;
3737

3838
// [[Rcpp::export]]
3939
void convertSparse(S4 mat) { // slight improvement with two non-nested loops
40+
4041
IntegerVector dims = mat.slot("Dim");
41-
IntegerVector i = mat.slot("i");
42-
IntegerVector p = mat.slot("p");
43-
NumericVector x = mat.slot("x");
44-
42+
arma::urowvec i = Rcpp::as<arma::urowvec>(mat.slot("i"));
43+
arma::urowvec p = Rcpp::as<arma::urowvec>(mat.slot("p"));
44+
arma::vec x = Rcpp::as<arma::vec>(mat.slot("x"));
45+
4546
int nrow = dims[0], ncol = dims[1];
4647
arma::sp_mat res(nrow, ncol);
4748

4849
// create space for values, and copy
49-
arma::access::rw(res.values) =
50-
arma::memory::acquire_chunked<double>(x.size() + 1);
51-
arma::arrayops::copy(arma::access::rwp(res.values),
52-
x.begin(), x.size() + 1);
50+
arma::access::rw(res.values) = arma::memory::acquire_chunked<double>(x.size() + 1);
51+
arma::arrayops::copy(arma::access::rwp(res.values), x.begin(), x.size() + 1);
5352

54-
// create space for row_indices, and copy -- so far in a lame loop
55-
arma::access::rw(res.row_indices) =
56-
arma::memory::acquire_chunked<arma::uword>(x.size() + 1);
57-
for (int j=0; j<i.size(); j++)
58-
arma::access::rwp(res.row_indices)[j] = i[j];
53+
// create space for row_indices, and copy
54+
arma::access::rw(res.row_indices) = arma::memory::acquire_chunked<arma::uword>(i.size() + 1);
55+
arma::arrayops::copy(arma::access::rwp(res.row_indices), i.begin(), i.size() + 1);
5956

60-
// create space for col_ptrs, and copy -- so far in a lame loop
61-
arma::access::rw(res.col_ptrs) =
62-
arma::memory::acquire<arma::uword>(p.size() + 2);
63-
for (int j=0; j<p.size(); j++)
64-
arma::access::rwp(res.col_ptrs)[j] = p[j];
57+
// create space for col_ptrs, and copy
58+
arma::access::rw(res.col_ptrs) = arma::memory::acquire<arma::uword>(p.size() + 2);
59+
arma::arrayops::copy(arma::access::rwp(res.col_ptrs), p.begin(), p.size() + 1);
6560

6661
// important: set the sentinel as well
67-
arma::access::rwp(res.col_ptrs)[p.size()+1] =
68-
std::numeric_limits<arma::uword>::max();
62+
arma::access::rwp(res.col_ptrs)[p.size()+1] = std::numeric_limits<arma::uword>::max();
6963

7064
// set the number of non-zero elements
7165
arma::access::rw(res.n_nonzero) = x.size();
@@ -79,12 +73,14 @@ void convertSparse(S4 mat) { // slight improvement with two non-nested l
7973
*/
8074

8175
/*** R
82-
convertSparse(A)
76+
convertSparse(A)
8377
*/
8478

8579
/**
8680
* Support for sparse matrix is currently still limited in Armadillo,
8781
* but expected to grow. Likewise, RcppArmadillo does not yet have
88-
* `as<>()` and `wrap()` converters but we expect to add these
82+
* converters such as `as<>()` (though the example above does
83+
* essentially everything that is needed) and `wrap()` converters.
84+
* But we expect to add these
8985
* eventually --- at which point this example will be much simpler.
9086
*/

0 commit comments

Comments
 (0)