Skip to content

Commit e05504b

Browse files
author
luke
committed
ALTREP now supports \code{VECSXP} vectors.
Contributed by Gabor Csardi in PR17620. git-svn-id: https://svn.r-project.org/R/trunk@83914 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent d30f8bc commit e05504b

File tree

7 files changed

+186
-30
lines changed

7 files changed

+186
-30
lines changed

Diff for: doc/NEWS.Rd

+3
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,9 @@
424424

425425
\item New macro \code{CAD5R()} is provided in \file{Rinternals.h}
426426
and used in a few places in the \R sources.
427+
428+
\item ALTREP now supports \code{VECSXP} vectors. Contributed by
429+
Gabor Csardi in \PR{17620}.
427430
}
428431
}
429432

Diff for: src/include/Defn.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,6 @@ typedef union { VECTOR_SEXPREC s; double align; } SEXPREC_ALIGN;
404404
#define RAW(x) ((Rbyte *) DATAPTR(x))
405405
#define COMPLEX(x) ((Rcomplex *) DATAPTR(x))
406406
#define REAL(x) ((double *) DATAPTR(x))
407-
#define VECTOR_ELT(x,i) ((SEXP *) DATAPTR(x))[i]
408407
#define STRING_PTR(x) ((SEXP *) DATAPTR(x))
409408
#define VECTOR_PTR(x) ((SEXP *) DATAPTR(x))
410409
#define LOGICAL_RO(x) ((const int *) DATAPTR_RO(x))
@@ -678,6 +677,8 @@ Rcomplex ALTCOMPLEX_ELT(SEXP x, R_xlen_t i);
678677
void ALTCOMPLEX_SET_ELT(SEXP x, R_xlen_t i, Rcomplex v);
679678
Rbyte ALTRAW_ELT(SEXP x, R_xlen_t i);
680679
void ALTRAW_SET_ELT(SEXP x, R_xlen_t i, Rbyte v);
680+
SEXP ALTLIST_ELT(SEXP, R_xlen_t);
681+
void ALTLIST_SET_ELT(SEXP, R_xlen_t, SEXP);
681682

682683
/* invoking ALTREP class methods */
683684
SEXP ALTINTEGER_SUM(SEXP x, Rboolean narm);

Diff for: src/include/R_ext/Altrep.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* R : A Computer Language for Statistical Data Analysis
3-
* Copyright (C) 2016 The R Core Team.
3+
* Copyright (C) 2016-2023 The R Core Team.
44
*
55
* This program is free software; you can redistribute it and/or modify
66
* it under the terms of the GNU Lesser General Public License as published by
@@ -50,6 +50,8 @@ R_altrep_class_t
5050
R_make_altraw_class(const char *cname, const char *pname, DllInfo *info);
5151
R_altrep_class_t
5252
R_make_altcomplex_class(const char *cname, const char *pname, DllInfo *info);
53+
R_altrep_class_t
54+
R_make_altlist_class(const char *cname, const char *pname, DllInfo *info);
5355

5456
Rboolean R_altrep_inherits(SEXP x, R_altrep_class_t);
5557

@@ -105,6 +107,9 @@ typedef void (*R_altstring_Set_elt_method_t)(SEXP, R_xlen_t, SEXP);
105107
typedef int (*R_altstring_Is_sorted_method_t)(SEXP);
106108
typedef int (*R_altstring_No_NA_method_t)(SEXP);
107109

110+
typedef SEXP (*R_altlist_Elt_method_t)(SEXP, R_xlen_t);
111+
typedef void (*R_altlist_Set_elt_method_t)(SEXP, R_xlen_t, SEXP);
112+
108113
#define DECLARE_METHOD_SETTER(CNAME, MNAME) \
109114
void \
110115
R_set_##CNAME##_##MNAME##_method(R_altrep_class_t cls, \
@@ -156,6 +161,9 @@ DECLARE_METHOD_SETTER(altstring, Set_elt)
156161
DECLARE_METHOD_SETTER(altstring, Is_sorted)
157162
DECLARE_METHOD_SETTER(altstring, No_NA)
158163

164+
DECLARE_METHOD_SETTER(altlist, Elt)
165+
DECLARE_METHOD_SETTER(altlist, Set_elt)
166+
159167
#ifdef __cplusplus
160168
}
161169
#endif

Diff for: src/main/altclasses.c

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* R : A Computer Language for Statistical Data Analysis
3-
* Copyright (C) 2016--2021 The R Core Team
3+
* Copyright (C) 2016--2023 The R Core Team
44
*
55
* This program is free software; you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -1418,6 +1418,7 @@ static R_altrep_class_t wrap_real_class;
14181418
static R_altrep_class_t wrap_complex_class;
14191419
static R_altrep_class_t wrap_raw_class;
14201420
static R_altrep_class_t wrap_string_class;
1421+
static R_altrep_class_t wrap_list_class;
14211422

14221423
/* Wrapper objects are ALTREP objects designed to hold the attributes
14231424
of a potentially large object and/or meta data for the object. */
@@ -1711,6 +1712,20 @@ static int wrapper_string_no_NA(SEXP x)
17111712
}
17121713

17131714

1715+
/*
1716+
* ALTLIST Methods
1717+
*/
1718+
1719+
static SEXP wrapper_list_Elt(SEXP x, R_xlen_t i)
1720+
{
1721+
return VECTOR_ELT(WRAPPER_WRAPPED(x), i);
1722+
}
1723+
1724+
static void wrapper_list_Set_elt(SEXP x, R_xlen_t i, SEXP v)
1725+
{
1726+
SET_VECTOR_ELT(WRAPPER_WRAPPED_RW(x), i, v);
1727+
}
1728+
17141729
/*
17151730
* Class Objects and Method Tables
17161731
*/
@@ -1863,6 +1878,24 @@ static void InitWrapStringClass(DllInfo *dll)
18631878
R_set_altstring_No_NA_method(cls, wrapper_string_no_NA);
18641879
}
18651880

1881+
static void InitWrapListClass(DllInfo *dll)
1882+
{
1883+
R_altrep_class_t cls =
1884+
R_make_altlist_class("wrap_list", WRAPPKG, dll);
1885+
wrap_list_class = cls;
1886+
1887+
/* override ALTREP methods */
1888+
R_set_altrep_Unserialize_method(cls, wrapper_Unserialize);
1889+
R_set_altrep_Serialized_state_method(cls, wrapper_Serialized_state);
1890+
R_set_altrep_Duplicate_method(cls, wrapper_Duplicate);
1891+
R_set_altrep_Inspect_method(cls, wrapper_Inspect);
1892+
R_set_altrep_Length_method(cls, wrapper_Length);
1893+
1894+
/* override ALTLIST methods */
1895+
R_set_altlist_Elt_method(cls, wrapper_list_Elt);
1896+
R_set_altlist_Set_elt_method(cls, wrapper_list_Set_elt);
1897+
}
1898+
18661899

18671900
/*
18681901
* Constructor
@@ -1879,6 +1912,7 @@ static SEXP make_wrapper(SEXP x, SEXP meta)
18791912
case CPLXSXP: cls = wrap_complex_class; break;
18801913
case RAWSXP: cls = wrap_raw_class; break;
18811914
case STRSXP: cls = wrap_string_class; break;
1915+
case VECSXP: cls = wrap_list_class; break;
18821916
default: error("unsupported type");
18831917
}
18841918

@@ -1915,6 +1949,7 @@ static R_INLINE int is_wrapper(SEXP x)
19151949
case CPLXSXP: return R_altrep_inherits(x, wrap_complex_class);
19161950
case RAWSXP: return R_altrep_inherits(x, wrap_raw_class);
19171951
case STRSXP: return R_altrep_inherits(x, wrap_string_class);
1952+
case VECSXP: return R_altrep_inherits(x, wrap_list_class);
19181953
default: return FALSE;
19191954
}
19201955
else return FALSE;
@@ -2039,4 +2074,5 @@ attribute_hidden void R_init_altrep(void)
20392074
InitWrapComplexClass(NULL);
20402075
InitWrapRawClass(NULL);
20412076
InitWrapStringClass(NULL);
2077+
InitWrapListClass(NULL);
20422078
}

Diff for: src/main/altrep.c

+96-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* R : A Computer Language for Statistical Data Analysis
3-
* Copyright (C) 2016--2017 The R Core Team
3+
* Copyright (C) 2016--2023 The R Core Team
44
*
55
* This program is free software; you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -134,6 +134,7 @@ static void SET_ALTREP_CLASS(SEXP x, SEXP class)
134134
#define ALTRAW_METHODS_TABLE(x) GENERIC_METHODS_TABLE(x, altraw)
135135
#define ALTCOMPLEX_METHODS_TABLE(x) GENERIC_METHODS_TABLE(x, altcomplex)
136136
#define ALTSTRING_METHODS_TABLE(x) GENERIC_METHODS_TABLE(x, altstring)
137+
#define ALTLIST_METHODS_TABLE(x) GENERIC_METHODS_TABLE(x, altlist)
137138

138139
#define ALTREP_METHODS \
139140
R_altrep_UnserializeEX_method_t UnserializeEX; \
@@ -196,6 +197,11 @@ static void SET_ALTREP_CLASS(SEXP x, SEXP class)
196197
R_altstring_Is_sorted_method_t Is_sorted; \
197198
R_altstring_No_NA_method_t No_NA
198199

200+
#define ALTLIST_METHODS \
201+
ALTVEC_METHODS; \
202+
R_altlist_Elt_method_t Elt; \
203+
R_altlist_Set_elt_method_t Set_elt
204+
199205
typedef struct { ALTREP_METHODS; } altrep_methods_t;
200206
typedef struct { ALTVEC_METHODS; } altvec_methods_t;
201207
typedef struct { ALTINTEGER_METHODS; } altinteger_methods_t;
@@ -204,6 +210,7 @@ typedef struct { ALTLOGICAL_METHODS; } altlogical_methods_t;
204210
typedef struct { ALTRAW_METHODS; } altraw_methods_t;
205211
typedef struct { ALTCOMPLEX_METHODS; } altcomplex_methods_t;
206212
typedef struct { ALTSTRING_METHODS; } altstring_methods_t;
213+
typedef struct { ALTLIST_METHODS; } altlist_methods_t;
207214

208215
/* Macro to extract first element from ... macro argument.
209216
From Richard Hansen's answer in
@@ -223,6 +230,7 @@ typedef struct { ALTSTRING_METHODS; } altstring_methods_t;
223230
#define ALTRAW_DISPATCH(fun, ...) DO_DISPATCH(ALTRAW, fun, __VA_ARGS__)
224231
#define ALTCOMPLEX_DISPATCH(fun, ...) DO_DISPATCH(ALTCOMPLEX, fun, __VA_ARGS__)
225232
#define ALTSTRING_DISPATCH(fun, ...) DO_DISPATCH(ALTSTRING, fun, __VA_ARGS__)
233+
#define ALTLIST_DISPATCH(fun, ...) DO_DISPATCH(ALTLIST, fun, __VA_ARGS__)
226234

227235

228236
/*
@@ -541,6 +549,37 @@ int STRING_NO_NA(SEXP x)
541549
return ALTREP(x) ? ALTSTRING_DISPATCH(No_NA, x) : 0;
542550
}
543551

552+
SEXP /*attribute_hidden*/ ALTLIST_ELT(SEXP x, R_xlen_t i)
553+
{
554+
SEXP val = NULL;
555+
556+
/**** move GC disabling into method? */
557+
if (R_in_gc)
558+
error("cannot get ALTLIST_ELT during GC");
559+
R_CHECK_THREAD;
560+
int enabled = R_GCEnabled;
561+
R_GCEnabled = FALSE;
562+
563+
val = ALTLIST_DISPATCH(Elt, x, i);
564+
565+
R_GCEnabled = enabled;
566+
return val;
567+
}
568+
569+
void attribute_hidden ALTLIST_SET_ELT(SEXP x, R_xlen_t i, SEXP v)
570+
{
571+
/**** move GC disabling into method? */
572+
if (R_in_gc)
573+
error("cannot set ALTLIST_ELT during GC");
574+
R_CHECK_THREAD;
575+
int enabled = R_GCEnabled;
576+
R_GCEnabled = FALSE;
577+
578+
ALTLIST_DISPATCH(Set_elt, x, i, v);
579+
580+
R_GCEnabled = enabled;
581+
}
582+
544583
SEXP ALTINTEGER_SUM(SEXP x, Rboolean narm)
545584
{
546585
return ALTINTEGER_DISPATCH(Sum, x, narm);
@@ -801,6 +840,25 @@ static void altstring_Set_elt_default(SEXP x, R_xlen_t i, SEXP v)
801840
static int altstring_Is_sorted_default(SEXP x) { return UNKNOWN_SORTEDNESS; }
802841
static int altstring_No_NA_default(SEXP x) { return 0; }
803842

843+
static SEXP altlist_Elt_default(SEXP x, R_xlen_t i)
844+
{
845+
error("ALTLIST classes must provide an Elt method");
846+
}
847+
848+
static void altlist_Set_elt_default(SEXP x, R_xlen_t i, SEXP v)
849+
{
850+
error("ALTLIST classes must provide a Set_elt method");
851+
}
852+
853+
static void *altlist_Dataptr_default(SEXP x, Rboolean writeable)
854+
{
855+
error("ALTLIST classes do not have a Dataptr method");
856+
}
857+
858+
static const void *altlist_Dataptr_or_null_default(SEXP x)
859+
{
860+
error("ALTLIST classes do not have a Dataptr_or_null method");
861+
}
804862

805863
/**
806864
** ALTREP Initial Method Tables
@@ -925,6 +983,24 @@ static altstring_methods_t altstring_default_methods = {
925983
};
926984

927985

986+
987+
static altlist_methods_t altlist_default_methods = {
988+
.UnserializeEX = altrep_UnserializeEX_default,
989+
.Unserialize = altrep_Unserialize_default,
990+
.Serialized_state = altrep_Serialized_state_default,
991+
.DuplicateEX = altrep_DuplicateEX_default,
992+
.Duplicate = altrep_Duplicate_default,
993+
.Coerce = altrep_Coerce_default,
994+
.Inspect = altrep_Inspect_default,
995+
.Length = altrep_Length_default,
996+
.Dataptr = altlist_Dataptr_default,
997+
.Dataptr_or_null = altlist_Dataptr_or_null_default,
998+
.Extract_subset = altvec_Extract_subset_default,
999+
.Elt = altlist_Elt_default,
1000+
.Set_elt = altlist_Set_elt_default
1001+
};
1002+
1003+
9281004
/**
9291005
** Class Constructors
9301006
**/
@@ -958,6 +1034,7 @@ make_altrep_class(int type, const char *cname, const char *pname, DllInfo *dll)
9581034
case RAWSXP: MAKE_CLASS(class, altraw); break;
9591035
case CPLXSXP: MAKE_CLASS(class, altcomplex); break;
9601036
case STRSXP: MAKE_CLASS(class, altstring); break;
1037+
case VECSXP: MAKE_CLASS(class, altlist); break;
9611038
default: error("unsupported ALTREP class");
9621039
}
9631040
RegisterClass(class, type, cname, pname, dll);
@@ -976,6 +1053,7 @@ make_altrep_class(int type, const char *cname, const char *pname, DllInfo *dll)
9761053
}
9771054

9781055
DEFINE_CLASS_CONSTRUCTOR(altstring, STRSXP)
1056+
DEFINE_CLASS_CONSTRUCTOR(altlist, VECSXP)
9791057
DEFINE_CLASS_CONSTRUCTOR(altinteger, INTSXP)
9801058
DEFINE_CLASS_CONSTRUCTOR(altreal, REALSXP)
9811059
DEFINE_CLASS_CONSTRUCTOR(altlogical, LGLSXP)
@@ -991,6 +1069,7 @@ static void reinit_altrep_class(SEXP class)
9911069
case LGLSXP: INIT_CLASS(class, altlogical); break;
9921070
case RAWSXP: INIT_CLASS(class, altraw); break;
9931071
case CPLXSXP: INIT_CLASS(class, altcomplex); break;
1072+
case VECSXP: INIT_CLASS(class, altlist); break;
9941073
default: error("unsupported ALTREP class");
9951074
}
9961075
}
@@ -1008,6 +1087,18 @@ static void reinit_altrep_class(SEXP class)
10081087
m->MNAME = fun; \
10091088
}
10101089

1090+
#define DEFINE_METHOD_SETTER_NOLIST(CNAME, MNAME) \
1091+
void R_set_##CNAME##_##MNAME##_method(R_altrep_class_t cls, \
1092+
R_##CNAME##_##MNAME##_method_t fun) \
1093+
{ \
1094+
CNAME##_methods_t *m = CLASS_METHODS_TABLE(R_SEXP(cls)); \
1095+
if (m->MNAME == altlist_##MNAME##_default) { \
1096+
error("ALTLIST classes do not have a ##MNAME## method"); \
1097+
} else { \
1098+
m->MNAME = fun; \
1099+
} \
1100+
}
1101+
10111102
DEFINE_METHOD_SETTER(altrep, UnserializeEX)
10121103
DEFINE_METHOD_SETTER(altrep, Unserialize)
10131104
DEFINE_METHOD_SETTER(altrep, Serialized_state)
@@ -1017,8 +1108,8 @@ DEFINE_METHOD_SETTER(altrep, Coerce)
10171108
DEFINE_METHOD_SETTER(altrep, Inspect)
10181109
DEFINE_METHOD_SETTER(altrep, Length)
10191110

1020-
DEFINE_METHOD_SETTER(altvec, Dataptr)
1021-
DEFINE_METHOD_SETTER(altvec, Dataptr_or_null)
1111+
DEFINE_METHOD_SETTER_NOLIST(altvec, Dataptr)
1112+
DEFINE_METHOD_SETTER_NOLIST(altvec, Dataptr_or_null)
10221113
DEFINE_METHOD_SETTER(altvec, Extract_subset)
10231114

10241115
DEFINE_METHOD_SETTER(altinteger, Elt)
@@ -1054,6 +1145,8 @@ DEFINE_METHOD_SETTER(altstring, Set_elt)
10541145
DEFINE_METHOD_SETTER(altstring, Is_sorted)
10551146
DEFINE_METHOD_SETTER(altstring, No_NA)
10561147

1148+
DEFINE_METHOD_SETTER(altlist, Elt)
1149+
DEFINE_METHOD_SETTER(altlist, Set_elt)
10571150

10581151
/**
10591152
** ALTREP Object Constructor and Utility Functions

Diff for: src/main/dotcode.c

+11-6
Original file line numberDiff line numberDiff line change
@@ -2025,14 +2025,19 @@ attribute_hidden SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env)
20252025
type2char(t), na + 1);
20262026
/* Used read-only, so this is safe */
20272027
#ifdef USE_RINTERNALS
2028-
cargs[na] = (void*) DATAPTR(s);
2028+
if (!ALTREP(s))
2029+
cargs[na] = (void*) DATAPTR(s);
2030+
else {
20292031
#else
2030-
n = XLENGTH(s);
2031-
SEXP *lptr = (SEXP *) R_alloc(n, sizeof(SEXP));
2032-
for (R_xlen_t i = 0 ; i < n ; i++) lptr[i] = VECTOR_ELT(s, i);
2033-
cargs[na] = (void*) lptr;
2032+
n = XLENGTH(s);
2033+
SEXP *lptr = (SEXP *) R_alloc(n, sizeof(SEXP));
2034+
for (R_xlen_t i = 0 ; i < n ; i++) lptr[i] = VECTOR_ELT(s, i);
2035+
cargs[na] = (void*) lptr;
20342036
#endif
2035-
break;
2037+
#ifdef USE_RINTERNALS
2038+
}
2039+
#endif
2040+
break;
20362041
case CLOSXP:
20372042
case BUILTINSXP:
20382043
case SPECIALSXP:

0 commit comments

Comments
 (0)