11

I am reading the chapter 4 of "Seamless R and C++ Integration with Rcpp" and I had a little problem.

In the "listing 4.13" the book given a example about how to use a function of R. I tried use other functions (different of the example) and I had success. My code is here:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::DataFrame myrandom(Rcpp::NumericVector x) {
  int n = x.size();
  Rcpp::NumericVector y1(n), y2(n), y3(n);

  y1 = Rcpp::pexp(x,1.0,1,0);
  y2 = Rcpp::pnorm(x,0.0,1.0,1,0);
  y3 = Rcpp::ppois(x,3.0,1,0);

  return Rcpp::DataFrame::create(Rcpp::Named("Exp") = y1,Rcpp::Named("Norm") = y2, Rcpp::Named("Pois") = y3);
}


sourceCpp("random.cpp")
myrandom(c(0.5,1))

In this case is OK, but when I try use Rcpp::pt I don't have success. My code is here.

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::DataFrame myrandom2(Rcpp::NumericVector x) {
  int n = x.size();
  Rcpp::NumericVector y1(n);

  y1 = Rcpp::pt(x,3.0,0,1,0);

  return Rcpp::DataFrame::create(Rcpp::Named("T") = y1);
}

sourceCpp("random2.cpp")
myrandom2(c(0.5,1))

/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include/Rcpp/stats/nt.h: In function ‘Rcpp::stats::P2<RTYPE, NA, T> Rcpp::pt(const Rcpp::VectorBase<RTYPE, NA, VECTOR>&, double, double, bool, bool) [with int RTYPE = 14, bool NA = true, T = Rcpp::Vector<14>]’:
random2.cpp:8:   instantiated from here
/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include/Rcpp/stats/nt.h:25: error: invalid conversion from ‘double (*)(double, double, int, int)’ to ‘double (*)(double, double, double, int, int)’
/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include/Rcpp/stats/nt.h:25: error:   initializing argument 1 of ‘Rcpp::stats::P2<RTYPE, NA, T>::P2(double (*)(double, double, double, int, int), const Rcpp::VectorBase<RTYPE, NA, VECTOR>&, double, double, bool, bool) [with int RTYPE = 14, bool NA = true, T = Rcpp::Vector<14>]’
make: *** [random2.o] Error 1
llvm-g++-4.2 -arch x86_64 -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG  -I/usr/local/include  -I"/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include"    -fPIC  -mtune=core2 -g -O2  -c random2.cpp -o random2.o 

When I use Rcpp::pt(x,3) I want have control over de parameters od the function

pt(q, df, ncp, lower.tail = TRUE, log.p = FALSE)

I think that I'm not using correctly de function but I don't know what.

carlos1985
  • 318
  • 1
  • 9
  • 1
    Since you have some responses below that seem to answer your question, please consider marking one of them as ‘Accepted’ by clicking on the tickmark below their vote count. This shows which answer helped you most, and it assigns reputation points to the author of the answer (and to you!). It's part of this site's idea to identify good questions and answers through upvotes and acceptance of answers. – jub0bs Jan 05 '15 at 20:22

2 Answers2

8

Aren't C++ compiler messages lovely? ;-)

I think you just helped squash a really old bug. For both t and F, R actually has two functions group (r|p|q|d)t and (r|p|q|d)nt (ditto for f and nf) where the second form allows for the non-centrality parameter. And I think out header for nt.h was wrong.

If you make this change in file include/Rcpp/stats/nt.h

@@ -22,7 +22,7 @@
 #ifndef Rcpp__stats__nt_h
 #define Rcpp__stats__nt_h

-RCPP_DPQ_2(t,::Rf_dt,::Rf_pt,::Rf_qt)
+RCPP_DPQ_2(nt,::Rf_dnt,::Rf_pnt,::Rf_qnt)

 #endif

(which you can just edit in the header, no reinstallation needed) then things seem to work:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::DataFrame myrandom(Rcpp::NumericVector x) {
  Rcpp::NumericVector y1, y2, y3, y4, y5, y6, y7, y8;

  y1 = Rcpp::pexp(x,1.0,1,0);
  y2 = Rcpp::pnorm(x,0.0,1.0,1,0);
  y3 = Rcpp::ppois(x,3.0,1,0);
  y4 = Rcpp::pt(x,3.0,1,0);
  y5 = Rcpp::pnt(x,3.0,2,TRUE,FALSE);
  y6 = Rcpp::pnt(x,3.0,2,TRUE,TRUE);
  y7 = Rcpp::pnt(x,3.0,2,FALSE,TRUE);
  y8 = Rcpp::pnt(x,3.0,2,FALSE,FALSE);

  return Rcpp::DataFrame::create(Rcpp::Named("Exp") = y1,
                                 Rcpp::Named("Norm") = y2, 
                                 Rcpp::Named("Pois") = y3,
                                 Rcpp::Named("t") = y4,
                                 Rcpp::Named("nt1") = y5,
                                 Rcpp::Named("nt2") = y6,
                                 Rcpp::Named("nt3") = y7,
                                 Rcpp::Named("nt4") = y8);
}

I still need to check the numerics against R, but at least it builds now. (And TRUE/FALSE versus 1/0 does not matter; that gets cast correctly).

Edit: And here is some output:

> sourceCpp("/tmp/so1.cpp")  
R> myrandom(seq(0.2, 0.5, by=0.1))  
       Exp     Norm      Pois        t       nt1      nt2        nt3      nt4   
1 0.181269 0.579260 0.0497871 0.572865 0.0351335 -3.34860 -0.0357655 0.964866   
2 0.259182 0.617911 0.0497871 0.608118 0.0434710 -3.13566 -0.0444441 0.956529  
3 0.329680 0.655422 0.0497871 0.642032 0.0535219 -2.92767 -0.0550074 0.946478  
4 0.393469 0.691462 0.0497871 0.674276 0.0654790 -2.72603 -0.0677212 0.934521   
R>   
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • That is the price to pay for not having tested it. If anyone listening here wants to tackle this https://github.com/RcppCore/Rcpp/issues/29 in a systematic way, they are more than welcome. – Romain Francois Nov 22 '13 at 20:36
  • Actually, the test was there for several years, but wrong. We both goofed on that one. That said, additional testing would indeed be welcome. – Dirk Eddelbuettel Nov 22 '13 at 20:37
5

It seems that the Student-t distribution doesn't have a non-centrality parameter ncp; from Rmath.h:

/* Student t Distibution */
inline double dt(double x, double n, int lg) { return ::Rf_dt(x, n, lg); }
inline double pt(double x, double n, int lt, int lg) { return ::Rf_pt(x, n, lt, lg); }
inline double qt(double p, double n, int lt, int lg) { return ::Rf_qt(p, n, lt, lg); }
inline double rt(double n) { return ::Rf_rt(n); }

I can compile and execute your code with the following change:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::DataFrame myrandom2(Rcpp::NumericVector x) {
  int n = x.size();
  Rcpp::NumericVector y1(n);

  y1 = Rcpp::pt(x, 3.0, false, true);

  return Rcpp::DataFrame::create(Rcpp::Named("T") = y1);
}
rcs
  • 67,191
  • 22
  • 172
  • 153
  • 1
    Good answer, @rcs, but it bypasses the actual question of how to do this with the added `ncp` parameter. We had a bug there, I committed a fix earlier and will commit some more unit tests this eve. – Dirk Eddelbuettel Nov 22 '13 at 15:41