Faheem Mitha
2003-Dec-14 00:44 UTC
[R] compile error with C code and standalone R math C library
Dear People, I just went back to an old piece of C code. On trying to compile it with the R math standalone C library I got the following error. Can anyone enlighten me what I am doing wrong, if anything? C file (rr-sa.c) follows. I'm on Debian sarge. I'm running R version 1.8.1. Gcc is version 3.3.1. Thanks in advance. Faheem. ********************************************************************** faheem ~/co/rr/trunk>gcc -o rr rr-sa.c -lRmath -lm /usr/lib/gcc-lib/i486-linux/3.3.2/../../../libRmath.so: undefined reference to `Rlog1p' collect2: ld returned 1 exit status ********************************************************************** rr-sa.c ********************************************************************** #include <stdio.h> #include <assert.h> #define T 3 #define INITVAL 1 #define MATHLIB_STANDALONE #define THETA 2 #include <Rmath.h> #include <time.h> void advance(double *node, int *current_pos, double newval); void retreat(double *node, int *current_pos); double new_val(double *node, double theta, int current_pos); double accept_prob(double *node, double theta, int current_pos); double accept_prob_fn(double a, double y); int main() { int currentpos = 0; int i; double newval, node[T+2], theta = THETA, p, u; set_seed(time(NULL), clock()); node[0]=0; for(i=1;i<=T;i++) node[i]= INITVAL; /* for simplicity choose all values the same */ node[T+1]=0; for(i=0; currentpos < T; i++) { u = unif_rand(); newval = new_val(node, theta, currentpos); p = accept_prob(node, theta, currentpos); printf("current position is %u\n",currentpos); printf("uniform random variable determining acceptance/rejection is %g\n",u); printf("value of acceptance probability is %g\n",p); printf("value of proposed new variable is %g\n",newval); if(u < p) advance(node,¤tpos,newval); else retreat(node, ¤tpos); } for(i=1;i <= T; i++) printf("value of node %u is %g\n",i,node[i]); return 0; } /* function that moves chain one step forward in the event of an acceptance */ void advance(double *node, int *current_pos, double newval) { *current_pos = *current_pos + 1; node[*current_pos] = newval; } /* function that moves the chain backwards in the event of a rejection*/ void retreat(double *node, int *current_pos) { /* need special handling for small values of current_pos */ if(*current_pos >= 1) *current_pos = *current_pos - 1; else if(*current_pos == 0) ; /* do nothing, already at beginning */ } /* generate new candidate value with appropriate distribution */ double new_val(double *node, double theta, int current_pos) { double a, u, y; u = unif_rand(); a = node[current_pos] + node[current_pos+2]; if (a != 0) y = (1/a)*log( ( exp(a*theta) - exp(-a*theta) )*u + exp(-a*theta) ); else /* degenerate case (for a=0) is Unif[-theta,theta] */ y = 2*theta*u - theta; return y; } /* generate acceptance probabilities for candidates*/ /* NB: This assumes: (a) That all the initial values of the starting state are set to -1 (b) That theta > 1. */ double accept_prob(double *node, double theta, int current_pos) { double a, p, y, num, denom, leftval, rtval; a = node[current_pos + 1]; y = node[current_pos] + node[current_pos+2]; num = accept_prob_fn(a, y); leftval = accept_prob_fn(a, -theta + node[current_pos+2]); rtval = accept_prob_fn(a, theta + node[current_pos+2]); denom = fmax2(leftval, rtval); /* function in Rmath which returns max of two doubles */ p = num/denom; assert(p>=0 && p <=1); return p; } /* auxilary function for accept_prob */ double accept_prob_fn(double a, double y) { double f; if(y != 0) f = (exp(y) - exp(-y))/(y*exp(a*y)); else f = 2; return f; }
Dirk Eddelbuettel
2003-Dec-14 03:25 UTC
[R] compile error with C code and standalone R math C library
On Sat, Dec 13, 2003 at 07:44:46PM -0500, Faheem Mitha wrote:> I just went back to an old piece of C code. On trying to compile it with > the R math standalone C library I got the following error. Can anyone > enlighten me what I am doing wrong, if anything? C file (rr-sa.c) follows. > > I'm on Debian sarge. I'm running R version 1.8.1. Gcc is version > 3.3.1.[...]> faheem ~/co/rr/trunk>gcc -o rr rr-sa.c -lRmath -lm > /usr/lib/gcc-lib/i486-linux/3.3.2/../../../libRmath.so: undefined > reference to `Rlog1p' > collect2: ld returned 1 exit statusThe linker tells you that it cannot find object code for a function Rlog1p. So let's check: edd at chibud:~> grep Rlog1p /usr/include/Rmath.h edd at chibud:~> grep log1p /usr/include/Rmath.h double log1p(double); /* = log(1+x) {care for small x} */ edd at chibud:~> Turns out that there is none defined in Rmath.h, but log1p exists. This may have gotten renamed since you first wrote your code. Hth, Dirk -- Those are my principles, and if you don't like them... well, I have others. -- Groucho Marx