Rcpp Version 0.12.12
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 namespace Rcpp {
26 
27 template <
28  int RTYPE, template <class> class StoragePolicy,
29  int RHS_RTYPE, bool RHS_NA, typename RHS_T
30 >
31 class SubsetProxy {
32 
35 
36 public:
37 
38  SubsetProxy(LHS_t& lhs_, const RHS_t& rhs_):
39  lhs(lhs_), rhs(rhs_), lhs_n(lhs.size()), rhs_n(rhs.size()) {
41  }
42 
43  SubsetProxy(const SubsetProxy& other):
44  lhs(other.lhs),
45  rhs(other.rhs),
46  lhs_n(other.lhs_n),
47  rhs_n(other.rhs_n),
48  indices(other.indices),
49  indices_n(other.indices_n) {}
50 
51  // Enable e.g. x[y] = z
52  template <int OtherRTYPE, template <class> class OtherStoragePolicy>
54  int n = other.size();
55 
56  if (n == 1) {
57  for (int i=0; i < indices_n; ++i) {
58  lhs[ indices[i] ] = other[0];
59  }
60  } else if (n == indices_n) {
61  for (int i=0; i < n; ++i) {
62  lhs[ indices[i] ] = other[i];
63  }
64  } else {
65  stop("index error");
66  }
67  return *this;
68  }
69 
70  // Enable e.g. x[y] = 1;
71  // TODO: std::enable_if<primitive> with C++11
72  SubsetProxy& operator=(double other) {
73  for (int i=0; i < indices_n; ++i) {
74  lhs[ indices[i] ] = other;
75  }
76  return *this;
77  }
78 
79  SubsetProxy& operator=(int other) {
80  for (int i=0; i < indices_n; ++i) {
81  lhs[ indices[i] ] = other;
82  }
83  return *this;
84  }
85 
86  SubsetProxy& operator=(const char* other) {
87  for (int i=0; i < indices_n; ++i) {
88  lhs[ indices[i] ] = other;
89  }
90  return *this;
91  }
92 
93  SubsetProxy& operator=(bool other) {
94  for (int i=0; i < indices_n; ++i) {
95  lhs[ indices[i] ] = other;
96  }
97  return *this;
98  }
99 
100  template <int RTYPE_OTHER, template <class> class StoragePolicyOther,int RHS_RTYPE_OTHER, bool RHS_NA_OTHER, typename RHS_T_OTHER>
102 
103  Vector<RTYPE_OTHER, StoragePolicyOther> other_vec = other;
104  *this = other_vec;
105  return *this;
106  }
107 
109  if (other.indices_n == 1) {
110  for (int i=0; i < indices_n; ++i) {
111  lhs[ indices[i] ] = other.lhs[other.indices[0]];
112  }
113  }
114  else if (indices_n == other.indices_n) {
115  for (int i=0; i < indices_n; ++i)
116  lhs[ indices[i] ] = other.lhs[other.indices[i]];
117  }
118  else {
119  stop("index error");
120  }
121  return *this;
122  }
123 
124  operator Vector<RTYPE, StoragePolicy>() const {
125  return get_vec();
126  }
127 
128  operator SEXP() const {
129  return wrap( get_vec() );
130  }
131 
132 private:
133 
134  #ifndef RCPP_NO_BOUNDS_CHECK
135  void check_indices(int* x, int n, int size) {
136  for (int i=0; i < n; ++i) {
137  if (x[i] < 0 or x[i] >= size) {
138  stop("index error");
139  }
140  }
141  }
142  #else
143  void check_indices(int* x, int n, int size) {}
144  #endif
145 
147  indices.reserve(rhs_n);
148  int* ptr = INTEGER(rhs);
149  check_indices(ptr, rhs_n, lhs_n);
150  for (int i=0; i < rhs_n; ++i) {
151  indices.push_back( rhs[i] );
152  }
153  indices_n = rhs_n;
154  }
155 
157  indices.reserve(rhs_n);
159  as< Vector<INTSXP, StoragePolicy> >(rhs);
160  int* ptr = INTEGER(tmp);
161  check_indices(ptr, rhs_n, lhs_n);
162  for (int i=0; i < rhs_n; ++i) {
163  indices.push_back( tmp[i] );
164  }
165  indices_n = rhs_n;
166  }
167 
169  indices.reserve(rhs_n);
170  SEXP names = Rf_getAttrib(lhs, R_NamesSymbol);
171  if (Rf_isNull(names)) stop("names is null");
172  SEXP* namesPtr = STRING_PTR(names);
173  SEXP* rhsPtr = STRING_PTR(rhs);
174  for (int i = 0; i < rhs_n; ++i) {
175  SEXP* match = std::find(namesPtr, namesPtr + lhs_n, *(rhsPtr + i));
176  if (match == namesPtr + lhs_n)
177  stop("not found");
178  indices.push_back(match - namesPtr);
179  }
180  indices_n = indices.size();
181  }
182 
184  indices.reserve(rhs_n);
185  if (lhs_n != rhs_n) {
186  stop("logical subsetting requires vectors of identical size");
187  }
188  int* ptr = LOGICAL(rhs);
189  for (int i=0; i < rhs_n; ++i) {
190  if (ptr[i] == NA_INTEGER) {
191  stop("can't subset using a logical vector with NAs");
192  }
193  if (ptr[i]) {
194  indices.push_back(i);
195  }
196  }
197  indices_n = indices.size();
198  }
199 
202  for (int i=0; i < indices_n; ++i) {
203  output[i] = lhs[ indices[i] ];
204  }
205  SEXP names = Rf_getAttrib(lhs, R_NamesSymbol);
206  if (!Rf_isNull(names)) {
207  Shield<SEXP> out_names( Rf_allocVector(STRSXP, indices_n) );
208  for (int i=0; i < indices_n; ++i) {
209  SET_STRING_ELT(out_names, i, STRING_ELT(names, indices[i]));
210  }
211  Rf_setAttrib(output, R_NamesSymbol, out_names);
212  }
213  Rf_copyMostAttrib(lhs, output);
214  return output;
215  }
216 
217  LHS_t& lhs;
218  const RHS_t& rhs;
219  int lhs_n;
220  int rhs_n;
221 
222  std::vector<int> indices;
223 
224  // because of the above, we keep track of the size
226 
227 public:
228 
229 #define RCPP_GENERATE_SUBSET_PROXY_OPERATOR(__OPERATOR__) \
230  template <int RTYPE_OTHER, template <class> class StoragePolicyOther, \
231  int RHS_RTYPE_OTHER, bool RHS_NA_OTHER, typename RHS_T_OTHER> \
232  Vector<RTYPE, StoragePolicy> operator __OPERATOR__ ( \
233  const SubsetProxy<RTYPE_OTHER, StoragePolicyOther, RHS_RTYPE_OTHER, \
234  RHS_NA_OTHER, RHS_T_OTHER>& other) { \
235  Vector<RTYPE, StoragePolicy> result(indices_n); \
236  if (other.indices_n == 1) { \
237  for (int i = 0; i < indices_n; ++i) \
238  result[i] = lhs[indices[i]] __OPERATOR__ other.lhs[other.indices[0]]; \
239  } else if (indices_n == other.indices_n) { \
240  for (int i = 0; i < indices_n; ++i) \
241  result[i] = lhs[indices[i]] __OPERATOR__ other.lhs[other.indices[i]]; \
242  } else { \
243  stop("index error"); \
244  } \
245  return result; \
246  }
247 
252 
253 #undef RCPP_GENERATE_SUBSET_PROXY_OPERATOR
254 
255 };
256 
257 }
258 
259 #endif
const RHS_t & rhs
Definition: Subsetter.h:218
SubsetProxy(const SubsetProxy &other)
Definition: Subsetter.h:43
SubsetProxy & operator=(bool other)
Definition: Subsetter.h:93
no_init_vector no_init(R_xlen_t size)
Definition: no_init.h:69
Vector< RTYPE, StoragePolicy > LHS_t
Definition: Subsetter.h:33
SubsetProxy & operator=(const SubsetProxy< RTYPE_OTHER, StoragePolicyOther, RHS_RTYPE_OTHER, RHS_NA_OTHER, RHS_T_OTHER > &other)
Definition: Subsetter.h:101
SubsetProxy & operator=(const SubsetProxy &other)
Definition: Subsetter.h:108
SubsetProxy & operator=(int other)
Definition: Subsetter.h:79
Vector< RTYPE, StoragePolicy > get_vec() const
Definition: Subsetter.h:200
SEXP find(const std::string &name) const
Definition: Environment.h:149
void get_indices(traits::identity< traits::int2type< INTSXP > > t)
Definition: Subsetter.h:146
std::vector< int > indices
Definition: Subsetter.h:222
R_xlen_t size() const
Definition: Vector.h:274
Vector< RHS_RTYPE, StoragePolicy > RHS_t
Definition: Subsetter.h:34
SubsetProxy & operator=(const Vector< OtherRTYPE, OtherStoragePolicy > &other)
Definition: Subsetter.h:53
SubsetProxy & operator=(double other)
Definition: Subsetter.h:72
SubsetProxy(LHS_t &lhs_, const RHS_t &rhs_)
Definition: Subsetter.h:38
SEXP wrap(const Date &date)
Definition: Date.h:38
void NORET stop(const char *fmt, Args &&...args)
Definition: exceptions.h:51
SubsetProxy & operator=(const char *other)
Definition: Subsetter.h:86
Rcpp API.
Definition: algo.h:28
void get_indices(traits::identity< traits::int2type< STRSXP > > t)
Definition: Subsetter.h:168
void get_indices(traits::identity< traits::int2type< LGLSXP > > t)
Definition: Subsetter.h:183
IntegerVector match(const VectorBase< RTYPE, NA, T > &x, const VectorBase< RTYPE, RHS_NA, RHS_T > &table_)
Definition: match.h:28
void get_indices(traits::identity< traits::int2type< REALSXP > > t)
Definition: Subsetter.h:156
void check_indices(int *x, int n, int size)
Definition: Subsetter.h:135
#define RCPP_GENERATE_SUBSET_PROXY_OPERATOR(__OPERATOR__)
Definition: Subsetter.h:229