[R] Modifying Internal C Files

Ken Kelley KKIII at Indiana.Edu
Tue Nov 8 12:33:41 CET 2005


Thanks for your thoughts Prof. Ripley.

When I set out to do this I had no idea it would be so difficult. 
Nevertheless, perhaps the best thing would be for me to say why I want 
to change internal parts of the function and why the best solution might 
be for it to be done in the next release of R. At the beginning of the 
pnbeta.c file we see:

     /* change errmax and itrmax if desired */

     const static double errmax = 1.0e-9;
     const int    itrmax = 100;

Which obviously sets the limits for the error and for the number of 
iterations. The comment says to change if desired, but there is no way 
for the user to modify these values. If you recall, I posted on problems 
with the pf() function for large noncentral parameters (On Oct. 24 and 
filed a bug #8251). Since pf() uses the pnbeta.c, the limitations in 
pnbeta.c filter though to the pf() function. My thoughts about the 
limitations of the iterations where confirmed when Chattamvelli and 
Shanmugam (1997; _Applied Statistics_) illustrate in their table that 
the method R uses (Length, 1987, and the Frick, 1990, update) that 
indeed the number of iterations can go well above 100. Dr. T. Lumley 
emailed the list saying increasing the iterations does in fact seem to 
solve the problems I described (presumably he modifying the source code 
directly).

So, can the itrmax be changed inside of pnbeta.c to some large value 
(e.g., 5000; realizing most problems will converge after only a few 
iterations). Or can the pbeta() function (possibly pf() since it uses 
pbeta.c) have parameters added that allows user control over these 
values? I would very much appreciate if this could be done, and 
obviously it would make R a bit more stable for large noncentral values 
(which are growing more important in some areas). That way everyone has 
a working function and not just me (If I were to be able to modify this 
internal function anyway!). As an aside, the Chattamvelli and Shanmugam 
(1997) paper update the algorithms that pnbeta.c is based (Algorithm AS 
310). It would be nice to incorporate this into R at some point, but 
first taking care of the iteration issue would be easy to take care of 
right now.

Thanks,
Ken

Prof Brian Ripley wrote:
> In your first post you said you called .C.  Here you say you call 
> .Internal.  Users cannot add .Internal functions, nor can they be used 
> in packages. In any case, The syntax is not as you show, but
> 
>     .Internal(pnbeta(q, shape1, shape2, ncp, lower.tail, log.p))
> 
> (And to be definite, that calls the C function do_math4, not pnbeta.)
> 
> Final comment:  Duncan mentioned
> 
>>> double pnbeta2(double x, double a, double b, double lambda,
>>>           int lower_tail, int log_p)
> 
> 
> but a .C call has to be to a function with all arguments as pointers, so 
> there would need a wrapper function.
> 
> The reason you are finding this difficult is that you are not dealing 
> with the C function behind .Internal, but one deeper into the system. 
> The simplest thing to do would be to compile R from the sources, then 
> make modifications and rebuild.  But in this case I believe Thomas 
> Lumley has already modified the R-devel sources and Duncan Murdoch has 
> provided Windows binaries of R-devel, so perhaps there is a much simpler 
> route?
> 
> 
> On Mon, 7 Nov 2005, Ken Kelley wrote:
> 
>> Hi Duncan and others.
>>
>> Thanks for your insight. Actually, I did change the function name in the
>> pnbeta2.c code (I should have said so). When I check the package I get
>> no errors. I build the package and all seems well. When I install and
>> then load the package in R, I get:
>>
>> > pnbeta2
>> function (x, a, b, lambda, low.tail, log.p)
>> {
>>     res <- .Internal("pnbeta2", as.double(x), as.double(a),
>> as.double(b), as.double(lambda), as.integer(low.tail), as.integer(log.p))
>>     return(list(res))
>> }
>> <environment: namespace:try>
>>
>> which seems good, but the function does not work:
>>
>> pnbeta2(.1, 10, 25, 2, TRUE, FALSE)
>> Error in pnbeta2(0.1, 10, 25, 2, TRUE, FALSE) :
>>         7 arguments passed to '.Internal' which requires 1
>>
>> When I try to run the .Internal file directly is perhaps where my
>> problems begin:
>> > .Internal(pnbeta2(.1, 10, 25, 2, TRUE, FALSE))
>> Error in .Internal(pnbeta2(0.1, 10, 25, 2, TRUE, FALSE)) :
>>         no internal function "pnbeta2"
>>
>> But, when I do the same thing to the pnbeta internal function (which
>> pnbeta2 is identical to at this point) I get the result:
>> > .Internal(pnbeta(.1, 10, 25, 2, TRUE, FALSE))
>> [1] 0.0006837318
>>
>> So, I'm at a loss for what is going on in this situation. my pnbeta2
>> internal function doesn't seem to be there. What I want to do is simple
>> (modify an interal C file), but it is proving to be quite difficult for
>> me to implement.
>>
>> Thanks for any thoughts,
>> Ken
>>
>>
>> Duncan Murdoch wrote:
>>
>>> On 11/7/2005 5:17 PM, Ken Kelley wrote:
>>>
>>>> Hi All.
>>>> I want to tweak a few minor things inside of internal C code. I have
>>>> my Win. XP machine set-up to build packages (including C code), but
>>>> I'm having problems getting the package to run correctly. In
>>>> particular, I want to modify a few things inside of pnbeta.c (namely
>>>> errmax and itrmax), which is what the pbeta() function calls upon when
>>>> there is a noncentral parameter. I copied the pnbeta.c C code, changed
>>>> its name [to pnbeta2.c], included the nmath.h, dpq.h files, lgamma.c,
>>>> and pbeta.c in my src folder (since the .h files were called upon and
>>>> the .c files were). I then created an R function that I thought would
>>>> call upon the new C code:
>>>>
>>>> pnbeta2 <- function(x, a, b, lambda, low.tail, log.p)
>>>> {
>>>> res <- .C("pnbeta2", as.double(x), as.double(a), as.double(b),
>>>> as.double(lambda), as.integer(low.tail), as.integer(log.p))
>>>> return(list(res))
>>>> }
>>>>
>>>> But after I built the package and loaded it it, the function doesn't
>>>> work (it isn't even recognized). I have no idea why this is failing.
>>>> Any information to help me figure out what I need to do to modify
>>>> internal C code generally, or specifically as it applies to this
>>>> scenario would be most helpful.
>>>
>>>
>>>
>>> You didn't say that you changed the name of the function, only the file
>>> that contained it.  If this wasn't an oversight, then you should put
>>>
>>> double pnbeta2(double x, double a, double b, double lambda,
>>>           int lower_tail, int log_p)
>>>
>>> in the appropriate place in your pnbeta2.c file.
>>>
>>> The other thing you should do is to add a PACKAGE argument to your .C
>>> call, just in case there is already a pnbeta2 function somewhere else
>>> (or will be some day).  In fact, if you do this, there should be no need
>>> to change the name of the function:  R will look in the package DLL
>>> rather than R.dll to find it.  Just make sure that the name in the .C
>>> call matches the declared name in the source.
>>>
>>> Duncan Murdoch
>>>
>>
>> -- 
>> Ken Kelley, Ph.D.
>> Inquiry Methodology Program
>> Indiana University
>> 201 North Rose Avenue, Room 4004
>> Bloomington, Indiana 47405
>> http://www.indiana.edu/~kenkel
>>
>> ______________________________________________
>> 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
>>
> 

-- 
Ken Kelley, Ph.D.
Inquiry Methodology Program
Indiana University
201 North Rose Avenue, Room 4004
Bloomington, Indiana 47405
http://www.indiana.edu/~kenkel




More information about the R-help mailing list