Rcpp Version 1.0.14
Loading...
Searching...
No Matches
Subsetter.h
Go to the documentation of this file.
1// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2//
3// Subsetter.h: Rcpp R/C++ interface class library -- vector subsetting
4//
5// Copyright (C) 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_Subsetter_h_
23#define Rcpp_vector_Subsetter_h_
24
25#include <limits>
26
27namespace Rcpp {
28
29template <
30 int RTYPE, template <class> class StoragePolicy,
31 int RHS_RTYPE, bool RHS_NA, typename RHS_T
32>
34
37
38public:
39
44
52
53 // Enable e.g. x[y] = z
54 template <int OtherRTYPE, template <class> class OtherStoragePolicy>
56 R_xlen_t n = other.size();
57
58 if (n == 1) {
59 for (R_xlen_t i=0; i < indices_n; ++i) {
60 lhs[ indices[i] ] = other[0];
61 }
62 } else if (n == indices_n) {
63 for (R_xlen_t i=0; i < n; ++i) {
64 lhs[ indices[i] ] = other[i];
65 }
66 } else {
67 stop("index error");
68 }
69 return *this;
70 }
71
72 // Enable e.g. x[y] = 1;
73 // TODO: std::enable_if<primitive> with C++11
75 for (R_xlen_t i=0; i < indices_n; ++i) {
76 lhs[ indices[i] ] = other;
77 }
78 return *this;
79 }
80
82 for (R_xlen_t i=0; i < indices_n; ++i) {
83 lhs[ indices[i] ] = other;
84 }
85 return *this;
86 }
87
88 SubsetProxy& operator=(const char* other) {
89 for (R_xlen_t i=0; i < indices_n; ++i) {
90 lhs[ indices[i] ] = other;
91 }
92 return *this;
93 }
94
96 for (R_xlen_t i=0; i < indices_n; ++i) {
97 lhs[ indices[i] ] = other;
98 }
99 return *this;
100 }
101
102 template <int RTYPE_OTHER, template <class> class StoragePolicyOther,int RHS_RTYPE_OTHER, bool RHS_NA_OTHER, typename RHS_T_OTHER>
109
111 if (other.indices_n == 1) {
112 for (R_xlen_t i=0; i < indices_n; ++i) {
113 lhs[ indices[i] ] = other.lhs[other.indices[0]];
114 }
115 }
116 else if (indices_n == other.indices_n) {
117 for (R_xlen_t i=0; i < indices_n; ++i)
118 lhs[ indices[i] ] = other.lhs[other.indices[i]];
119 }
120 else {
121 stop("index error");
122 }
123 return *this;
124 }
125
127 return get_vec();
128 }
129
130 operator SEXP() const {
131 return wrap( get_vec() );
132 }
133
134private:
135
136 template <typename IDX>
137 void check_indices(IDX* x, R_xlen_t n, R_xlen_t size) {
138#ifndef RCPP_NO_BOUNDS_CHECK
139 for (IDX i=0; i < n; ++i) {
140 if (x[i] < 0 or x[i] >= size) {
141 if(std::numeric_limits<IDX>::is_integer && size > std::numeric_limits<IDX>::max()) {
142 stop("use NumericVector to index an object of length %td", size);
143 }
144 stop("index error");
145 }
146 }
147#endif
148 }
149
151 indices.reserve(rhs_n);
152 int* ptr = INTEGER(rhs); // ok to use int * here, we'll catch any problems inside check_indices
154 for (R_xlen_t i=0; i < rhs_n; ++i) {
155 indices.push_back( rhs[i] );
156 }
158 }
159
161 indices.reserve(rhs_n);
162 std::vector<R_xlen_t> tmp(rhs.size()); // create temp R_xlen_t type indices from reals
163 for(size_t i = 0 ; i < tmp.size() ; ++i) {
164 tmp[i] = rhs[i];
165 }
167 for (R_xlen_t i=0; i < rhs_n; ++i) {
168 indices.push_back( tmp[i] );
169 }
171 }
172
174 indices.reserve(rhs_n);
176 if (Rf_isNull(names)) stop("names is null");
177 const SEXP* namesPtr = RCPP_STRING_PTR(names);
178 const SEXP* rhsPtr = RCPP_STRING_PTR(rhs);
179 for (R_xlen_t i = 0; i < rhs_n; ++i) {
180 const SEXP* match = std::find(namesPtr, namesPtr + lhs_n, *(rhsPtr + i));
181 if (match == namesPtr + lhs_n)
182 stop("not found");
183 indices.push_back(match - namesPtr);
184 }
185 indices_n = indices.size();
186 }
187
189 indices.reserve(rhs_n);
190 if (lhs_n != rhs_n) {
191 stop("logical subsetting requires vectors of identical size");
192 }
193 int* ptr = LOGICAL(rhs);
194 for (R_xlen_t i=0; i < rhs_n; ++i) {
195 if (ptr[i] == NA_INTEGER) {
196 stop("can't subset using a logical vector with NAs");
197 }
198 if (ptr[i]) {
199 indices.push_back(i);
200 }
201 }
202 indices_n = indices.size();
203 }
204
207 for (R_xlen_t i=0; i < indices_n; ++i) {
208 output[i] = lhs[ indices[i] ];
209 }
211 if (!Rf_isNull(names)) {
213 for (R_xlen_t i=0; i < indices_n; ++i) {
215 }
217 }
219 return output;
220 }
221
223 const RHS_t& rhs;
226
227 std::vector<R_xlen_t> indices;
228
229 // because of the above, we keep track of the size
231
232public:
233
234#define RCPP_GENERATE_SUBSET_PROXY_OPERATOR(__OPERATOR__) \
235 template <int RTYPE_OTHER, template <class> class StoragePolicyOther, \
236 int RHS_RTYPE_OTHER, bool RHS_NA_OTHER, typename RHS_T_OTHER> \
237 Vector<RTYPE, StoragePolicy> operator __OPERATOR__ ( \
238 const SubsetProxy<RTYPE_OTHER, StoragePolicyOther, RHS_RTYPE_OTHER, \
239 RHS_NA_OTHER, RHS_T_OTHER>& other) { \
240 Vector<RTYPE, StoragePolicy> result(indices_n); \
241 if (other.indices_n == 1) { \
242 for (R_xlen_t i = 0; i < indices_n; ++i) \
243 result[i] = lhs[indices[i]] __OPERATOR__ other.lhs[other.indices[0]]; \
244 } else if (indices_n == other.indices_n) { \
245 for (R_xlen_t i = 0; i < indices_n; ++i) \
246 result[i] = lhs[indices[i]] __OPERATOR__ other.lhs[other.indices[i]]; \
247 } else { \
248 stop("index error"); \
249 } \
250 return result; \
251 }
252
257
258#undef RCPP_GENERATE_SUBSET_PROXY_OPERATOR
259
260};
261
262}
263
264#endif
#define RCPP_GENERATE_SUBSET_PROXY_OPERATOR(__OPERATOR__)
Definition Subsetter.h:234
SubsetProxy & operator=(bool other)
Definition Subsetter.h:95
void get_indices(traits::identity< traits::int2type< REALSXP > > t)
Definition Subsetter.h:160
void get_indices(traits::identity< traits::int2type< STRSXP > > t)
Definition Subsetter.h:173
SubsetProxy & operator=(const char *other)
Definition Subsetter.h:88
void get_indices(traits::identity< traits::int2type< LGLSXP > > t)
Definition Subsetter.h:188
SubsetProxy & operator=(int other)
Definition Subsetter.h:81
SubsetProxy & operator=(const SubsetProxy< RTYPE_OTHER, StoragePolicyOther, RHS_RTYPE_OTHER, RHS_NA_OTHER, RHS_T_OTHER > &other)
Definition Subsetter.h:103
SubsetProxy & operator=(const Vector< OtherRTYPE, OtherStoragePolicy > &other)
Definition Subsetter.h:55
SubsetProxy & operator=(double other)
Definition Subsetter.h:74
void check_indices(IDX *x, R_xlen_t n, R_xlen_t size)
Definition Subsetter.h:137
void get_indices(traits::identity< traits::int2type< INTSXP > > t)
Definition Subsetter.h:150
SubsetProxy(const SubsetProxy &other)
Definition Subsetter.h:45
Vector< RTYPE, StoragePolicy > get_vec() const
Definition Subsetter.h:205
std::vector< R_xlen_t > indices
Definition Subsetter.h:227
SubsetProxy & operator=(const SubsetProxy &other)
Definition Subsetter.h:110
SubsetProxy(LHS_t &lhs_, const RHS_t &rhs_)
Definition Subsetter.h:40
Vector< RHS_RTYPE, StoragePolicy > RHS_t
Definition Subsetter.h:36
const RHS_t & rhs
Definition Subsetter.h:223
Vector< RTYPE, StoragePolicy > LHS_t
Definition Subsetter.h:35
R_xlen_t indices_n
Definition Subsetter.h:230
R_xlen_t size() const
Definition Vector.h:275
#define RCPP_STRING_PTR
Definition compat.h:28
Rcpp API.
Definition algo.h:28
void NORET stop(const std::string &message)
Definition exceptions.h:117
no_init_vector no_init(R_xlen_t size)
Definition no_init.h:77
T as(SEXP x)
Definition as.h:151
IntegerVector match(const VectorBase< RTYPE, NA, T > &x, const VectorBase< RTYPE, RHS_NA, RHS_T > &table_)
Definition match.h:28
SEXP wrap(const Date &date)
Definition Date.h:38