|
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