Fortran是最古老的计算机语言之一,是专为数值计算设计的,在过去几十年中积累了大量代码。很多情况下,人们无需用R或Python重新实现fortran中已有的算法, 而是直接调用这些Fortran代码即可。相对其他编程语言,Fortran比较简单,而且很多编译器经过多次优化,代码的执行效率非常高,一般会超过C语言。虽然Fortran已经60岁了,但在涉及高性能计算的很多领域,如天文、物理、气象、统计等学科中仍发挥着重要作用。
Fortran语言的标准包括F77,F90,F95,F2003, F2008等。每一次版本调整, 一般是为语言增加部分新的特性。最常用的Fortran版本为F77和F90。Fortran77版本编写的代码,扩展名为.f, 以固定格式书写;而Fortran90的源代码文件,扩展名一般为f90,以相对自由的格式书写。
本文简要介绍在R中如何调用Fortran77和Fortran90代码,最后介绍在inline程序包中编译和调用fortran代码。
在R中调用Fortran代码的基本流程是:
- 先将Fortran用gfortran编译为shared library。 在Windows下,要将fortran源代码编译为动态链接库 dll, 在Linux和Mac下编译为so文件。编译过程可通过cmd或者terminal调用gfortran(或者其他fortran编译器)实现,也可以直接在R中用system()函数调用gfortran编译。
- 在R中,用dyn.load()函数加载编译好的bishared library。
- 在R中,使用.Fortran()函数调用shared library中的代码,结果将以List的格式返回。
目标:
计算n的阶乘 n!=∏nk=1k∀n≥1 源代码用Fortran写成。
所需软件
- R(https://cran.r-project.org/)
- Windows下,请安装Rtools,Rtools中包含gfortran编译器,安装时请将Rtools添加到启动 路径,参考 (https://github.com/helixcn/programing_in_r_cn/blob/master/beamer/00_software_installation.pdf )
方法1,编译代码后加载和调用Fortran代码
将Fortran代码编译为share library后,再用R的.Fortran
函数调用。
编译和调用Fortran77代码
Fortran 77源代码
1 | C Content of file factorial.f |
Mac和Linux下的R脚本
1 | setwd("/Users/jinlong/Desktop/fortran_example/fortran77/") |
Windows下的R脚本
1 | setwd("C:\Users\jlzhang\Desktop\fortran77") |
编译和调用Fortran90代码
Fortran90源代码
1 | ! Content of file factorial.f90 |
Linux下的R代码
1 | setwd("/Users/jinlong/Desktop/fortran_example/fortran90/") |
Windows下的R代码
1 | setwd("C:\Users\jlzhang\Desktop\fortran90") |
方法2,使用inline程序包
1 | library(inline) |
若要将Fortran编写到程序包中, 则需要将fortran源代码放入src文件夹中, 用.Fortran()直接调用fortran中的subroutine。R程序包的源代码中是不允许有已经编译好的可执行程序的, 因为这会造成安全风险以及可移植性的问题。注意,.Fortran()中的参数数据类型,必须与fortran代码中的类型一致,一般用 as.integer, as.double, as.character等转换成fortran代码能识别的数据类型。
labdsv程序包(https://cran.r-project.org/web/packages/labdsv/index.html )中包含了f77,可供参考。
参考资料
- https://www.r-bloggers.com/fortran-and-r-speed-things-up/
- http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2016-October/009389.html
- http://users.stat.umn.edu/~geyer/rc/
- http://www.econr.org/FortranAndR.html
- http://dirk.eddelbuettel.com/code/rcpp/Rcpp-introduction.pdf
- http://www.mjdenny.com/Rcpp_Intro.html