Eventhough I highly recommend using C++
together with R
, in some cases fortran can be faster. For simple problems that do not require additional libraries and when the intel
compiler is avaibalbe, f90
can be a very good option.
In this note we will see how one can write some f90
code and call it from R
. You will notice however how this procedure is less convenient than when using Rcpp
.
What needs to be done is:
let's write a very simple matrix multiplication
subroutine fmult(A,X,Y,n,m)
implicit none
integer :: n,i,j
double precision,dimension(n,m) :: A
double precision,dimension(m) :: X
double precision,dimension(n) :: Y
do i = 1,n
Y(i)=0
do j = 1,m
Y(i) = Y(i) + A(i,j,1) * X(j)
end do
end do
end
save this code to fmult.f90
, we then compile it into a library using the following command:
R CMD SHLIB fmult.f90
at this point we can start R, load the library and call the function:
dyn.load('fmult.so')
A = array(runif(100),c(10,10))
X = array(runif(10),c(10))
res = .Fortran('fmult', A=A, X=X, Y=double(length(X)),as.integer(dim(A)[1]),as.integer(dim(A)[2]))
print(res$Y)
Now we want to write a wrapper that will call the f90
function. Rcpp
and inline
are packages that do this automatically. Unfortunately, at the moment, neither seems to work properly with f90
so we will do it by hand.
matmult <- function(A,X) {
if (!is.loaded(symbol.For('fmult'))) {
dyn.load('fmult.so')
}
res = .Fortran('fmult', A=A, X=X, Y=double(length(X)),as.integer(dim(A)[1]),as.integer(dim(A)[2]))
return(res$Y)
}
and we are done!
as.integer
or they will be set to 0
nm -g
in the terminalimplicit none