Skip to content

Commit 6182955

Browse files
committed
Proxies for DimNames, allowing e.g. rownames(x) = ...
1 parent 85545f4 commit 6182955

File tree

6 files changed

+118
-1
lines changed

6 files changed

+118
-1
lines changed

ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2014-07-14 Kevin Ushey <kevinushey@gmail.com>
2+
3+
* inst/unitTests/runit.Matrix.R: DimNames Proxy
4+
* inst/unitTests/cpp/Matrix.cpp: Idem
5+
* inst/include/Rcpp/vector/Matrix.h: Idem
6+
* inst/include/Rcpp/vector/DimNameProxy.h: Idem
7+
18
2014-07-12 Dirk Eddelbuettel <edd@debian.org>
29

310
* inst/include/Rcpp/generated/InternalFunction__ctors.h: Regenerated

inst/include/Rcpp/Vector.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ namespace Rcpp{
5050
#include <Rcpp/vector/Vector.h>
5151
#include <Rcpp/vector/proxy.h>
5252
#include <Rcpp/vector/traits.h>
53+
54+
#include <Rcpp/vector/DimNameProxy.h>
55+
5356
#include <Rcpp/vector/Matrix.h>
5457
#include <Rcpp/vector/SubMatrix.h>
5558
#include <Rcpp/vector/MatrixRow.h>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
2+
//
3+
// DimNameProxy.h: Rcpp R/C++ interface class library -- dimension name proxy
4+
//
5+
// Copyright (C) 2010 - 2014 Dirk Eddelbuettel, Romain Francois and Kevin Ushey
6+
//
7+
// This file is part of Rcpp.
8+
//
9+
// Rcpp is free software: you can redistribute it and/or modify it
10+
// under the terms of the GNU General Public License as published by
11+
// the Free Software Foundation, either version 2 of the License, or
12+
// (at your option) any later version.
13+
//
14+
// Rcpp is distributed in the hope that it will be useful, but
15+
// WITHOUT ANY WARRANTY; without even the implied warranty of
16+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
// GNU General Public License for more details.
18+
//
19+
// You should have received a copy of the GNU General Public License
20+
// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
21+
22+
#ifndef Rcpp_vector_DimNameProxy_h
23+
#define Rcpp_vector_DimNameProxy_h
24+
25+
namespace Rcpp{
26+
namespace internal{
27+
28+
class DimNameProxy {
29+
30+
public:
31+
32+
DimNameProxy(SEXP data, int dim): data_(data), dim_(dim) {}
33+
DimNameProxy(DimNameProxy const& other):
34+
data_(other.data_), dim_(other.dim_) {}
35+
36+
inline DimNameProxy& operator=(SEXP other) {
37+
SEXP dim = Rf_getAttrib(data_, R_DimSymbol);
38+
if (INTEGER(dim)[dim_] != Rf_length(other)) {
39+
std::stringstream s;
40+
s << "dimension extent is '"
41+
<< INTEGER(dim)[dim_]
42+
<< "' while length of names is '"
43+
<< Rf_length(other)
44+
<< "'";
45+
stop(s.str());
46+
}
47+
SEXP dimnames = Rf_getAttrib(data_, R_DimNamesSymbol);
48+
SEXP dims = Rf_getAttrib(data_, R_DimSymbol);
49+
if (Rf_isNull(dimnames)) {
50+
Shield<SEXP> new_dimnames(Rf_allocVector(VECSXP, Rf_length(dims)));
51+
SET_VECTOR_ELT(new_dimnames, dim_, other);
52+
Rf_setAttrib(data_, R_DimNamesSymbol, new_dimnames);
53+
} else {
54+
SET_VECTOR_ELT(dimnames, dim_, other);
55+
}
56+
return *this;
57+
}
58+
59+
inline operator SEXP() const {
60+
SEXP dimnames = Rf_getAttrib(data_, R_DimNamesSymbol);
61+
return Rf_isNull(dimnames) ? (R_NilValue) : (VECTOR_ELT(dimnames, dim_));
62+
}
63+
64+
template <typename T>
65+
inline operator T() const {
66+
SEXP dimnames = Rf_getAttrib(data_, R_DimNamesSymbol);
67+
if (Rf_isNull(dimnames)) {
68+
return T();
69+
} else {
70+
return T(VECTOR_ELT(dimnames, dim_));
71+
}
72+
}
73+
74+
private:
75+
76+
SEXP data_;
77+
int dim_;
78+
};
79+
80+
}
81+
82+
}
83+
84+
#endif

inst/include/Rcpp/vector/Matrix.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,15 @@ class Matrix : public Vector<RTYPE, StoragePolicy>, public MatrixBase<RTYPE, tru
188188
}
189189
}
190190

191-
} ;
191+
};
192+
193+
inline internal::DimNameProxy rownames(SEXP x) {
194+
return internal::DimNameProxy(x, 0);
195+
}
196+
197+
inline internal::DimNameProxy colnames(SEXP x) {
198+
return internal::DimNameProxy(x, 1);
199+
}
192200

193201
}
194202

inst/unitTests/cpp/Matrix.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,9 @@ NumericMatrix runit_SubMatrix( ){
205205
return res;
206206
}
207207

208+
// [[Rcpp::export]]
209+
void runit_rownames_colnames_proxy(
210+
NumericMatrix x, CharacterVector row_names, CharacterVector col_names) {
211+
rownames(x) = row_names;
212+
colnames(x) = col_names;
213+
}

inst/unitTests/runit.Matrix.R

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,5 +146,14 @@ if (.runThisTest) {
146146
checkEquals(m, matrix_opequals(m))
147147
}
148148

149+
test.NumericMatrix.rownames.colnames.proxy <- function() {
150+
m <- matrix(as.numeric(1:4), nrow = 2)
151+
runit_rownames_colnames_proxy(m, letters[1:2], LETTERS[1:2])
152+
checkEquals(rownames(m), letters[1:2])
153+
checkEquals(colnames(m), LETTERS[1:2])
154+
checkException(runit_rownames_colnames_proxy(m, letters[1:3], letters[1:3]))
155+
checkException(runit_rownames_colnames_proxy(m, letters[1:2], NULL))
156+
}
157+
149158

150159
}

0 commit comments

Comments
 (0)