require(inline)
func <- cxxfunction(, 'return Rcpp::wrap( qnorm(0.95,0.0,1.0) );' ,plugin="Rcpp")
error: no matching function for call to ‘qnorm5(double, int, int)’
require(inline)
func <- cxxfunction(, 'return Rcpp::wrap( qnorm(0.95, 0.0, 1.0, 1, 0) );'
,plugin="Rcpp")
error: no matching function for call to ‘qnorm5(double, double, double, int, int)’
require(inline)
code <-'
double a = qnorm(0.95, 0.0, 1.0);
return Rcpp::wrap( a );
'
func <-
cxxfunction(, code ,plugin="Rcpp")
func()
error: no matching function for call to ‘qnorm5(double, double, double)’
How can I use qnorm on Rcpp?
By making the mean and sd arguments double as the error message shows -- so try this is a full example
library(inline)
f <- cxxfunction(signature(xs="numeric", plugin="Rcpp", body='
Rcpp::NumericVector x(xs);
return Rcpp::wrap(Rcpp::qnorm(x, 1.0, 0.0));
')
and have a look at the examples and unit tests -- I just looked this up in the unit test file runit.stats.R which has a lot of test cases for these statistical 'Rcpp sugar' functions.
Edit on 2012-11-14: With Rcpp 0.10.0 released today, you can call do the signature R::qnorm(double, double, double, int, int) if you want to use C-style code written against Rmath.h. Rcpp sugar still gives you vectorised versions.
Related
Recently I am trying to add a Fortran function into an existing R package that contains C++ code and is build under Rcpp package. I have successfully added the Fortran function and build the R package. But when I try to run an example for the R package for different times, each time the function returns a different value, which a bit confusing since the Fortran function I added has no undeterministic parameter or contains self iteration. Also sometimes when I try to run the function, R crashes.
This is a part of the Fortran function that are in the file "src/k2s.f95"
REAL*8 FUNCTION k2(n1,n2,n3,vec1,length1,a1,vec2,length2,a2)
integer :: n1,n2,n3,length1,length2
integer, dimension(length1) :: vec1
double precision :: a1,a2
double precision, dimension(length2):: vec2
double precision :: P(n1+2)
...
k2 = -1.0
IF ((n1<1) .OR. (n2<1) .OR. (length2 .NE. n1+n2-1) .OR. (n3<1) .OR. (n3 > 3)) RETURN
k2 = -2.0
IF(MINVAL(vec1).LE.0) RETURN
IF(SUM(vec1).NE.(n1+n2)) RETURN
IF(MINVAL(vec2).LE.0) RETURN
...
END FUNCTION K2
And I have used this answer Integrate Fortran, C++ with R to construct the package. Therefore I have written the following C++ file under src dictionary. This is the content of C++ file "k2s2.cpp"
#include "Rcpp.h"
extern "C" {
double k2_(int *n1, int *n2, int *n3, int vec1[], int *length1, double *a1, double vec2[], int *length2, double *a2);
}
// [[Rcpp::export]]
double K2_fortran(int n1, int n2, int n3, Rcpp::IntegerVector vec1, double a1, Rcpp::NumericVector vec2, double a2)
{
int length1 = vec1.size();
int length2 = vec2.size();
double q = 0;
pval = k2_(&n1,&n2,&n3,vec1.begin(),&length1,&a1,vec2.begin(),&length2,&a2);
return q;
}
I think it should be fine. Then I build the package (with Rcpp automatically generates the file "src/RcppExports.cpp" and "R/RcppExports.R" to link the cpp function K2_fortran to R) and load all the functions, then I get the R function K2_fortran. And I run the following example.
K2_fortran(120, 150, 1, c(80,70,40,80), 0.1, rep(1,269), 1e-6)
And the result is -2. Then I rerun the code for the second time, I got the expected result 0.175. For the third time, I got 1(some other returned value when there is an error). Then I run it again, a fatal error occurs in R and closes the R.
If I reopen it and run this example 4 times again. The result will be again -2, 0.175, 1 and a fatal error. I am not sure what has happened.
I'm trying to call BLAS in Julia using ccall like this
ccall((BLAS.#blasfunc(:zgemm_), BLAS.libblas),...other arguments)
For as far as I can tell, this is the same way the LinearAlgebra package calls BLAS (link to source)
I get the following error however:
ccall: could not find function :zgemm_64_ in library libopenblas64_
Anyone have any idea what could be the problem?
EDIT: found out that using :zgemm_64_ directly instead of BLAS.#blasfunc(:zgemm_) solved the error, but I'd still like to know why.
In case it becomes necessary, here is the full function where I make the BLAS call.
import LinearAlgebra: norm, lmul!, rmul!, BlasInt, BLAS
# Preallocated version of A = A*B
function rmul!(
A::AbstractMatrix{T},
B::AbstractMatrix{T},
workspace::AbstractVector{T}
) where {T<:Number}
m,n,lw = size(A,1), size(B,2), length(workspace)
if(size(A,2) !== size(B,1))
throw(DimensionMismatch("dimensions of A and B don't match"))
end
if(size(B,1) !== n)
throw(DimensionMismatch("A must be square"))
end
if(lw < m*n)
throw(DimensionMismatch("provided workspace is too small"))
end
# Multiplication via direct blas call
ccall((BLAS.#blasfunc(:zgemm_), BLAS.libblas), Cvoid,
(Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt},
Ref{BlasInt}, Ref{T}, Ptr{T}, Ref{BlasInt},
Ptr{T}, Ref{BlasInt}, Ref{T}, Ptr{T},
Ref{BlasInt}),
'N', 'N', m, n,n, 1.0, A, max(1,stride(A,2)),B, max(1,stride(B,2)), 0.0, workspace, n)
# Copy temp to A
for j=1:n
for i=1:m
A[i,j] = workspace[j+*(i-1)*n]
end
end
end
function test_rmul(m::Integer, n::Integer)
BLAS.set_num_threads(1)
A = rand(ComplexF64, m,n)
Q = rand(ComplexF64, n,n)
workspace = similar(A, m*n)
A_original = copy(A)
Q_original = copy(Q)
rmul!(A,Q,workspace)
#show norm(A_original*Q_original - A)
#show norm(Q_original - Q)
end
test_rmul(100,50)
BLAS.#blasfunc(:zgemm_) returns Symbol(":zgemm_64_"), and not :zgemm_64_, which looks rather strange in the first place... it's hygienic in the technical sense, but admittedly confusing. The reason it works in the original implementation is because there, the symbol with the name is always spliced into #eval; compare:
julia> #eval begin
BLAS.#blasfunc(:zgemm_)
end
Symbol(":zgemm_64_")
julia> #eval begin
BLAS.#blasfunc($(:zgemm_))
end
:zgemm_64_
So, #blasfunc expects its argument to be a name (i.e., a symbol in the AST), not a symbol literal (a quoted symbol in the AST). You could equivalently write it like a variable name:
julia> #eval begin
BLAS.#blasfunc zgemm_
end
:zgemm_64_
(without zgemm_ being actually defined in this scope!)
I have a cpp function which has an R function as one of its arguments like below:
void mycppfunction(SEXP x, Rcpp::Function func)
func can be a function, or it can be NULL. How can I implement this? If I do this:
void mycppfunction(SEXP x, Rcpp::Nullable<Rcpp::Function> func)
then, the line:
func(x)
gives me the error:
error: no match for call to ‘(Rcpp::Nullable<Rcpp::Function_Impl<Rcpp::PreserveStorage> >) (SEXP)’
On the other hand, if I just define mycppfunction as:
void mycppfunction(SEXP x, Rcpp::Function func)
then running the code with a NULL value for func results in a segfault: "memory not mapped".
Yes you can do this but I would advise that you are careful about verifying the compatibility of the function passed in and the argument. Here's a small example, with minimal defensive code to ensure that f is a valid function:
#include <Rcpp.h>
typedef Rcpp::Nullable<Rcpp::Function> nullable_t;
// [[Rcpp::export]]
SEXP null_fun(Rcpp::NumericVector x, nullable_t f = R_NilValue) {
if (f.isNotNull()) {
return Rcpp::as<Rcpp::Function>(f)(x);
}
return Rcpp::wrap((double)Rcpp::sum(x));
}
/*** R
null_fun(1:5)
#[1] 15
null_fun(1:5, mean)
#[1] 3
null_fun(1:5, min)
#[1] 1
null_fun(1:5, max)
#[1] 5
*/
Note that the use of SEXP as a return type and the Rcpp::wrap((double)...) was just to quiet the compiler in this specific example, and won't necessarily apply to your use case(s).
I am wondering if there is a way to call an R function in a particular package from Rcpp. For example, I would like to call "dtrunc" function in "truncdist" package in my Rcpp file. Is it possible to do that?
Sure. You'd grab the function like this:
Environment truncdist("package:truncdist") ;
Function dtrunc = truncdist["dtrunc"] ;
Or even this with version 0.11.5
Function dtrunc( "dtrunc", "truncdist" ) ;
Yes, you can use an R function within Rcpp.
library(inline)
src <- '
using namespace Rcpp;
Environment truncdist("package:truncdist");
Function dtrunc = truncdist["dtrunc"];
NumericVector res = dtrunc(x, "norm", 1, 2);
return res;
'
x <- seq( 0, 3, .1 )
fun <- cxxfunction(signature(x="numeric"),src, plugin="Rcpp")
identical(fun(x), dtrunc( x, spec="norm", a=1, b=2 ))
As a note, you need to keep in mind that the performance of dtrunc will not improve simply by being inside Rcpp. It will essentially be the exact same speed as if you called it directly in R.
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
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 ;
}