Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R & Fortran call

Tags:

r

fortran

I don't have experience with Fortran, but I am trying to run a very simple loop in that language by calling it from R via the .Fortran() function. Whenever I run the last line of the R code that is pasted below, the R gui crashes and I get no result. I am interest in bringing back the vector of real values x from Fortran into R for further analysis. g is a numeric value between 0 and 1, and n an integer, and they are both supplied by the user in R.

Any help would be much appreciated! Best,

Vincent

Fortran code saved in bar.f:

    subroutine bar(n, g, x)

      integer n
      double precision g
      double precision x(n)
      integer i
      x(1)=1
      do 100 i = 2, n
          x(i) = x(i-1) * g + 1
  100 continue

      end

Compiling the DLL in Cygwin with gfortran:

gfortran -shared -obar.dll bar.f

R code:

dyn.load("d:/bar.dll")
is.loaded("bar")
.Fortran("bar", n=as.integer(15), g=as.double(5), x=as.double(rnorm(5)))
like image 875
Vincent Avatar asked Jan 19 '11 04:01

Vincent


People also ask

What is R used for?

R offers a wide variety of statistics-related libraries and provides a favorable environment for statistical computing and design. In addition, the R programming language gets used by many quantitative analysts as a programming tool since it's useful for data importing and cleaning.

Why R is so popular?

R is the most popular language in the world of Data Science. It is heavily used in analyzing data that is both structured and unstructured. This has made R, the standard language for performing statistical operations. R allows various features that set it apart from other Data Science languages.

Is R difficult to learn?

R is known for being hard to learn. This is in large part because R is so different from many programming languages. The syntax of R, unlike languages like Python, is very difficult to read. Basic operations like selecting, naming, and renaming variables are more confusing in R than they are in other languages.

Why R is called R?

The "R" name is derived from the first letter of the names of its two developers, Ross Ihaka and Robert Gentleman, who were associated with the University of Auckland at the time.


1 Answers

When I compile your code, I can execute the call to .Fortran once. When I run it a second time, it crashes. However, I noticed that if I make the vector passed for x the same length as the integer passed for n suggests it should be, i.e:

.Fortran('bar', n = as.integer(15), g = as.double (5), x = as.double(rnorm(15)) )

I can run the function as many times as I want. So the problem may be that you are telling the Fortran routine it has a vector of length 15 to work with, but are only sending in a vector of length 5. This could be causing the Fortran routine to access memory it is not supposed to which would explain a crash.

Since it looks like you are generating all values of x in the routine anyway, you could skip generating random numbers and just send in an empty vector using R's double(n) function, where n is the length of the empty vector you want to generate:

.Fortran('bar', n = as.integer(15), g = as.double(5), x = double(15))

integer and character are useful functions that return vectors like double.

Also some friendly suggestions concerning Fortran style since you mention you are just getting started with the language:

  • It might be wise to name your files with a .f90 extension---files ending in .f are assumed by most compilers to adhere to the old "fixed-form" format which is a PITA as it was designed to be used on punch cards.

  • The Do 100 ... 100 continue statements are an style of ending loops in Fortran 77. The modern equivalent is Do .. end do.

  • With Fortran functions and subroutines, it is wise to declare the "intent" of variables passing in and out of the routine. The available intent declarations are:

    • intent(in): Signifies variables that are entering the routine only as inputs. Once inside the routine, they should be treated as parameters and the compiler will raise an error if any attempt is made to change them.

    • intent(out): Signifies variables whose values should be generated inside the routine as outputs. The compiler will issue a warning if an intent out variable is not assigned within the routine.

    • intent(inout): Signifies variables that may enter the routine carrying a certain set of values and leave the routine with different values.

    Setting intents on variables will help the compiler generate warnings and errors that may save you some bug hunting.

  • Fortran has a default behavior where any variable not declared in the header of the routine will be an integer if its name starts with i-n and real otherwise. This can cause misspelled variable names to "magically" become variables without the compiler batting an eye or telling you. Setting implicit none at the top of your routines disables this behavior and allows the compiler to notify you of mistakes that can be very hard to track down otherwise.

A version of your subroutine that takes these suggestions into account would look like the following:

subroutine bar(n, g, x)
  implicit none

  integer, intent(in):: n
  double precision, intent(in):: g
  double precision, intent(inout):: x(n)

  integer:: i

  x(1) = 1
  do i = 2, n
    x(i) = x(i - 1) * g + 1
  end do

end subroutine bar

Also, it is useful to let R compile your libraries using the SHLIB subcommand of R CMD:

R CMD SHLIB -o bar.dll bar.f90

This will compile your programs against the R libraries which contain useful functions---such as BLAS routines, stats routines and methods that can print information to the R console. See Writing R Extensions, Section 6 for more info.

Hope this helps!

like image 131
Sharpie Avatar answered Sep 24 '22 07:09

Sharpie