caburke
caburke

Reputation: 268

Passing mean and standard deviation into dnorm() using Rcpp Sugar

I am converting some R code to Rcpp code and need to calculate the likelihood for a vector of observations given a vector of means and vector of standard deviations. If I assume the means are 0 and the standard deviations 1, I can write this function (running this requires the 'inline' and 'Rcpp' packages to be loaded),

dtest1 = cxxfunction(signature( x = "numeric"),
                      'Rcpp::NumericVector xx(x);
                       return::wrap(dnorm(xx, 0.0, 1.0));', 
                       plugin='Rcpp')

and the result is as expected.

> dtest1(1:3) 
[1] 0.241970725 0.053990967 0.004431848

However, if I try to make a function

dtest2 = cxxfunction(signature( x = "numeric", y="numeric", z="numeric" ),
                  'Rcpp::NumericVector xx(x);
                   Rcpp::NumericVector yy(y);
                   Rcpp::NumericVector zz(z);
                   return::wrap(dnorm(xx, yy, zz));',
                   plugin='Rcpp')

which would allow me to pass in different means and standard deviations results in an error, shown below. Is there a way to make the function I am trying to make, or I do need to program the normal density manually?

Error

Error in compileCode(f, code, language = language, verbose = verbose) :   
    Compilation ERROR, function(s)/method(s) not created! file31c82bff9d7c.cpp: In function ‘SEXPREC* file31c82bff9d7c(SEXP, SEXP, SEXP)’:
file31c82bff9d7c.cpp:33:53: error: no matching function for call to 
     ‘dnorm4(Rcpp::NumericVector&, Rcpp::NumericVector&, Rcpp::NumericVector&)’
file31c82bff9d7c.cpp:33:53: note: candidates are:
/home/chris/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include/Rcpp/stats/norm.h:106:1: 
     note: template<int RTYPE, bool NA, class T> Rcpp::stats::D0<RTYPE, NA, T> Rcpp::dnorm4(const Rcpp::VectorBase<RTYPE, NA, VECTOR>&, bool)
/home/chris/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include/Rcpp/stats/norm.h:107:1: 
     note: template<int RTYPE, bool NA, class T> Rcpp::stats::D1<RTYPE, NA, T> Rcpp::dnorm4(const Rcpp::VectorBase<RTYPE, NA, VECTOR>&, double, bool)
/home/chris/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include/Rcpp/stats/norm.h:108:1: 
     note: template<int RTYPE, bool NA, class T> Rcpp::stats::D2<RTYPE, NA, T> Rcpp::dnorm4(const Rcpp::VectorBase<RTYPE, NA,
In addition: Warning message:
running command '/usr/lib/R/bin/R CMD SHLIB file31c82bff9d7c.cpp 2> file31c82bff9d7c.cpp.err.txt' had status 1

Upvotes: 3

Views: 2589

Answers (1)

Romain Francois
Romain Francois

Reputation: 17642

The sugar dnorm is only vectorized in terms of the first argument.

To simplify (it is slightly more involved, but we don't need to concern ourselves with this yet here), the call

dnorm(xx, 0.0, 1.0)

uses the overload

NumericVector dnorm( NumericVector, double, double )

And the second call tries to use something like

NumericVector dnorm( NumericVector, NumericVector, NumericVector )

which is not implemented. We could implement it, it would have to go high enough in our priority list.

In the meantime, it is easy enough to write a small wrapper, like (this does not handle argument lengths, etc ...) :

NumericVector my_dnorm( NumericVector x, NumericVector means, NumericVector sds){
    int n = x.size() ;
    NumericVector res(n) ;
    for( int i=0; i<n; i++) res[i] = R::dnorm( x[i], means[i], sds[i] ) ;
    return res ;
}

Upvotes: 7

Related Questions