R packages with Fortran code

R is an open-source programming language primarily for statistics. There are about 18000 R packages, and 218 of them have some Fortran code, almost all of it FORTRAN 77 or earlier. There are 759 and 1000 packages using C and C++. R uses gfortran as its Fortran compiler. It is a high-level language in which “arrays know their own size”, so an R wrapper for a FORTRAN code is similar to what a modern Fortran wrapper would look like. One can look at R, Octave, and SciPy as places to “scavenge” well-tested, if often old-fashioned, Fortran code. One can search packages by both programming language and topic – there are for example 21 R packages with Fortran code for regression.

7 Likes

Wikipedia states R to be partially written in R, and other parts in C and Fortran. Recently, @KjellJorner initiated a discussion how to engage Fortran from Python with examples like f2py. Perhaps in contrast to you @Beliavsky, or others, I do not possess any working knowledge about R and still ask – out of curiosity*: is there a similar bridge, while working within R, to reach out for Fortran? For me, FortranCallsR found on the same index mentioned by you looks just the other way around …

*) In part equally a speculation: fortran-lang.org might benefit from a directory-like compilation in tune of «if you happen to work in language example, you may reach (back) to Fortran e.g., with module / library f2example with typical limitations of x and y». This guide need not to be exhaustive.

Yes, one way for R to call Fortran is to use the C interface of R. For example, on Windows for the Fortran code mands.f90

subroutine mands(n,x,dm,s)
implicit none
integer         , parameter   :: dp = kind(1.0d0)
integer         , intent(in)  :: n
real(kind=dp)   , intent(in)  :: x(n)
real(kind=dp)   , intent(out) :: dm,s ! mean and standard deviation
real(kind=dp)                 :: dmold,ds
integer                       :: i
write (*,"(a,i0,/)") "in mands, n = ",n
dm = x(1)
ds = 0.d0
do i=1,n
   dmold = dm
   dm    = dm + (x(i)-dm)/i
   s     = s  + (x(i)-dmold) * (x(i)-dm)
end do
s = sqrt(s/(n-1))
return
end subroutine mands

running the R code call_fortran.r

dyn.load("mands.dll")
n  = 5
x1 = rnorm(n)
mands = .C("mands_",as.integer(length(x1)),as.double(x1),as.double(0.0),as.double(0.0))
names(mands) = c("Sample Size","Sample","Mean","Standard Deviation")
print(mands)
cat("\nchecking in R: mean =",mean(x1),"sd =",sd(x1),"\n")

gives output such as

in mands, n = 5

$`Sample Size`
[1] 5

$Sample
[1]  1.2534455 -0.9944838  0.3846756 -1.0785162 -0.1023869

$Mean
[1] -0.1074532

$`Standard Deviation`
[1] 0.9777587


checking in R: mean = -0.1074532 sd = 0.9777587

The batch file is

setlocal
if exist mands.dll del mands.dll
gfortran -shared -fPIC -o mands.dll mands.f90
C:\programs\R\R-4.0.3\bin\x64\rterm.exe --vanilla --slave < call_fortran.r

The code is modified from here. There is a tutorial Calling Fortran subroutines from R showing how to do it on Linux.

In addition to R’s .C and .Fortran interfaces, there is a .Call interface that can be used for C, and you can use iso_C_binding to call Fortran subroutines directly from this. While it is a bit more complicated, in my experience using .Call interface it was easier to avoid making copies of the function arguments, which could otherwise slow some codes substantially. Although some documentation suggests this should not really be an issue, in my experience it did matter (around 3 or 4 years ago).

More recently there is a package dotcall64 that looks like it has solve this problem, with an easier interface (?) that supports C and Fortran.

See also some further relevant discussion on stackoverflow: performance - R: Advantages of using a Fortran subroutine with .Call and C/C++ wrapper instead of .Fortran? - Stack Overflow.

2 Likes

Have you used the dotCall64 package to import Fortran subroutines into R? I am currently exploring it.

Update: I have converted all my Fortran codes that interface R with the .Fortran function to using the R package dotCall64.

The package dotCall64 not only avoids copying large objects from R to Fortran but also allows for the use of long vectors (length longer than 2^31 - 1). I find it a great tool to interface R with Fortran.

Just like Fortran, the dotCall64 package is incredibly under-marketed.

6 Likes

quantreg is an R package for quantile regression analysis. Its maintainer, Roger Koenker, invented quantile regression. It has some ratfor codes.

Many R packages contain ancient Fortran codes.

If you happen to fluently speak both Fortran .and. R, then contributing to the modernization of «ancient codes» you mention may be one of the avenues to advertise and popularize contemporary Fortran.

Just a bit of a random note, but S, the language R is based on, was originally a high level wrapper for Fortran code — all the underlying routines etc were implemented in Fortran. I think R (and maybe subsequent versions of S) later moved more to C/C++ but kept some of the Fortran.

Source: ‘Extending R’ by John Chambers

2 Likes

I use the R packages tseries and quantreg a lot. They both contain many F77-style Fortran codes. In a recent update, they produced a lot of warnings. The R and Fortran communities need to advocate Modern Fortran.

1 Like

Now there are 224 R packages using Fortran, 6 more than when the original post was created.

1 Like

Just as a headsup, the number of Fortran-R packages on CRAN is maybe not the best metric, CRAN can be hard to submit to, especially with compiled code. For example:

Which wraps a Fortran code: GitHub - TheochemUI/potlib: A repository of potential energy surface functions

That being said, I have no idea how to better find R packages with Fortran code in them, just thought I’d add this data-point.