Daj*_* Xu 19 c++ fortran r armadillo rcpp
我的任务是用C++重写R函数来加速while循环.所有R代码都在Rcpp和Armadillo的帮助下重写,除了.Fortran().我尝试首先使用Rinside,它的工作速度非常慢,正如Dirk所指出的那样.(数据通过R - > C++ - > R - > Fortran是昂贵的)
由于我不想用C++重写Fortran代码,反之亦然,通过将C++直接链接到Fortran来加速程序看起来很自然:R - > C++ - > Fortran.
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
extern "C"{
List f_(int *n,NumericMatrix a, NumericVector c, double* eps);
}
Run Code Online (Sandbox Code Playgroud)
问题是我可以将C++与Fortran集成并将R与C++集成,但我不能让这三个东西一起工作!
我尝试在Linux中编译C++,但它无法找到RcppArmadillo.h并且namespace Rcpp:
error: RcppArmadillo.h: No such file or directory
error: 'Rcpp' is not a namespace-name
Run Code Online (Sandbox Code Playgroud)
当我sourceCpp("test.cpp")直接打电话给R时,控制台会显示:
test.o:test.cpp:(.text+0x20b2): undefined reference to `f_'
collect2: ld returned 1 exit status
Error in sourceCpp("test.cpp") : Error occurred building shared library.
Run Code Online (Sandbox Code Playgroud)
我也尝试将所有这些东西组合在一起
RcppArmadillo::RcppArmadillo.package.skeleton("TTTest")
Run Code Online (Sandbox Code Playgroud)
但是我TTTest添加了.cpp和.f文件/src并运行后,我不知道如何处理包(我相信它无法安装)compileAttributes.
那么,是否有可能像Rcpp那样做我想象的事情?或者有必要将Fortran代码转换为C/C++代码?
谢谢你的帮助.
duc*_*ayr 25
我建议这些项目将代码转换为包.我创建了一个这样的包的简单示例,我mixedlang在此GitHub仓库中提供了该包.我将在这里描述创建包的过程.
我采取的步骤如下:
RcppArmadillo::RcppArmadillo.package.skeleton("mixedlang")(我只使用RcppArmadillo而不是Rcpp,因为OP是 - 这个例子没有特定的Armadillo)src/文件夹中Rcpp::compileAttributes("mixedlang/")然后运行devtools::install("mixedlang/")我创建了一个简单的C++函数,其唯一目的(本质上)是调用Fortran函数.示例函数接受一个数字向量,将每个元素乘以其索引,并返回结果.首先让我们看一下Fortran代码:
这个函数只需要两个双精度并将它们相乘,返回结果:
REAL*8 FUNCTION MULTIPLY (X, Y)
REAL*8 X, Y
MULTIPLY = X * Y
RETURN
END
Run Code Online (Sandbox Code Playgroud)
现在我们需要从C++代码中调用这个Fortran代码.这样做时,我们需要考虑以下几点:
由于MULTIPLY在另一个文件中定义,我们需要在C++文件中声明它,以便编译器知道参数和返回类型.
一个.在为我们的C++文件声明Fortran函数时,我们将删除函数名称的情况并附加下划线,因为Fortran编译器默认情况下应该这样做.
湾 我们必须在extern "C"链接规范中声明该函数; C++编译器通常不能将函数名称用作唯一标识符,因为它允许重载,但是为了调用Fortran函数,我们需要它extern "C"完成链接规范完成的操作(例如,参见此SO答案).
#include "RcppArmadillo.h"
// [[Rcpp::depends(RcppArmadillo)]]
// First we'll declare the MULTIPLY Fortran function
// as multiply_ in an extern "C" linkage specification
// making sure to have the arguments passed as pointers.
extern "C" {
double multiply_(double *x, double *y);
}
// Now our C++ function
// [[Rcpp::export]]
Rcpp::NumericVector test_function(Rcpp::NumericVector x) {
// Get the size of the vector
int n = x.size();
// Create a new vector for our result
Rcpp::NumericVector result(n);
for ( int i = 0; i < n; ++i ) {
// And for each element of the vector,
// store as doubles the element and the index
double starting_value = x[i], multiplier = (double)i;
// Now we can call the Fortran function,
// being sure to pass the address of the variables
result[i] = multiply_(&starting_value, &multiplier);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
安装包后,我跑了一个例子
mixedlang::test_function(0:9)
# [1] 0 1 4 9 16 25 36 49 64 81
Run Code Online (Sandbox Code Playgroud)
RcppArmadillo.h.sourceCpp只是在寻找麻烦; 它并没有真正做出处理多个文件(例如,见这个答案由德克Eddelbuettel),多语言处理时是必要的.我不确定当他们试图将它卷成一个包时会发生什么,这就是我制作这个例子的原因.