From bates at stat.wisc.edu  Thu Mar 29 01:21:57 2007
From: bates at stat.wisc.edu (Douglas Bates)
Date: Wed, 28 Mar 2007 18:21:57 -0500
Subject: [Rd] [R] Use of 'defineVar' and 'install' in .Call
In-Reply-To: <f13f1c9c0703270156hba5b26fyb541817bed557b0c@mail.gmail.com>
References: <f13f1c9c0703270156hba5b26fyb541817bed557b0c@mail.gmail.com>
Message-ID: <40e66e0b0703281621u58200b39oe3695fc4eaa6d948@mail.gmail.com>

I did read your second message about the problem symptoms disappearing
but I thought that I might make a couple of suggestions about your
code anyway.

There are a number of helper functions declared in Rinternals.h such
as ScalarReal, which is equivalent to your mkans.  (Also
ScalarInteger, ScalarLogical, ...) The functions to convert scalars in
the other direction, i.e. taking an SEXP and returning an int or a
double or a ... , are called asInteger, asReal, ...

If you are writing a package you can define an initialization function
called R_init_<pkgname> to perform initialization for the package.  If
you are going to use a symbol like x many times then you can save the
result of install("x") as a global, say, myPkg_xSymbol during
initialization and use the global variable instead of calling install
many times.  The overhead for calling install is small but if you can
avoid it I don't see a reason not to.

Finally, why do you want to use identifiers like u1, u2, ... when you
could pass a vector named "u" and use that.  In other words, wouldn't
it be easier to do the extraction of the components in the R code for
the function rather than generating a whole bunch of different names?

I suggest that this thread be moved to the r-devel list, which I have cc:d.

On 3/27/07, Daniel Berg <daniel at danielberg.no> wrote:
> Dear all,
>
> [system and version information below]
>
> I am trying to modify a C function for finding the root of an
> expression. The function is to be called from R as .Call with input
> parameters:
>
> f: expression for which we will find the root
> guesses: interval for the solution
> stol: tolerance
> rho: environment
>
> The original functions I use are:
>
> SEXP mkans(double x) {
>   SEXP ans;
>   PROTECT(ans = allocVector(REALSXP, 1));
>   REAL(ans)[0] = x;
>   UNPROTECT(1);
>   return ans;
> }
> double feval(double x, SEXP f, SEXP rho) {
>   defineVar(install("x"), mkans(x), rho);
>   return(REAL(eval(f, rho))[0]);
> }
> SEXP zero(SEXP f, SEXP guesses, SEXP stol, SEXP rho) {
>   double x0 = REAL(guesses)[0], x1 = REAL(guesses)[1], tol = REAL(stol)[0];
>   double f0, f1, fc, xc;
>   if(tol <= 0.0) error("non-positive tol value");
>   f0 = feval(x0, f, rho); f1 = feval(x1, f, rho);
>   if(f0 == 0.0) return mkans(x0);
>   if(f1 == 0.0) return mkans(x1);
>   if(f0*f1 > 0.0) error("x[0] and x[1] have the same sign");
>   for(;;) {
>     xc = 0.5*(x0+x1);
>     if(fabs(x0-x1) < tol) return mkans(xc);
>     fc = feval(xc, f, rho);
>     if(fc == 0) return mkans(xc);
>     if(f0*fc > 0.0) {
>       x0 = xc; f0 = fc;
>     }
>     else {
>       x1 = xc; f1 = fc;
>     }
>   }
> }
>
>
> This works great. However, I wish to make it more general, by
> modifying 'feval'. Given that my problem involves a data set 'u', with
> dimension (i x j), I need to assign values to 'u1', 'u2', ..., 'ui'
> via defineVar(install(...)). I tried the following:
>
> double feval(double x, double *u, int d, double v, SEXP f, SEXP rho) {
>   int i;
>   char *str1="u", str2[1001], *str3;
>   defineVar(install("x"), mkans(x), rho);
>   defineVar(install("y"), mkans(v), rho);
>   for(i=0;i<d;i++) {
>     sprintf(str2,"%d",i+1);
>     str3 = (char *)malloc((strlen(str1)+strlen(str2)+1)*sizeof(char));
>     strcpy(str3,str1);
>     strcat(str3,str2);
>     defineVar(install(str3), mkans(u[i]), rho);
>   }
>   free(str3);
>   return(REAL(eval(f,rho))[0]);
> }
>
> My R-package still compiles without errors but R crashes due to the
> defineVar command.
>
> Any suggestions to how I can do the defineVar bit?
>
> Thanks in advance.
>
> Reagards,
> Daniel Berg
>
> --------------------------------------------
> > R.Version()
> $platform
> [1] "i486-pc-linux-gnu"
> $arch
> [1] "i486"
> $os
> [1] "linux-gnu"
> $system
> [1] "i486, linux-gnu"
> $status
> [1] ""
> $major
> [1] "2"
> $minor
> [1] "3.1"
> $year
> [1] "2006"
> $month
> [1] "06"
> $day
> [1] "01"
> $`svn rev`
> [1] "38247"
> $language
> [1] "R"
> $version.string
> [1] "Version 2.3.1 (2006-06-01)"
>
> ______________________________________________
> R-help at stat.math.ethz.ch mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>



[Rd] [R] Use of 'defineVar' and 'install' in .Call
Douglas Bates