@@ -66,31 +66,42 @@ static R_INLINE SEXP VECTOR_ELT_FIX_NAMED(SEXP y, R_xlen_t i) {
66
66
currently the subscript code forces allocation.
67
67
*/
68
68
69
- #define EXTRACT_SUBSET_LOOP (STDCODE , NACODE ) do { \
70
- if (TYPEOF(indx) == INTSXP) { \
71
- const int *pindx = INTEGER_RO(indx); \
72
- for (i = 0; i < n; i++) { \
73
- ii = pindx[i]; \
74
- if (0 < ii && ii <= nx) { \
75
- ii--; \
76
- STDCODE; \
77
- } \
78
- else /* out of bounds or NA */ \
79
- NACODE ; \
80
- } \
81
- } \
82
- else { \
83
- const double * pindx = REAL_RO (indx ); \
84
- for (i = 0 ; i < n ; i ++ ) { \
85
- double di = pindx [i ]; \
86
- ii = (R_xlen_t ) (di - 1 ); \
87
- if (R_FINITE (di ) && \
88
- 0 <= ii && ii < nx ) \
89
- STDCODE ; \
90
- else \
91
- NACODE ; \
92
- } \
93
- } \
69
+ #define EXTRACT_SUBSET_LOOP_ (STDCODE , NACODE ) do { \
70
+ if (TYPEOF(indx) == INTSXP) { \
71
+ const int *pindx = INTEGER_RO(indx); \
72
+ for (i = 0; i < n; i++) { \
73
+ ii = pindx[i]; \
74
+ if (0 < ii && ii <= nx) { \
75
+ ii--; \
76
+ STDCODE; \
77
+ } \
78
+ else /* out of bounds or NA */ \
79
+ NACODE ; \
80
+ } \
81
+ } \
82
+ else { \
83
+ const double * pindx = REAL_RO (indx ); \
84
+ for (i = 0 ; i < n ; i ++ ) { \
85
+ double di = pindx [i ]; \
86
+ ii = (R_xlen_t ) (di - 1 ); \
87
+ if (R_FINITE (di ) && \
88
+ 0 <= ii && ii < nx ) \
89
+ STDCODE ; \
90
+ else \
91
+ NACODE ; \
92
+ } \
93
+ } \
94
+ } while (0 )
95
+
96
+ #define EXTRACT_SUBSET_LOOP (PTR , STDCODEPTR , STDCODENOPTR , NACODE ) do { \
97
+ PTR; \
98
+ if (px != NULL) { \
99
+ EXTRACT_SUBSET_LOOP_(STDCODEPTR, NACODE); \
100
+ } else { \
101
+ /* Fallback `ELT()` based path used for ALTREP classes */ \
102
+ /* that return `NULL` from `DATAPTR_OR_NULL()`. */ \
103
+ EXTRACT_SUBSET_LOOP_ (STDCODENOPTR , NACODE ); \
104
+ } \
94
105
} while (0 )
95
106
96
107
NORET static void errorcallNotSubsettable (SEXP x , SEXP call )
@@ -134,36 +145,52 @@ attribute_hidden SEXP ExtractSubset(SEXP x, SEXP indx, SEXP call)
134
145
PROTECT (result = allocVector (mode , n ));
135
146
switch (mode ) {
136
147
case LGLSXP :
137
- EXTRACT_SUBSET_LOOP (LOGICAL0 (result )[i ] = LOGICAL_ELT (x , ii ),
138
- LOGICAL0 (result )[i ] = NA_INTEGER );
148
+ EXTRACT_SUBSET_LOOP (const int * px = (const int * ) DATAPTR_OR_NULL (x ),
149
+ LOGICAL0 (result )[i ] = px [ii ],
150
+ LOGICAL0 (result )[i ] = LOGICAL_ELT (x , ii ),
151
+ LOGICAL0 (result )[i ] = NA_LOGICAL );
139
152
break ;
140
153
case INTSXP :
141
- EXTRACT_SUBSET_LOOP (INTEGER0 (result )[i ] = INTEGER_ELT (x , ii ),
154
+ EXTRACT_SUBSET_LOOP (const int * px = (const int * ) DATAPTR_OR_NULL (x ),
155
+ INTEGER0 (result )[i ] = px [ii ],
156
+ INTEGER0 (result )[i ] = INTEGER_ELT (x , ii ),
142
157
INTEGER0 (result )[i ] = NA_INTEGER );
143
158
break ;
144
159
case REALSXP :
145
- EXTRACT_SUBSET_LOOP (REAL0 (result )[i ] = REAL_ELT (x , ii ),
160
+ EXTRACT_SUBSET_LOOP (const double * px = (const double * ) DATAPTR_OR_NULL (x ),
161
+ REAL0 (result )[i ] = px [ii ],
162
+ REAL0 (result )[i ] = REAL_ELT (x , ii ),
146
163
REAL0 (result )[i ] = NA_REAL );
147
164
break ;
148
165
case CPLXSXP :
149
166
{
150
167
Rcomplex NA_CPLX = { .r = NA_REAL , .i = NA_REAL };
151
- EXTRACT_SUBSET_LOOP (COMPLEX0 (result )[i ] = COMPLEX_ELT (x , ii ),
152
- COMPLEX0 (result )[i ] = NA_CPLX );
168
+ EXTRACT_SUBSET_LOOP (const Rcomplex * px = (const Rcomplex * ) DATAPTR_OR_NULL (x ),
169
+ COMPLEX0 (result )[i ] = px [ii ],
170
+ COMPLEX0 (result )[i ] = COMPLEX_ELT (x , ii ),
171
+ COMPLEX0 (result )[i ] = NA_CPLX );
153
172
}
154
173
break ;
155
174
case STRSXP :
156
- EXTRACT_SUBSET_LOOP (SET_STRING_ELT (result , i , STRING_ELT (x , ii )),
175
+ EXTRACT_SUBSET_LOOP (const SEXP * px = (const SEXP * ) DATAPTR_OR_NULL (x ),
176
+ SET_STRING_ELT (result , i , px [ii ]),
177
+ SET_STRING_ELT (result , i , STRING_ELT (x , ii )),
157
178
SET_STRING_ELT (result , i , NA_STRING ));
158
179
break ;
159
180
case VECSXP :
160
181
case EXPRSXP :
161
- EXTRACT_SUBSET_LOOP (SET_VECTOR_ELT (result , i ,
162
- VECTOR_ELT_FIX_NAMED (x , ii )),
163
- SET_VECTOR_ELT (result , i , R_NilValue ));
164
- break ;
182
+ /* Is `VECTOR_ELT_FIX_NAMED()` still needed? If not, split out VECSXP */
183
+ /* case and use `DATAPTR_OR_NULL()` there too. Currently it never */
184
+ /* takes the `px[ii]` path - DV. */
185
+ EXTRACT_SUBSET_LOOP (const SEXP * px = NULL ,
186
+ SET_VECTOR_ELT (result , i , px [ii ]),
187
+ SET_VECTOR_ELT (result , i , VECTOR_ELT_FIX_NAMED (x , ii )),
188
+ SET_VECTOR_ELT (result , i , R_NilValue ));
189
+ break ;
165
190
case RAWSXP :
166
- EXTRACT_SUBSET_LOOP (RAW0 (result )[i ] = RAW_ELT (x , ii ),
191
+ EXTRACT_SUBSET_LOOP (const Rbyte * px = (const Rbyte * ) DATAPTR_OR_NULL (x ),
192
+ RAW0 (result )[i ] = px [ii ],
193
+ RAW0 (result )[i ] = RAW_ELT (x , ii ),
167
194
RAW0 (result )[i ] = (Rbyte ) 0 );
168
195
break ;
169
196
case LISTSXP :
0 commit comments