Skip to content

Calling C implementations of rnorm and friends

4 messages · Joshua Ulrich, Gabriel Becker, Luis Usier

#
Gabriel,

Thanks for that! I guess I really should have figured that one out sooner,
huh?

I understand why that wouldn't be CRAN-compliant. But then, what *is* the
proper way to do it? Is there any way I can call unexported functions from
another package and have it accepted by CRAN?

Also, if I instead re-write the random variable generating functions, do
you have any idea of where the source code is in the stats package? As I
said above, I can't seem to find the source code for the functional forms.

Thanks,

Luis

On Thu, Jun 30, 2016 at 10:38 PM, Gabriel Becker <gmbecker at ucdavis.edu>
wrote:

  
  
#
On Fri, Jul 1, 2016 at 6:13 AM, Luis Usier
<luis.henrique.usier at gmail.com> wrote:
There may be ways to call unexported functions that R CMD check will
not detect, but you should not look for ways to violate the spirit of
the policy.  Work-arounds include asking the package maintainer to
export the functionality you want, or you can copy the desired
functionality to your package (with attribution, of course).

In this particular case, you can probably get what you want via the
Rmath library.  It provides C-level access to all the distribution
functions (and more).  You would need something like this in your C
code:

#include <Rmath.h>
GetRNGstate();
double rn = rnorm(0.0, 1.0);
PutRNGstate()

Once Dirk recovers from useR!, he'll tell you how this is all
super-easy if you just use Rcpp. ;)
See the sections "Functions that call compiled code" and "Compiled
code in a base package" from this answer:
http://stackoverflow.com/a/19226817/271616

That should give you a few pointers on where/how to look.

  
    
#
Well,

For this particular use case why not just transform the parameters at the R
level and then call the existing function? Is there not a closed form
mapping?

~G
On Jul 1, 2016 2:50 PM, "Joshua Ulrich" <josh.m.ulrich at gmail.com> wrote:

            

  
  
#
Gabriel,

That's exactly what I have been doing, and it works fine. However, I just
wanted to *understand* how the random numbers are generated, for no other
reason than to satiate my curiosity.

The one thing that's not very elegant about this way of doing things is
that I have to hard-code special rules for parameter values that are
infinite. I guess there's no other way though; I finally found something
closer to the source code for rnorm which for some reason is *not* in the
stats package folder but in "nmath/rnorm.c":

double rnorm(double mu, double sigma)
{

if (ISNAN(mu) || !R_FINITE(sigma) || sigma < 0.)

ML_ERR_return_NAN;

if (sigma == 0. || !R_FINITE(mu))

return mu; /* includes mu = +/- Inf with finite sigma */

else

return mu + sigma * norm_rand();

}

However, this just scales the result from calling the function norm_rand(),
which I cannot find anywhere : (


Following Joshua's suggestion should only show me functions from the base
package, that is, functions called with .Primitive() and .Internal(). Since
I'm looking at a function from the stats package called with .Call() I
thought it shouldn't be names.c. BUT, it turns out that it *is* actually
there and is also a function that can be called with .Internal() from the
base package. So, surprisingly enough, this:

.Internal(rnorm(1, 0, 1))

actually works, even in the command line, as all functions from base are
always accessible : ) Am I allowed to do this? There's a note in the source
code that says "Can remove all the [dpqr]xxx once the compiler knows how to
optimize
to .External.", whatever that means; I feel like R CMD check/CRAN may not
like it if I call norm and friends from base.

Anyway, thank you both for your help! Any extra nuggets of wisdom would be
appreciated, but this was already very helpful.

Luis

On Sat, Jul 2, 2016 at 12:24 AM, Gabriel Becker <gmbecker at ucdavis.edu>
wrote: