Skip to content

Commit 1cc6a00

Browse files
committed
Correctly set dimnames for matrices
1 parent 05c888b commit 1cc6a00

File tree

8 files changed

+1442
-1449
lines changed

8 files changed

+1442
-1449
lines changed

cpp11test/R/cpp11.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ row_sums <- function(x) {
108108
.Call(`_cpp11test_row_sums`, x)
109109
}
110110

111+
mat_mat_copy_dimnames <- function(x) {
112+
.Call(`_cpp11test_mat_mat_copy_dimnames`, x)
113+
}
114+
115+
mat_sexp_copy_dimnames <- function(x) {
116+
.Call(`_cpp11test_mat_sexp_copy_dimnames`, x)
117+
}
118+
119+
mat_mat_create_dimnames <- function() {
120+
.Call(`_cpp11test_mat_mat_create_dimnames`)
121+
}
122+
111123
col_sums <- function(x) {
112124
.Call(`_cpp11test_col_sums`, x)
113125
}

cpp11test/src/cpp11.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,27 @@ extern "C" SEXP _cpp11test_row_sums(SEXP x) {
209209
END_CPP11
210210
}
211211
// matrix.cpp
212+
cpp11::doubles_matrix<> mat_mat_copy_dimnames(cpp11::doubles_matrix<> x);
213+
extern "C" SEXP _cpp11test_mat_mat_copy_dimnames(SEXP x) {
214+
BEGIN_CPP11
215+
return cpp11::as_sexp(mat_mat_copy_dimnames(cpp11::as_cpp<cpp11::decay_t<cpp11::doubles_matrix<>>>(x)));
216+
END_CPP11
217+
}
218+
// matrix.cpp
219+
SEXP mat_sexp_copy_dimnames(cpp11::doubles_matrix<> x);
220+
extern "C" SEXP _cpp11test_mat_sexp_copy_dimnames(SEXP x) {
221+
BEGIN_CPP11
222+
return cpp11::as_sexp(mat_sexp_copy_dimnames(cpp11::as_cpp<cpp11::decay_t<cpp11::doubles_matrix<>>>(x)));
223+
END_CPP11
224+
}
225+
// matrix.cpp
226+
cpp11::doubles_matrix<> mat_mat_create_dimnames();
227+
extern "C" SEXP _cpp11test_mat_mat_create_dimnames() {
228+
BEGIN_CPP11
229+
return cpp11::as_sexp(mat_mat_create_dimnames());
230+
END_CPP11
231+
}
232+
// matrix.cpp
212233
cpp11::doubles col_sums(cpp11::doubles_matrix<cpp11::by_column> x);
213234
extern "C" SEXP _cpp11test_col_sums(SEXP x) {
214235
BEGIN_CPP11
@@ -488,6 +509,9 @@ static const R_CallMethodDef CallEntries[] = {
488509
{"_cpp11test_gibbs_rcpp", (DL_FUNC) &_cpp11test_gibbs_rcpp, 2},
489510
{"_cpp11test_gibbs_rcpp2", (DL_FUNC) &_cpp11test_gibbs_rcpp2, 2},
490511
{"_cpp11test_grow_", (DL_FUNC) &_cpp11test_grow_, 1},
512+
{"_cpp11test_mat_mat_copy_dimnames", (DL_FUNC) &_cpp11test_mat_mat_copy_dimnames, 1},
513+
{"_cpp11test_mat_mat_create_dimnames", (DL_FUNC) &_cpp11test_mat_mat_create_dimnames, 0},
514+
{"_cpp11test_mat_sexp_copy_dimnames", (DL_FUNC) &_cpp11test_mat_sexp_copy_dimnames, 1},
491515
{"_cpp11test_my_message", (DL_FUNC) &_cpp11test_my_message, 2},
492516
{"_cpp11test_my_message_n1", (DL_FUNC) &_cpp11test_my_message_n1, 1},
493517
{"_cpp11test_my_message_n1fmt", (DL_FUNC) &_cpp11test_my_message_n1fmt, 1},

cpp11test/src/matrix.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "cpp11/matrix.hpp"
22
#include "Rmath.h"
33
#include "cpp11/doubles.hpp"
4+
#include "cpp11/list.hpp"
5+
#include "cpp11/strings.hpp"
46
using namespace cpp11;
57

68
[[cpp11::register]] SEXP gibbs_cpp(int N, int thin) {
@@ -86,6 +88,40 @@ using namespace Rcpp;
8688
return sums;
8789
}
8890

91+
[[cpp11::register]] cpp11::doubles_matrix<> mat_mat_copy_dimnames(
92+
cpp11::doubles_matrix<> x) {
93+
cpp11::writable::doubles_matrix<> out = x;
94+
95+
out.attr("dimnames") = x.attr("dimnames");
96+
97+
return out;
98+
}
99+
100+
[[cpp11::register]] SEXP mat_sexp_copy_dimnames(cpp11::doubles_matrix<> x) {
101+
cpp11::writable::doubles_matrix<> out = x;
102+
103+
out.attr("dimnames") = x.attr("dimnames");
104+
105+
return out;
106+
}
107+
108+
[[cpp11::register]] cpp11::doubles_matrix<> mat_mat_create_dimnames() {
109+
cpp11::writable::doubles_matrix<> out(2, 2);
110+
111+
out(0, 0) = 1;
112+
out(0, 1) = 2;
113+
out(1, 0) = 3;
114+
out(1, 1) = 4;
115+
116+
cpp11::writable::list dimnames(2);
117+
dimnames[0] = cpp11::strings({"a", "b"});
118+
dimnames[1] = cpp11::strings({"c", "d"});
119+
120+
out.attr("dimnames") = dimnames;
121+
122+
return out;
123+
}
124+
89125
[[cpp11::register]] cpp11::doubles col_sums(cpp11::doubles_matrix<cpp11::by_column> x) {
90126
cpp11::writable::doubles sums(x.ncol());
91127

cpp11test/tests/testthat/test-matrix.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,19 @@ test_that("col_sums gives same result as colSums", {
2323
y[3, ] <- NA;
2424
expect_equal(col_sums(y), colSums(y))
2525
})
26+
27+
test_that("doubles_matrix<> can return a matrix with colnames and rownames", {
28+
x <- matrix(c(1, 2, 3, 4), nrow = 2, ncol = 2)
29+
colnames(x) <- letters[1:2]
30+
rownames(x) <- letters[3:4]
31+
32+
y <- mat_mat_copy_dimnames(x)
33+
z <- mat_sexp_copy_dimnames(x)
34+
35+
expect_equal(x, y)
36+
expect_equal(x, z)
37+
38+
r <- mat_mat_create_dimnames()
39+
expect_equal(rownames(r), c("a", "b"))
40+
expect_equal(colnames(r), c("c", "d"))
41+
})

inst/include/cpp11/matrix.hpp

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
#pragma once
22

3+
#include <initializer_list> // for initializer_list
34
#include <iterator>
45
#include <string> // for string
56

6-
#include "cpp11/R.hpp" // for SEXP, SEXPREC, R_xlen_t, INT...
7-
#include "cpp11/r_bool.hpp" // for r_bool
8-
#include "cpp11/r_string.hpp" // for r_string
9-
#include "cpp11/r_vector.hpp" // for r_vector
10-
#include "cpp11/sexp.hpp" // for sexp
7+
#include "cpp11/R.hpp" // for SEXP, SEXPREC, R_xlen_t, INT...
8+
#include "cpp11/attribute_proxy.hpp" // for attribute_proxy
9+
#include "cpp11/r_bool.hpp" // for r_bool
10+
#include "cpp11/r_string.hpp" // for r_string
11+
#include "cpp11/r_vector.hpp" // for r_vector
12+
#include "cpp11/sexp.hpp" // for sexp
1113

1214
namespace cpp11 {
1315

@@ -190,11 +192,49 @@ class matrix : public matrix_slices<S> {
190192

191193
// operator sexp() { return sexp(vector_); }
192194

193-
sexp attr(const char* name) const { return SEXP(vector_.attr(name)); }
195+
attribute_proxy<V> attr(const char* name) { return attribute_proxy<V>(vector_, name); }
194196

195-
sexp attr(const std::string& name) const { return SEXP(vector_.attr(name)); }
197+
attribute_proxy<V> attr(const std::string& name) {
198+
return attribute_proxy<V>(vector_, name.c_str());
199+
}
200+
201+
attribute_proxy<V> attr(SEXP name) { return attribute_proxy<V>(vector_, name); }
202+
203+
void attr(const char* name, SEXP value) { vector_.attr(name) = value; }
204+
205+
void attr(const std::string& name, SEXP value) { vector_.attr(name) = value; }
196206

197-
sexp attr(SEXP name) const { return SEXP(vector_.attr(name)); }
207+
void attr(SEXP name, SEXP value) { vector_.attr(name) = value; }
208+
209+
void attr(const char* name, std::initializer_list<SEXP> value) {
210+
SEXP attr = PROTECT(Rf_allocVector(VECSXP, value.size()));
211+
int i = 0;
212+
for (SEXP v : value) {
213+
SET_VECTOR_ELT(attr, i++, v);
214+
}
215+
vector_.attr(name) = attr;
216+
UNPROTECT(1);
217+
}
218+
219+
void attr(const std::string& name, std::initializer_list<SEXP> value) {
220+
SEXP attr = PROTECT(Rf_allocVector(VECSXP, value.size()));
221+
int i = 0;
222+
for (SEXP v : value) {
223+
SET_VECTOR_ELT(attr, i++, v);
224+
}
225+
vector_.attr(name) = attr;
226+
UNPROTECT(1);
227+
}
228+
229+
void attr(SEXP name, std::initializer_list<SEXP> value) {
230+
SEXP attr = PROTECT(Rf_allocVector(VECSXP, value.size()));
231+
int i = 0;
232+
for (SEXP v : value) {
233+
SET_VECTOR_ELT(attr, i++, v);
234+
}
235+
vector_.attr(name) = attr;
236+
UNPROTECT(1);
237+
}
198238

199239
r_vector<r_string> names() const { return r_vector<r_string>(vector_.names()); }
200240

0 commit comments

Comments
 (0)