Skip to content

Commit 373a8b4

Browse files
committed
Reuse indices passed in when possible (ie, IntegerVector case)
1 parent 349c8a6 commit 373a8b4

File tree

1 file changed

+32
-25
lines changed

1 file changed

+32
-25
lines changed

inst/include/Rcpp/vector/Subsetter.h

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,29 +37,27 @@ class SubsetProxy {
3737

3838
SubsetProxy(LHS_t& lhs_, const RHS_t& rhs_):
3939
lhs(lhs_), rhs(rhs_), lhs_n(lhs.size()), rhs_n(rhs.size()) {
40-
41-
indices.reserve(rhs_n);
4240
get_indices( traits::identity< traits::int2type<RHS_RTYPE> >() );
43-
4441
}
4542

4643
SubsetProxy(const SubsetProxy& other):
4744
lhs(other.lhs),
4845
rhs(other.rhs),
4946
lhs_n(other.lhs_n),
5047
rhs_n(other.rhs_n),
51-
indices(other.indices) {}
48+
indices(other.indices),
49+
indices_n(other.indices_n) {}
5250

5351
// Enable e.g. x[y] = z
5452
template <int OtherRTYPE, template <class> class OtherStoragePolicy>
5553
SubsetProxy& operator=(const Vector<OtherRTYPE, OtherStoragePolicy>& other) {
5654
int n = other.size();
57-
if (indices.size() != n) stop("index error");
55+
if (indices_n != n) stop("index error");
5856
if (n == 1) {
5957
for (int i=0; i < n; ++i) {
6058
lhs[ indices[i] ] = other[0];
6159
}
62-
} else if (n == indices.size()) {
60+
} else if (n == indices_n) {
6361
for (int i=0; i < n; ++i) {
6462
lhs[ indices[i] ] = other[i];
6563
}
@@ -72,32 +70,28 @@ class SubsetProxy {
7270
// Enable e.g. x[y] = 1;
7371
// TODO: std::enable_if<primitive> with C++11
7472
SubsetProxy& operator=(double other) {
75-
int n = indices.size();
76-
for (int i=0; i < n; ++i) {
73+
for (int i=0; i < indices_n; ++i) {
7774
lhs[ indices[i] ] = other;
7875
}
7976
return *this;
8077
}
8178

8279
SubsetProxy& operator=(int other) {
83-
int n = indices.size();
84-
for (int i=0; i < n; ++i) {
80+
for (int i=0; i < indices_n; ++i) {
8581
lhs[ indices[i] ] = other;
8682
}
8783
return *this;
8884
}
8985

9086
SubsetProxy& operator=(const char* other) {
91-
int n = indices.size();
92-
for (int i=0; i < n; ++i) {
87+
for (int i=0; i < indices_n; ++i) {
9388
lhs[ indices[i] ] = other;
9489
}
9590
return *this;
9691
}
9792

9893
SubsetProxy& operator=(bool other) {
99-
int n = indices.size();
100-
for (int i=0; i < n; ++i) {
94+
for (int i=0; i < indices_n; ++i) {
10195
lhs[ indices[i] ] = other;
10296
}
10397
return *this;
@@ -126,29 +120,31 @@ class SubsetProxy {
126120
#endif
127121

128122
void get_indices( traits::identity< traits::int2type<INTSXP> > t ) {
129-
int* ptr = INTEGER( rhs );
130-
check_indices(ptr, rhs_n, lhs_n);
131-
for (int i=0; i < rhs_n; ++i) {
132-
indices.push_back( ptr[i] );
133-
}
123+
indices = INTEGER(rhs);
124+
indices_n = rhs_n;
125+
check_indices(indices, rhs_n, lhs_n);
134126
}
135127

136128
void get_indices( traits::identity< traits::int2type<REALSXP> > t ) {
129+
indices.reserve(rhs_n);
137130
Vector<INTSXP, StoragePolicy> tmp =
138131
as< Vector<INTSXP, StoragePolicy> >(rhs);
139132
int* ptr = INTEGER(tmp);
140133
check_indices(ptr, rhs_n, lhs_n);
141134
for (int i=0; i < rhs_n; ++i) {
142135
indices.push_back( tmp[i] );
143136
}
137+
indices_n = rhs_n;
144138
}
145139

146140
void get_indices( traits::identity< traits::int2type<STRSXP> > t ) {
141+
indices.reserve(rhs_n);
147142
SEXP names = Rf_getAttrib(lhs, R_NamesSymbol);
148143
if (Rf_isNull(names)) stop("names is null");
149144
for (int i=0; i < rhs_n; ++i) {
150145
indices.push_back( find(names, CHAR( STRING_ELT(rhs, i) )) );
151146
}
147+
indices_n = indices.size();
152148
}
153149

154150
int find(const RHS_t& names, const char* str) {
@@ -160,6 +156,7 @@ class SubsetProxy {
160156
}
161157

162158
void get_indices( traits::identity< traits::int2type<LGLSXP> > t ) {
159+
indices.reserve(rhs_n);
163160
if (lhs_n != rhs_n) {
164161
stop("logical subsetting requires vectors of identical size");
165162
}
@@ -172,18 +169,18 @@ class SubsetProxy {
172169
indices.push_back(i);
173170
}
174171
}
172+
indices_n = indices.size();
175173
}
176174

177175
Vector<RTYPE, StoragePolicy> get_vec() const {
178-
int n = indices.size();
179-
Vector<RTYPE, StoragePolicy> output = no_init(n);
180-
for (int i=0; i < n; ++i) {
176+
Vector<RTYPE, StoragePolicy> output = no_init(indices_n);
177+
for (int i=0; i < indices_n; ++i) {
181178
output[i] = lhs[ indices[i] ];
182179
}
183180
SEXP names = Rf_getAttrib(lhs, R_NamesSymbol);
184181
if (!Rf_isNull(names)) {
185-
Shield<SEXP> out_names( Rf_allocVector(STRSXP, n) );
186-
for (int i=0; i < n; ++i) {
182+
Shield<SEXP> out_names( Rf_allocVector(STRSXP, indices_n) );
183+
for (int i=0; i < indices_n; ++i) {
187184
SET_STRING_ELT(out_names, i, STRING_ELT(names, indices[i]));
188185
}
189186
Rf_setAttrib(output, R_NamesSymbol, out_names);
@@ -196,7 +193,17 @@ class SubsetProxy {
196193
const RHS_t& rhs;
197194
int lhs_n;
198195
int rhs_n;
199-
std::vector<int> indices;
196+
197+
// we want to reuse the indices if an IntegerVector is passed in; otherwise,
198+
// we construct a std::vector<int> to hold the indices
199+
typename traits::if_<
200+
RHS_RTYPE == INTSXP,
201+
int*,
202+
std::vector<int>
203+
>::type indices;
204+
205+
// because of the above, we keep track of the size
206+
int indices_n;
200207

201208
};
202209

0 commit comments

Comments
 (0)