张金龙的博客分享 http://blog.sciencenet.cn/u/zjlcas 物种适应性、分布与进化

博文

R中调用FORTRAN的两种方式

已有 7317 次阅读 2015-5-2 22:12 |个人分类:统计分析|系统分类:科研笔记

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代码的基本流程是:

  1. 先将Fortran用gfortran编译为shared library。 在Windows下,要将fortran源代码编译为动态链接库 dll, 在Linux和Mac下编译为so文件。编译过程可通过cmd或者terminal调用gfortran(或者其他fortran编译器)实现,也可以直接在R中用system()函数调用gfortran编译。

  2. 在R中,用dyn.load()函数加载编译好的bishared library。

  3. 在R中,使用.Fortran()函数调用shared library中的代码,结果将以List的格式返回。

目标:

计算n的阶乘 n!=nk=1kn1 源代码用Fortran写成。

所需软件

  1. R(https://cran.r-project.org/)

  2. 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源代码

C   Content of file factorial.f
C   FINDING THE FACTORIAL IN FORTRAN 77
        SUBROUTINE FACTO1(N,ANSWER)        
        INTEGER N, ANSWER, I
        ANSWER = 1
        DO 100 I = 2,N
            ANSWER = ANSWER * I
 100     CONTINUE
        END

Mac和Linux下的R脚本

setwd("/Users/jinlong/Desktop/fortran_example/fortran77/")
system("R CMD SHLIB factorial.f")
dyn.load("factorial.so")
.Fortran("facto1",n=as.integer(5),answer=as.integer(1))

Windows下的R脚本

setwd("C:\Users\jlzhang\Desktop\fortran77")
system("Rcmd SHLIB factorial.f")
dyn.load("factorial.dll")
.Fortran("facto1",n=as.integer(5),answer=as.integer(1))

编译和调用Fortran90代码

Fortran90源代码

  ! Content of file factorial.f90
  ! Finding the factorial in Fortran 90

  subroutine facto2(n,answer)      
  implicit none
      integer n, answer, i
      answer = 1
      do i = 2,n
          answer = answer * i      
      end do
  end subroutine facto2

Linux下的R代码

setwd("/Users/jinlong/Desktop/fortran_example/fortran90/")
system("R CMD SHLIB factorial.f90")
dyn.load("factorial.so")
.Fortran("facto2",n=as.integer(5),answer=as.integer(1))

Windows下的R代码

setwd("C:\Users\jlzhang\Desktop\fortran90")
system("Rcmd SHLIB factorial.f90")
dyn.load("factorial.dll")
.Fortran("facto2", n=as.integer(5), answer=as.integer(1))

方法2,使用inline程序包

library(inline)
fcode <- "
      integer::i
      do i = 2, n(1)
         res(1) = res(1) * i
      end do
"
fcodefun <- cfunction(signature(n="integer", res = "integer"),
                     fcode, convention=".Fortran")
fcodefun(n = as.integer(5), res = as.integer(1))

若要将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://wap.sciencenet.cn/blog-255662-886943.html

上一篇:山寨版 Color Checker
下一篇:用git在github上托管代码

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2022-6-30 11:51

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部