Skip to content

Commit f902f6a

Browse files
committed
Use DATAPTR_OR_NULL() in ExtractSubset() when possible
1 parent e0f5c5e commit f902f6a

File tree

1 file changed

+64
-37
lines changed

1 file changed

+64
-37
lines changed

src/main/subset.c

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -66,31 +66,42 @@ static R_INLINE SEXP VECTOR_ELT_FIX_NAMED(SEXP y, R_xlen_t i) {
6666
currently the subscript code forces allocation.
6767
*/
6868

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+
} \
94105
} while (0)
95106

96107
NORET static void errorcallNotSubsettable(SEXP x, SEXP call)
@@ -134,36 +145,52 @@ attribute_hidden SEXP ExtractSubset(SEXP x, SEXP indx, SEXP call)
134145
PROTECT(result = allocVector(mode, n));
135146
switch(mode) {
136147
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);
139152
break;
140153
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),
142157
INTEGER0(result)[i] = NA_INTEGER);
143158
break;
144159
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),
146163
REAL0(result)[i] = NA_REAL);
147164
break;
148165
case CPLXSXP:
149166
{
150167
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);
153172
}
154173
break;
155174
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)),
157178
SET_STRING_ELT(result, i, NA_STRING));
158179
break;
159180
case VECSXP:
160181
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;
165190
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),
167194
RAW0(result)[i] = (Rbyte) 0);
168195
break;
169196
case LISTSXP:

0 commit comments

Comments
 (0)