|
24 | 24 |
|
25 | 25 | namespace Rcpp {
|
26 | 26 |
|
27 |
| -template <int RTYPE, template <class> class StoragePolicy, typename T> |
28 |
| -class Subsetter { |
| 27 | + template <int RTYPE, template <class> class StoragePolicy, typename T> |
| 28 | + class Subsetter { |
29 | 29 |
|
30 |
| - typedef Vector<RTYPE, StoragePolicy> VECTOR; |
| 30 | + typedef Vector<RTYPE, StoragePolicy> VECTOR; |
31 | 31 |
|
32 |
| - public: |
| 32 | + public: |
33 | 33 |
|
34 |
| - explicit Subsetter(const Subsetter& rhs): vec(rhs.vec), other(rhs.other) {}; |
35 |
| - Subsetter(const VECTOR& vec_, const T& other_): vec(vec_), other(other_) {}; |
| 34 | + explicit Subsetter(const Subsetter& rhs): vec(rhs.vec), other(rhs.other) {}; |
| 35 | + Subsetter(const VECTOR& vec_, const T& other_): vec(vec_), other(other_) {}; |
36 | 36 |
|
37 |
| - inline operator SEXP() const { |
38 |
| - return subset_impl(vec, other).get__(); |
39 |
| - } |
| 37 | + inline operator SEXP() const { |
| 38 | + return subset_impl(vec, other).get__(); |
| 39 | + } |
40 | 40 |
|
41 |
| - inline operator VECTOR() const { |
42 |
| - return subset_impl(vec, other); |
43 |
| - } |
| 41 | + inline operator VECTOR() const { |
| 42 | + return subset_impl(vec, other); |
| 43 | + } |
44 | 44 |
|
45 |
| - private: |
| 45 | + private: |
46 | 46 |
|
47 |
| - Subsetter() {}; |
| 47 | + Subsetter() {}; |
48 | 48 |
|
49 |
| - // helper function used for the subset methods when going from logical to int |
50 |
| - template <template <class> class OtherStoragePolicy> |
51 |
| - static Vector<INTSXP, StoragePolicy> which_na( const Vector<LGLSXP, OtherStoragePolicy>& x) { |
52 |
| - std::vector<int> output; |
53 |
| - int n = x.size(); |
54 |
| - output.reserve(n); |
55 |
| - for (int i=0; i < n; ++i) { |
56 |
| - if (x[i] == NA_LOGICAL) { |
57 |
| - output.push_back(NA_INTEGER); |
58 |
| - } else if (x[i]) { |
59 |
| - output.push_back(i); |
60 |
| - } |
61 |
| - } |
62 |
| - int n_ = output.size(); |
63 |
| - Vector<INTSXP, StoragePolicy> output_ = no_init(n_); |
64 |
| - for (int i=0; i < n_; ++i) { |
65 |
| - output_[i] = output[i]; |
66 |
| - }; |
67 |
| - return output_; |
68 |
| - } |
| 49 | + // helper function used for the subset methods when going from logical to int |
| 50 | + template <template <class> class OtherStoragePolicy> |
| 51 | + static Vector<INTSXP, StoragePolicy> which_na( const Vector<LGLSXP, OtherStoragePolicy>& x) { |
| 52 | + std::vector<int> output; |
| 53 | + int n = x.size(); |
| 54 | + output.reserve(n); |
| 55 | + for (int i=0; i < n; ++i) { |
| 56 | + if (x[i] == NA_LOGICAL) { |
| 57 | + output.push_back(NA_INTEGER); |
| 58 | + } else if (x[i]) { |
| 59 | + output.push_back(i); |
| 60 | + } |
| 61 | + } |
| 62 | + int n_ = output.size(); |
| 63 | + Vector<INTSXP, StoragePolicy> output_ = no_init(n_); |
| 64 | + for (int i=0; i < n_; ++i) { |
| 65 | + output_[i] = output[i]; |
| 66 | + }; |
| 67 | + return output_; |
| 68 | + } |
69 | 69 |
|
70 |
| - // Subsetting for logicals |
71 |
| - template <template <class> class OtherStoragePolicy> |
72 |
| - inline Vector<RTYPE, StoragePolicy> subset_impl( const VECTOR& this_, const Vector<LGLSXP, OtherStoragePolicy>& x ) const { |
73 |
| - Vector<INTSXP, StoragePolicy> tmp = which_na(x); |
74 |
| - if (!tmp.size()) return Vector<RTYPE, StoragePolicy>(0); |
75 |
| - else return subset_impl(this_, tmp); |
76 |
| - } |
| 70 | + // Subsetting for logicals |
| 71 | + template <template <class> class OtherStoragePolicy> |
| 72 | + inline Vector<RTYPE, StoragePolicy> subset_impl( const VECTOR& this_, const Vector<LGLSXP, OtherStoragePolicy>& x ) const { |
| 73 | + Vector<INTSXP, StoragePolicy> tmp = which_na(x); |
| 74 | + if (!tmp.size()) return Vector<RTYPE, StoragePolicy>(0); |
| 75 | + else return subset_impl(this_, tmp); |
| 76 | + } |
77 | 77 |
|
78 |
| - // Subsetting for characters |
79 |
| - template <template <class> class OtherStoragePolicy> |
80 |
| - inline Vector<RTYPE, StoragePolicy> subset_impl( const VECTOR& this_, const Vector<STRSXP, OtherStoragePolicy>& x ) const { |
| 78 | + // Subsetting for characters |
| 79 | + template <template <class> class OtherStoragePolicy> |
| 80 | + inline Vector<RTYPE, StoragePolicy> subset_impl( const VECTOR& this_, const Vector<STRSXP, OtherStoragePolicy>& x ) const { |
81 | 81 |
|
82 |
| - 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; |
89 |
| - } |
| 82 | + 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; |
| 89 | + } |
90 | 90 |
|
91 |
| - Vector<STRSXP, StoragePolicy> names = as< Vector<STRSXP, StoragePolicy> >(Rf_getAttrib(this_, R_NamesSymbol)); |
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 |
94 |
| - Vector<INTSXP, StoragePolicy> idxm1 = no_init(idx.size()); |
95 |
| - for (int i=0; i < idx.size(); ++i) { |
96 |
| - idxm1[i] = idx[i] - 1; |
97 |
| - } |
98 |
| - Vector<RTYPE, StoragePolicy> output = subset_impl(this_, idxm1); |
99 |
| - int n = output.size(); |
100 |
| - if (n == 0) return Vector<RTYPE, StoragePolicy>(0); |
101 |
| - Vector<STRSXP, StoragePolicy> out_names = no_init(n); |
102 |
| - 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 |
| - } |
106 |
| - output.attr("names") = out_names; |
107 |
| - return output; |
108 |
| - } |
| 91 | + Vector<STRSXP, StoragePolicy> names = as< Vector<STRSXP, StoragePolicy> >(Rf_getAttrib(this_, R_NamesSymbol)); |
| 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 |
| 94 | + Vector<INTSXP, StoragePolicy> idxm1 = no_init(idx.size()); |
| 95 | + for (int i=0; i < idx.size(); ++i) { |
| 96 | + idxm1[i] = idx[i] - 1; |
| 97 | + } |
| 98 | + Vector<RTYPE, StoragePolicy> output = subset_impl(this_, idxm1); |
| 99 | + int n = output.size(); |
| 100 | + if (n == 0) return Vector<RTYPE, StoragePolicy>(0); |
| 101 | + Vector<STRSXP, StoragePolicy> out_names = no_init(n); |
| 102 | + 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 | + } |
| 106 | + output.attr("names") = out_names; |
| 107 | + return output; |
| 108 | + } |
109 | 109 |
|
110 |
| - const VECTOR& vec; |
111 |
| - const T& other; |
| 110 | + const VECTOR& vec; |
| 111 | + const T& other; |
112 | 112 |
|
113 |
| - // Subsetting for integers -- note that it is 0-based |
114 |
| - // hidden until we decide whether to go with 0 or 1 based indexing |
115 |
| - template <template <class> class OtherStoragePolicy> |
116 |
| - inline Vector<RTYPE, StoragePolicy> |
117 |
| - subset_impl( const VECTOR this_, const Vector<INTSXP, OtherStoragePolicy>& x ) const { |
118 |
| - int n = x.size(); |
119 |
| - if (n == 0) return this_; |
120 |
| - Vector<RTYPE, StoragePolicy> output = no_init(n); |
121 |
| - for (int i=0; i < n; ++i) { |
122 |
| - 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>(); |
125 |
| - else output[i] = (this_)[ x[i] ]; |
126 |
| - } |
| 113 | + // Subsetting for integers -- note that it is 0-based |
| 114 | + // hidden until we decide whether to go with 0 or 1 based indexing |
| 115 | + template <template <class> class OtherStoragePolicy> |
| 116 | + inline Vector<RTYPE, StoragePolicy> |
| 117 | + subset_impl( const VECTOR this_, const Vector<INTSXP, OtherStoragePolicy>& x ) const { |
| 118 | + int n = x.size(); |
| 119 | + if (n == 0) return this_; |
| 120 | + Vector<RTYPE, StoragePolicy> output = no_init(n); |
| 121 | + for (int i=0; i < n; ++i) { |
| 122 | + 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>(); |
| 125 | + else output[i] = (this_)[ x[i] ]; |
| 126 | + } |
127 | 127 |
|
128 |
| - if (!Rf_isNull( Rf_getAttrib( this_, R_NamesSymbol) )) { |
| 128 | + if (!Rf_isNull( Rf_getAttrib( this_, R_NamesSymbol) )) { |
129 | 129 |
|
130 |
| - Vector<STRSXP, StoragePolicy> thisnames = |
131 |
| - as<Vector<STRSXP, StoragePolicy> >(Rf_getAttrib(this_, R_NamesSymbol)); |
| 130 | + Vector<STRSXP, StoragePolicy> thisnames = |
| 131 | + as<Vector<STRSXP, StoragePolicy> >(Rf_getAttrib(this_, R_NamesSymbol)); |
132 | 132 |
|
133 |
| - Vector<STRSXP, StoragePolicy> outnames = no_init(n); |
134 |
| - for (int i=0; i < n; ++i) { |
135 |
| - if (x[i] == NA_INTEGER) outnames[i] = NA_STRING; |
136 |
| - else if (x[i] > this_.size() - 1) outnames[i] = NA_STRING; |
137 |
| - else if (x[i] >= 0) outnames[i] = thisnames[ x[i] ]; |
138 |
| - } |
139 |
| - output.attr("names") = outnames; |
140 |
| - } |
141 |
| - return wrap(output); |
142 |
| - } |
| 133 | + Vector<STRSXP, StoragePolicy> outnames = no_init(n); |
| 134 | + for (int i=0; i < n; ++i) { |
| 135 | + if (x[i] == NA_INTEGER) outnames[i] = NA_STRING; |
| 136 | + else if (x[i] > this_.size() - 1) outnames[i] = NA_STRING; |
| 137 | + else if (x[i] >= 0) outnames[i] = thisnames[ x[i] ]; |
| 138 | + } |
| 139 | + output.attr("names") = outnames; |
| 140 | + } |
| 141 | + return wrap(output); |
| 142 | + } |
143 | 143 |
|
144 |
| -}; |
| 144 | + }; |
145 | 145 |
|
146 | 146 | } // namespace Rcpp
|
147 | 147 |
|
|
0 commit comments