@@ -47,8 +47,10 @@ namespace Rcpp {
47
47
Subsetter () {};
48
48
49
49
// helper function used for the subset methods when going from logical to int
50
+ // operates like R's which, but returns NA when it encounters an NA
50
51
template <template <class > class OtherStoragePolicy >
51
52
static Vector<INTSXP, StoragePolicy> which_na ( const Vector<LGLSXP, OtherStoragePolicy>& x) {
53
+
52
54
std::vector<int > output;
53
55
int n = x.size ();
54
56
output.reserve (n);
@@ -70,6 +72,9 @@ namespace Rcpp {
70
72
// Subsetting for logicals
71
73
template <template <class > class OtherStoragePolicy >
72
74
inline Vector<RTYPE, StoragePolicy> subset_impl ( const VECTOR& this_, const Vector<LGLSXP, OtherStoragePolicy>& x ) const {
75
+ if (this_.size () != x.size ()) {
76
+ stop (" unequal vector sizes" );
77
+ }
73
78
Vector<INTSXP, StoragePolicy> tmp = which_na (x);
74
79
if (!tmp.size ()) return Vector<RTYPE, StoragePolicy>(0 );
75
80
else return subset_impl (this_, tmp);
@@ -78,40 +83,32 @@ namespace Rcpp {
78
83
// Subsetting for characters
79
84
template <template <class > class OtherStoragePolicy >
80
85
inline Vector<RTYPE, StoragePolicy> subset_impl ( const VECTOR& this_, const Vector<STRSXP, OtherStoragePolicy>& x ) const {
81
-
86
+
82
87
if (Rf_isNull ( Rf_getAttrib (this_, R_NamesSymbol) )) {
83
- int n = x.size ();
84
- Vector<RTYPE, StoragePolicy> output (n);
85
- for (int i=0 ; i < n; ++i) {
86
- output[i] = traits::get_na<RTYPE>();
87
- }
88
- return output;
88
+ stop (" Tried to subset a vector with no names using a CharacterVector" );
89
89
}
90
90
91
91
Vector<STRSXP, StoragePolicy> names = as< Vector<STRSXP, StoragePolicy> >(Rf_getAttrib (this_, R_NamesSymbol));
92
92
Vector<INTSXP, StoragePolicy> idx = match (x, names); // match returns 1-based index
93
- // apparently, we don't see sugar, so we have to do this manually
93
+
94
+ // apparently, we don't see sugar, so we have to populate an (index - 1) manually
94
95
Vector<INTSXP, StoragePolicy> idxm1 = no_init (idx.size ());
95
96
for (int i=0 ; i < idx.size (); ++i) {
96
97
idxm1[i] = idx[i] - 1 ;
97
98
}
99
+
98
100
Vector<RTYPE, StoragePolicy> output = subset_impl (this_, idxm1);
99
101
int n = output.size ();
100
102
if (n == 0 ) return Vector<RTYPE, StoragePolicy>(0 );
101
103
Vector<STRSXP, StoragePolicy> out_names = no_init (n);
102
104
for (int i=0 ; i < n; ++i) {
103
- if (idx[i] == NA_INTEGER) out_names[i] = NA_STRING;
104
- else out_names[i] = names[ idx[i] - 1 ];
105
+ out_names[i] = names[ idx[i] - 1 ];
105
106
}
106
107
output.attr (" names" ) = out_names;
107
108
return output;
108
109
}
109
110
110
- const VECTOR& vec;
111
- const T& other;
112
-
113
111
// Subsetting for integers -- note that it is 0-based
114
- // hidden until we decide whether to go with 0 or 1 based indexing
115
112
template <template <class > class OtherStoragePolicy >
116
113
inline Vector<RTYPE, StoragePolicy>
117
114
subset_impl ( const VECTOR this_, const Vector<INTSXP, OtherStoragePolicy>& x ) const {
@@ -120,8 +117,10 @@ namespace Rcpp {
120
117
Vector<RTYPE, StoragePolicy> output = no_init (n);
121
118
for (int i=0 ; i < n; ++i) {
122
119
if (x[i] == NA_INTEGER) output[i] = traits::get_na<RTYPE>();
123
- else if (x[i] < 0 ) stop (" Cannot subset with an integer vector with elements <= 0" );
124
- else if (x[i] > this_.size () - 1 ) output[i] = traits::get_na<RTYPE>();
120
+ #ifndef RCPP_NO_BOUNDS_CHECK
121
+ else if (x[i] < 0 ) stop (" Index error: tried to index < 0" );
122
+ else if (x[i] > this_.size () - 1 ) stop (" Index error: tried to index above vector size" );
123
+ #endif
125
124
else output[i] = (this_)[ x[i] ];
126
125
}
127
126
@@ -133,13 +132,25 @@ namespace Rcpp {
133
132
Vector<STRSXP, StoragePolicy> outnames = no_init (n);
134
133
for (int i=0 ; i < n; ++i) {
135
134
if (x[i] == NA_INTEGER) outnames[i] = NA_STRING;
135
+ #ifndef RCPP_NO_BOUNDS_CHECK
136
136
else if (x[i] > this_.size () - 1 ) outnames[i] = NA_STRING;
137
+ #endif
137
138
else if (x[i] >= 0 ) outnames[i] = thisnames[ x[i] ];
138
139
}
139
140
output.attr (" names" ) = outnames;
140
141
}
141
142
return wrap (output);
142
143
}
144
+
145
+ // Subsetting for numerics -- coerce to integer
146
+ template <template <class > class OtherStoragePolicy >
147
+ Vector<RTYPE, StoragePolicy>
148
+ subset_impl ( const VECTOR this_, const Vector<REALSXP, OtherStoragePolicy>& x ) const {
149
+ return subset_impl (this_, as< Vector<INTSXP, OtherStoragePolicy> >(x) );
150
+ }
151
+
152
+ const VECTOR& vec;
153
+ const T& other;
143
154
144
155
};
145
156
0 commit comments