[Rcpp-devel] Organization of C++ classes for glm families

Romain Francois romain at r-enthusiasts.com
Tue Mar 16 23:28:21 CET 2010


Le 16/03/10 23:19, Romain Francois a écrit :
>
> Le 16/03/10 22:09, Douglas Bates a écrit :
>>
>> On Tue, Mar 16, 2010 at 3:24 PM, Dirk Eddelbuettel<edd at debian.org>   wrote:
>>
>>> That's an interesting problem.  AFAICT folks prefer iterators and transform()
>>> and its ilk because it allows you to swap vector() for, say, list() with minimal
>>> fuss.  It is less clear that you pick up speed that way.  Wouldn't the cost
>>> of log() dominate the looping, whether it's old school C style or via iterators?
>>
>> I was not sufficiently explicit.  The large amounts of time spent in
>> evaluating the inverse link and things like that are in the R
>> versions.   They use R constructions like
>>
>>> poisson()$linkinv
>> function (eta)
>> pmax(exp(eta), .Machine$double.eps)
>> <environment: 0x1c435e0>
>>
>> and it is (or, at least, was) the calls to pmax, pmin, etc. that
>> gobbled up the time.
>>
>> Several years ago I wrote C code using .Call for the usual link
>> functions in the binomial family, just to speed up such cases.  For
>> example, the default link for the binomial is
>>
>>> binomial()$linkinv
>> function (eta)
>> .Call("logit_linkinv", eta, PACKAGE = "stats")
>> <environment: 0x1c4b9e0>
>>
>> Using Rcpp I could certainly extract the R function from the family
>> and set up the call but for the heavily used families I would prefer
>> to set up a way to recognize the link name and use compiled code.
>>
>> In any case I now have code that seems to work
>>
>> otherd<- '
>> '
>> bod<- '
>>     Rcpp::NumericVector xv(x);
>>     Rcpp::NumericVector y(xv.size());
>>
>>     std::map<std::string, double(*)(double)>   lst;
>>     lst["log"] =&log;
>>     std::transform(xv.begin(), xv.end(), y.begin(), *(lst["log"]));
>>     return y;
>> '
>> ff<- cfunction(signature(x = "numeric"), bod, Rcpp = TRUE, verbose = FALSE,
>>                   otherdefs = otherd, includes = "#include<cmath>")
>
> It seems you answered your own questions ?
>
> Maybe it is worth investigating external pointers, which would offer a
> way to have some handle on the function pointer&log from the R side.
>
> We have Rcpp::XPtr for that, but I'm not sure right now what the right
> incantation would be to hold function pointers
>
> (... time passes ...) Maybe it would be easier to wrap the function into
> an std::unary_function<double,double>  ..
>
> (I need to think about this in the morning, with fresh coffee).
>
> Romain

Last try, maybe something like this :

fx <- cfunction( signature(),
'
   typedef pointer_to_unary_function <double,double> link_fun ;
   link_fun* log_link = new link_fun(log);
   Rcpp::XPtr<link_fun> xp( log_link, true );
   return xp ;

', Rcpp = TRUE, includes =
   c("using namespace Rcpp; ", "using namespace std;" ) )


 > fx()
<pointer: 0x100584930>

... maybe when I wake up tomorrow, none of this will make sense

Romain


-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/OIXN : raster images and RImageJ
|- http://tr.im/OcQe : Rcpp 0.7.7
`- http://tr.im/O1wO : highlight 0.1-5



More information about the Rcpp-devel mailing list