[Rd] C function with unknown output length

Dirk Eddelbuettel edd at debian.org
Wed Jun 6 20:19:58 CEST 2007


Salut Vincent,

On 6 June 2007 at 13:17, Vincent Goulet wrote:
| Could anyone point me to one or more examples in the R sources of a C  
| function that is called without knowing in advance what will be the  
| length (say) of the output vector?
| 
| To make myself clearer, we have a C function that computes  
| probabilities until their sum gets "close enough" to 1. Hence, the  
| number of probabilities is not known in advance.
| 
| I would like to have an idea what is the best way to handle this  
| situation in R.

I haven't been on the 'Dirk tells everybody to use RcppTemplate' soapbox
lately, so let me (drumroll) suggest to use RcppTemplate.  

So if you were to consider C++, which can be done incrementally relative to
C, then you could collect your data in a self-growing, autonagically
managemed STL Vector, pass it to RcppTemplate, and you're done.  I have a
local .deb package for r-cran-rcpptemplate I can send you (and which I should
upload to Debian), or you can just use it from source on CRAN.  You want the
source for the examples anyway.

If C++ is not an option, then I typically just hunt for decent examples that
do similar stuff.  BDR's RODBC is usually a good source -- he also does not
know ex ante how long the return sets are.  It's not _that_ hard, just
tedious.  You examine the length of your vector, assign a new one for results
of that length, and copy elements.  

As an example, see the following from my rdieharder package (that is pending
an upload to CRAN) where C as opposed to C++ was a given constraint. I wrote
this in a hurry and I may well have missed something to make it a tad better
-- but as indicated above, I'd rather be doing it in C++ anyway.  

In the code, element [1] is a vector of possibly varying size:

  /* vector of size three: [0] is scalar ks_pv, [1] is pvalues vec, [2] name */
  PROTECT(result = allocVector(VECSXP, 3)); 
  /* alloc scalar, and set it */
  PROTECT(pv = allocVector(REALSXP, 1));
  REAL(pv)[0] = testptr->ks_pvalue;
  /* vector and set it */
  PROTECT(vec = allocVector(REALSXP, testptr->psamples)); 
  for (i = 0; i < testptr->psamples; i++) {
    REAL(vec)[i] = testptr->pvalues[i];
  }
  PROTECT(name = allocVector(STRSXP, 1));
  SET_STRING_ELT(name, 0, mkChar(dtestptr->name));

  /* insert scalar and vector */
  SET_VECTOR_ELT(result, 0, pv);
  SET_VECTOR_ELT(result, 1, vec);
  SET_VECTOR_ELT(result, 2, name);
  
  UNPROTECT(4);
  return result;

and testptr->psamples has the unknonw 'N' of vector length.

And yes, we need better cookbook examples for all this.

Hth, Dirk

-- 
Hell, there are no rules here - we're trying to accomplish something. 
                                                  -- Thomas A. Edison



More information about the R-devel mailing list