Fortran

Modern Fortran has become a (mostly) domain specific language for Linear Algebra. Considering the number of problems easily expressed in that domain, Fortran may actually be quite useful.

Declarations

Fortran has a many different ways for declaring the same type. For example, an array of 10 double precision floating point values could be declared any of these ways (or through several combinations thereof):


double precision a(10)
double precision :: a(10)
real*8 :: a(10)
real(8) :: a(10)
real(8), dimension(10) :: a

Array Types

While C arrays are just pointers with an separate size parameter, Fortran gives a few different options.

SUBROUTINE example_sub( A, n, B, C )
  integer :: n
  ! A is a 1-D array of doubles of length n
  ! this is how C passes arrays
  ! this declaration is called an "Adjustable Array"
  real(8), dimension(n) :: A

  ! B is a 1-D array of doubles
  ! B is really passed as a descriptor that knows its size and memory chunk
  ! this declaration is called an "Assumed Shape Array"
  real(8), dimension(:) :: B

  ! C is a 1-D array of 10 doubles
  ! this is an "explicit shape array"
  real(8), dimension(10) :: C

  ! D is a 1-D array of doubles
  ! this is an "Automatic Array"
  ! It probably lives in the heap, and is free'ed on RETURN
  real(8), dimension(size(A)) :: D

  !...
END SUBROUTINE example_sub

Linking with C

Linking Fortran and C is relatively painless. There are only three differences to consider.

  • Name Mangling: Gfortran lowercases procedure names and appends and underscore. Procedures in modules are mangled with the module name.
  • Pass by reference: Fortran passes all parameters by reference. Thus, in C, you must past the address of you scalar variables. Arrays are still passed as a pointer to the initial element when using fortran's "Adjustable Arrays"
  • Fortran stores matrices in a different order than C, so you will need to transpose matrices when moving between languages (or just use Fortran's convention in C)

Calling Fortran from C


SUBROUTINE fort_proc(A, n)
integer :: n
real(8), dimension(n) :: A
!...
END SUBROUTINE fort_proc

Would have this C prototype:


void fort_proc_( double *A, int *n);


FUNCTION fort_proc(A, n) result(r)
integer, value:: n
real(8), dimension(n) :: A
real :: r
!...
END FUNCTION fort_proc

Would have this C prototype:


float fort_proc_( double *A, int n);

Calling C from Fortran

A common extension (gnu,intel,sun,ibm) extension to Fortran is the %VAL() intrinsic function which is used in a function call to pass the value of an argument, rather than Fortran's usual pass by reference. You can also use the `value' attribute in the interface/declaration in which case %VAL is not needed at the call site. This also works for Fortran functions.

External Links