[R] C++: SET_LENGTH() Over Many Iterations?
Jim Java
jjava at priscian.com
Wed Dec 10 03:55:44 CET 2003
In a C++ extension to R (v 1.8.1), I've been experimenting with a
generic "push back" function to tack one value at a time onto the end
of an R vector created within the extension. After calling this
function a certain number of times Rgui.exe (I'm writing in Windows
using Visual Studio .NET 2003) will fail with an Access Violation,
which doesn't happen when I pre-allocate the R-vector memory and write
to the reserved slots; i.e., I'm not trying to create an R object too
big to be handled by R within the context of my OS's available memory.
Here's some simple test code I've been running:
<CPP Code>
#define PUSH_BACK_INTEGER(v, x) \
do {\
UNPROTECT_PTR(v);\
SET_LENGTH(v, GET_LENGTH(v) + 1);\
PROTECT(v);\
INTEGER_POINTER(v)[GET_LENGTH(v) - 1] = x;\
}\
while (false)
SEXP R_SimplePushBackTest(SEXP args)
{
SEXP arg1, arg2, int_vect;
PROTECT(arg1 = AS_INTEGER(CADR(args)));
int n_reps = INTEGER_POINTER(arg1)[0];
PROTECT(arg2 = AS_LOGICAL(CADDR(args)));
bool full_alloc = (LOGICAL_POINTER(arg2)[0] ? true : false);
if (full_alloc)
PROTECT(int_vect = NEW_INTEGER(n_reps));
else
PROTECT(int_vect = NEW_INTEGER(0));
for (int i = 0; i < n_reps; ++i) {
Rprintf(" ** Iteration %d:\n", i + 1);
if (full_alloc)
INTEGER_POINTER(int_vect)[i] = i;
else
PUSH_BACK_INTEGER(int_vect, i);
}
SEXP out, names, cls;
PROTECT(out = NEW_LIST(1));
SET_VECTOR_ELT(out, 0, int_vect);
PROTECT(names = NEW_CHARACTER(1));
SET_STRING_ELT(names, 0, COPY_TO_USER_STRING("integer.vector"));
SET_NAMES(out, names);
PROTECT(cls = NEW_CHARACTER(1));
SET_STRING_ELT(cls, 0, COPY_TO_USER_STRING("pushback"));
classgets(out, cls);
UNPROTECT(6);
return out;
}
</CPP Code>
<R Code>
nreps=50000
allocate=FALSE
sink("pushback_test.txt")
test.pushback=.External("R_SimplePushBackTest", as.integer(nreps), as.logical(allocate))
print(test.pushback)
sink()
</R Code>
If allocate=TRUE (vector memory is pre-allocated in the extension),
the code proceeds normally on my system; if allocate=FALSE, Rgui.exe
eventually crashes from an Access Violation. I've gathered only enough
information from the R source code so far to think that R is
ultimately calling realloc() through the SET_LENGTH macro; that would
make my code rather inefficient, but I'm trying for genericness here.
In C++, is there a better way than what I'm doing to concatenate
values onto the end of an R vector of arbitrary length, especially
over many iterations?
Thanks for taking the time to read this.
System specs: Pentium 4 2.5 GHz, 512 MB RAM, 40 GB hard drive, Win XP
Yrs etc.,
Jim Java
More information about the R-help
mailing list