Integration of Fortran, C ++ with R

My task is to rewrite the R function in C ++ to speed up while loops. All R-codes were rewritten by Rcpp and Armadillo except .Fortran()

. I try to use Rinside first and it runs at a very slow speed as Dirk pointed out. (For data, you need to go through R -> C ++ -> R -> Fortran)

Since I don't want to rewrite Fortran codes in C ++ and vice versa, it's natural to speed up programs by linking C ++ directly to 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);
}

      

The problem is that I can integrate C ++ with Fortran and integrate R with C ++, but I cannot get these three things to work together!

I'm trying to compile C ++ on Linux but it just can't find RcppArmadillo.h

and namespace Rcpp

:

 error: RcppArmadillo.h: No such file or directory
 error: 'Rcpp' is not a namespace-name

      

When I sourceCpp("test.cpp")

call sourceCpp("test.cpp")

in R the console will display:

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.

      

I am also trying to combine all these things in a package

RcppArmadillo::RcppArmadillo.package.skeleton("TTTest")

      

But I don't know how to handle the package TTTest

(I believe it cannot be installed) after adding the files .cpp

and .f

in /src

and running compileAttributes

.

So, is it possible to do something like Rcpp? Or need to convert Fortran codes to C / C ++ codes?

Thank you for your help.

+17


source to share


1 answer


I would suggest that projects like this wrap your code into a package. I created a simple example of such a package, which I named mixedlang

which is available in this GitHub repo . I will describe the process of creating a package here.

I did the following steps:

  1. Set up the package structure from R with RcppArmadillo::RcppArmadillo.package.skeleton("mixedlang")

    (I used RcppArmadillo, not Rcpp as the OP was - nothing special about this Armadillo example)
  2. Added the C ++ and Fortran files described below to the folder src/

  3. In R run Rcpp::compileAttributes("mixedlang/")

    thendevtools::install("mixedlang/")

Code

I created a simple C ++ function whose sole purpose (essentially) was to call a Fortran function. The example function takes a numeric vector, multiplies each element by its index, and returns the result. Let's look at the Fortran code first:

fortranfunction.f90

This function simply takes two doubles and multiplies them, returning the result:

REAL*8 FUNCTION MULTIPLY (X, Y) 
REAL*8 X, Y
MULTIPLY = X * Y
RETURN
END

      

test_function.cpp



Now we need to call this Fortran code from our C ++ code. In doing so, we need to consider a few things:

  1. Fortran arguments are passed by reference, not by value.
  2. Since it is MULTIPLY

    defined in another file, we need to declare it in our C ++ file so that the compiler knows the arguments and return types.

    and. When declaring a Fortran function for our C ++ file, we will discard the case of the function name and add an underscore as the Fortran compiler should do this by default.

    b. We must declare this function within extern "C"

    the communication specification extern "C"

    ; C ++ compilers generally cannot use function names as unique identifiers as they allow overloading, but in order to call Fortran functions we need to do exactly what the communication specification does extern "C"

    (see, for example, this SO answer ).

#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;
}

      

Output example

After installing the package, I ran the example

mixedlang::test_function(0:9)
# [1]  0  1  4  9 16 25 36 49 64 81

      

Likely sources of original poster problems

  1. When trying to compile, initially they didn't let the compiler know where RcppArmadillo.h

    .
  2. Trying to do it with sourceCpp

    just sourceCpp

    trouble; it wasn't actually done to handle multiple files (see, for example, this answer from Dirk Eddelbuettel ), which is necessary when dealing with multiple languages.

I'm not sure what happened when they tried to flip it into a package, so I put together this example.

+22


source







All Articles