Hi all, Looking at the body for the function rnorm, I see that the body of the function is: .Call(C_rnorm, n, mean, sd) I want to implement functions that generate normal (and other) random variables. Now, I understand that I can perfectly well just call the R wrapper for these functions and that will be almost indistinguishable for most purposes, but for whatever reason I wanted to try and call the C function directly. My first instinct was to call them as: .Call(C_rnorm, 1, 1, 1) This doesn't work because R assumes C_rnorm is an object. Looking at the documentation for .Call, I try passing it in as a string: .Call("C_rnorm", 1, 1, 1, PACKAGE = "stats") This doesn't work either. The help page links to getNativeSymbolInfo(), which I can't make work either. It also refers me to the dyn.load() function and the "Writing R Extensions" manual. After reading and trying to digest those, I try getDLLRegisteredRoutines("stats") which shows me all the C and Fortran functions as registered routines, along with their number of parameters. I retrieve rnorm from the list and pass it on to .Call, which then works fine. However, is there an easier way to do this? Specifically, I would like to call the DLL registered routines from within functions in a package I am writing. The manual tells me I should use useDynLib(). So if I added useDynLib("stats") to my namespace, would that work? Could I then have a function such as: function(x, y, z) .Call(C_rnorm, x, y, z) in my package? If not, what is the proper way of calling these functions from other packages? Should I use "C_rnorm" or "norm"? Also, I was looking for the C source code of rnorm, because I wanted to understand how the function works. Looking at Winston Chang's github R mirror, I found rnorm in the random.c file in the stats package. However, the code I find for it: #define DEFRAND2_REAL(name) \ SEXP do_##name(SEXP sn, SEXP sa, SEXP sb) { \ return random2(sn, sa, sb, name, REALSXP); \ } DEFRAND2_REAL(rnorm) Doesn't help me at all in understanding how it works. It should create a function random2(sn, sa, sb, norm, REALSXP); I understand that is a version of the random2 function that returns a real S expression taking sn, sa and sb as parameters. But how does find the actual functional form for the normal distribution? I am asking because I would like to rewrite some of the other functions, such as parameterizing rbeta by the mean and sample size rather than by the number of successes and failures and rgamma by the mean and total time elapsed instead of the number of events. Once I understand how the C source code works, it would be hopefully not very difficult to reparameterize them. Thanks, Luis Usier [[alternative HTML version deleted]]
Luis, C_rnorm is a symbol but it's not exported. This means that you *can* do this by using stats:::C_rnorm. That said, it's not exported, which means that it's not supported to do this. So your package likely would not be allowed on CRAN, for example. Best, ~G On Jun 30, 2016 2:08 PM, "Luis Usier" <luis.henrique.usier at gmail.com> wrote:> Hi all, > > Looking at the body for the function rnorm, I see that the body of the > function is: > > .Call(C_rnorm, n, mean, sd) > > I want to implement functions that generate normal (and other) random > variables. Now, I understand that I can perfectly well just call the R > wrapper for these functions and that will be almost indistinguishable for > most purposes, but for whatever reason I wanted to try and call the C > function directly. My first instinct was to call them as: > > .Call(C_rnorm, 1, 1, 1) > > This doesn't work because R assumes C_rnorm is an object. Looking at the > documentation for .Call, I try passing it in as a string: > > .Call("C_rnorm", 1, 1, 1, PACKAGE = "stats") > > This doesn't work either. The help page links to getNativeSymbolInfo(), > which I can't make work either. It also refers me to the dyn.load() > function and the "Writing R Extensions" manual. > > After reading and trying to digest those, I try > > getDLLRegisteredRoutines("stats") > > which shows me all the C and Fortran functions as registered routines, > along with their number of parameters. I retrieve rnorm from the list and > pass it on to .Call, which then works fine. > > However, is there an easier way to do this? Specifically, I would like to > call the DLL registered routines from within functions in a package I am > writing. The manual tells me I should use useDynLib(). So if I added > useDynLib("stats") to my namespace, would that work? Could I then have a > function such as: > > function(x, y, z) .Call(C_rnorm, x, y, z) > > in my package? If not, what is the proper way of calling these functions > from other packages? Should I use "C_rnorm" or "norm"? > > Also, I was looking for the C source code of rnorm, because I wanted to > understand how the function works. Looking at Winston Chang's github R > mirror, I found rnorm in the random.c file in the stats package. However, > the code I find for it: > > > > #define DEFRAND2_REAL(name) \ > SEXP do_##name(SEXP sn, SEXP sa, SEXP sb) { \ > return random2(sn, sa, sb, name, REALSXP); \ > } > DEFRAND2_REAL(rnorm) > > > Doesn't help me at all in understanding how it works. It should create a > function random2(sn, sa, sb, norm, REALSXP); I understand that is a version > of the random2 function that returns a real S expression taking sn, sa and > sb as parameters. But how does find the actual functional form for the > normal distribution? > > I am asking because I would like to rewrite some of the other functions, > such as parameterizing rbeta by the mean and sample size rather than by the > number of successes and failures and rgamma by the mean and total time > elapsed instead of the number of events. Once I understand how the C source > code works, it would be hopefully not very difficult to reparameterize > them. > > Thanks, > > Luis Usier > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]
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:> Luis, > > C_rnorm is a symbol but it's not exported. This means that you *can* do > this by using stats:::C_rnorm. > > That said, it's not exported, which means that it's not supported to do > this. So your package likely would not be allowed on CRAN, for example. > > Best, > ~G > On Jun 30, 2016 2:08 PM, "Luis Usier" <luis.henrique.usier at gmail.com> > wrote: > >> Hi all, >> >> Looking at the body for the function rnorm, I see that the body of the >> function is: >> >> .Call(C_rnorm, n, mean, sd) >> >> I want to implement functions that generate normal (and other) random >> variables. Now, I understand that I can perfectly well just call the R >> wrapper for these functions and that will be almost indistinguishable for >> most purposes, but for whatever reason I wanted to try and call the C >> function directly. My first instinct was to call them as: >> >> .Call(C_rnorm, 1, 1, 1) >> >> This doesn't work because R assumes C_rnorm is an object. Looking at the >> documentation for .Call, I try passing it in as a string: >> >> .Call("C_rnorm", 1, 1, 1, PACKAGE = "stats") >> >> This doesn't work either. The help page links to getNativeSymbolInfo(), >> which I can't make work either. It also refers me to the dyn.load() >> function and the "Writing R Extensions" manual. >> >> After reading and trying to digest those, I try >> >> getDLLRegisteredRoutines("stats") >> >> which shows me all the C and Fortran functions as registered routines, >> along with their number of parameters. I retrieve rnorm from the list and >> pass it on to .Call, which then works fine. >> >> However, is there an easier way to do this? Specifically, I would like to >> call the DLL registered routines from within functions in a package I am >> writing. The manual tells me I should use useDynLib(). So if I added >> useDynLib("stats") to my namespace, would that work? Could I then have a >> function such as: >> >> function(x, y, z) .Call(C_rnorm, x, y, z) >> >> in my package? If not, what is the proper way of calling these functions >> from other packages? Should I use "C_rnorm" or "norm"? >> >> Also, I was looking for the C source code of rnorm, because I wanted to >> understand how the function works. Looking at Winston Chang's github R >> mirror, I found rnorm in the random.c file in the stats package. However, >> the code I find for it: >> >> >> >> #define DEFRAND2_REAL(name) \ >> SEXP do_##name(SEXP sn, SEXP sa, SEXP sb) { \ >> return random2(sn, sa, sb, name, REALSXP); \ >> } >> DEFRAND2_REAL(rnorm) >> >> >> Doesn't help me at all in understanding how it works. It should create a >> function random2(sn, sa, sb, norm, REALSXP); I understand that is a >> version >> of the random2 function that returns a real S expression taking sn, sa and >> sb as parameters. But how does find the actual functional form for the >> normal distribution? >> >> I am asking because I would like to rewrite some of the other functions, >> such as parameterizing rbeta by the mean and sample size rather than by >> the >> number of successes and failures and rgamma by the mean and total time >> elapsed instead of the number of events. Once I understand how the C >> source >> code works, it would be hopefully not very difficult to reparameterize >> them. >> >> Thanks, >> >> Luis Usier >> >> [[alternative HTML version deleted]] >> >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel >> >[[alternative HTML version deleted]]