vectores recorrer programacion matrices llenar funciones ejemplos dinamico con como c r data-structures random poisson

recorrer - Devuelve un vector dinámico de C a R



vector dinamico c++ (2)

Estoy escribiendo un código en C para ser llamado dinámicamente desde R.

Este código genera una ruta de un proceso de Poisson aleatorio hasta un tiempo deseado T. Por lo tanto, en cada llamada a mi función C, la longitud del vector devuelto será diferente dependiendo de los números aleatorios generados.

¿Qué estructura de datos de R tendré que crear? un LISTSXP ? ¿otro?

¿Cómo puedo crearlo y cómo puedo agregarlo? Y especialmente ¿cómo puedo devolverlo a R?

Gracias por la ayuda.


Depende de ti lo que quieras usar como estructura temporal, porque al final tendrás que asignar un vector para el resultado de todos modos. Entonces, lo que sea que vayas a usar no es lo que devolverás. Hay varias posibilidades:

  1. use Calloc + Realloc + Free que le permite expandir la memoria temporal según sea necesario. Una vez que tiene el conjunto completo, asigna el vector de resultado y lo devuelve.
  2. Si puede sobreestimar el tamaño fácilmente, puede SETLENGTH vector de resultado y usar SETLENGTH antes de devolverlo. Sin embargo, hay problemas con esto, porque el resultado seguirá estando sobreasignado hasta que se duplique más adelante.
  3. Puede usar lo que insinuó que es una lista encadenada de bloques vectoriales, es decir, asignar y proteger una paleta de la que añada vectores a la cola cuando los necesite. Al final, asigna el vector de retorno y copia el contenido de los bloques que asignó. Esto es más intrincado que los dos anteriores.

Cada uno de ellos tiene inconvenientes y beneficios, por lo que realmente depende de su aplicación elegir el que mejor se adapte a usted.

Editar: agregó un ejemplo del uso del enfoque de emparejamiento. Todavía recomendaría el enfoque de Realloc , ya que es mucho más fácil, pero no obstante:

#define BLOCK_SIZE xxx /* some reasonable size for increments - could be adaptive, too */ SEXP block; /* last vector block */ SEXP root = PROTECT(list1(block = allocVector(REALSXP, BLOCK_SIZE))); SEXP tail = root; double *values = REAL(block); int count = 0, total = 0; do { /* your code to generate values - if you want to add one first try to add it to the existing block, otherwise allocate new one */ if (count == BLOCK_SIZE) { /* add a new block when needed */ tail = SETCDR(tail, list1(block = allocVector(REALSXP, BLOCK_SIZE))); values = REAL(block); total += count; count = 0; } values[count++] = next_value; } while (...); total += count; /* when done, we need to create the result vector */ { SEXP res = allocVector(REALSXP, total); double *res_values = REAL(res); while (root != R_NilValue) { int size = (CDR(root) == R_NilValue) ? count : BLOCK_SIZE; memcpy(res_values, REAL(CAR(root)), sizeof(double) * size); res_values += size; root = CDR(root); } UNPROTECT(1); return res; }


Si estás abierto a cambiar de C a C ++, obtienes capa adicional de Rcpp gratis. Aquí hay un ejemplo de la página del paquete RcppExample (aún bastante incompleto):

#include <RcppClassic.h> #include <cmath> RcppExport SEXP newRcppVectorExample(SEXP vector) { BEGIN_RCPP Rcpp::NumericVector orig(vector); // keep a copy Rcpp::NumericVector vec(orig.size()); // create vector same size // we could query size via // int n = vec.size(); // and loop over the vector, but using the STL is so much nicer // so we use a STL transform() algorithm on each element std::transform(orig.begin(), orig.end(), vec.begin(), ::sqrt); return Rcpp::List::create(Rcpp::Named( "result" ) = vec, Rcpp::Named( "original" ) = orig) ; END_RCPP }

Como puede ver, no se asignan, liberan, PROTECT/UNPROTECT explícitamente la memoria, etc., y se obtiene un objeto de la lista R de primera clase.

Hay muchos más ejemplos, incluidos en otras preguntas de SO como esta .

Editar: Y realmente no dijiste lo que harían tus rutas, pero como una simple ilustración, aquí está el código C ++ usando las adiciones de cumsum() y rpois() que se comportan exactamente como lo hacen en R:

R> library(inline) R> R> fun <- cxxfunction(signature(ns="integer", lambdas="numeric"), + plugin="Rcpp", + body='' + int n = Rcpp::as<int>(ns); + double lambda = Rcpp::as<double>(lambdas); + + Rcpp::RNGScope tmp; // make sure RNG behaves + + Rcpp::NumericVector vec = cumsum( rpois( n, lambda ) ); + + return vec; + '') R> set.seed(42) R> fun(3, 0.3) [1] 1 2 2 R> fun(4, 0.4) [1] 1 1 1 2

Y como prueba, de vuelta en R, si establecemos la semilla, podemos generar exactamente los mismos números:

R> set.seed(42) R> cumsum(rpois(3, 0.3)) [1] 1 2 2 R> cumsum(rpois(4, 0.4)) [1] 1 1 1 2 R>