I’ve been trying to understand the distributed block LU code written in ScaLAPACK, which is written in FORTRAN. In order to understand the algorithms properly I took a 30 min crash course in FORTRAN. In this blog post I’ll write some details about the language that are relevant to understanding the ScaLAPACK code.

Table of Contents

Learning resources

Salient FORTRAN features

Here’s a simple addition program:

program addNumbers

! This simple program adds two numbers. This is a comment.
   implicit none
   
! Type declarations
   real :: a, b, result 
   
! Executable statements 
   a = 12.0
   b = 15.0
   result = a + b
   print *, 'The total is ', result
   
end program addNumbers 

Each program begins with keyword program <prog_name> and ends with end program <prog_name>.

A statement implicit none allows the compiler to check whether all variable types are declared correctly. This statement must be there to check if types have been declared correctly.

Program structure

A full program should be kept inside a program statement. A simple ‘hello world!’ program looks like so:

program hello
  implicit none

  print*,"Hello"
  print*,"World!"
end program

Printing

Write to standard output using the print statement.

Link: https://en.wikibooks.org/wiki/Fortran/Fortran_simple_input_and_output

Printing multi-dimensional arrays can be tricky since the print statement by default outputs newlines after each printing. Here’s a link that explains how to print 2d arrays in fortran using write:

Link: https://jblevins.org/log/array-write

If you want to use format specifiers with floating point numbers, read below link:

Link: https://pages.mtu.edu/~shene/COURSES/cs201/NOTES/chap05/format.html

FORTRAN w.r.t ScaLAPACK

Subroutines and functions

I will now explain the pdgetrf routine from ScaLAPACK.

The SUBROUTINE keyword is used for defining subroutines. For example:

SUBROUTINE PDGETRF( M, N, A, IA, JA, DESCA, IPIV, INFO )

Types of arguments to subroutines are defined in the subroutine definition itself. For example, in scalapack:

*     .. Scalar Arguments ..
      INTEGER            IA, INFO, JA, M, N
*     ..
*     .. Array Arguments ..
      INTEGER            DESCA( * ), IPIV( * )
      DOUBLE PRECISION   A( * )

Unlike in C, the argument types are not declared alongwith the name and argument list.

Functions and subroutines are different in FORTRAN. The main difference lies in the fact that functions can be used in an expression and can return only one value (exactly like functions in C or Java). A subroutine on the other hand, cannot be used in expressions, but has the advantage that it can be used for returning multiple values. In the respect of returning multiple values it is somewhat similar to MATLAB functions.

A subroutine ends with the RETURN and END statement. The arguements passed to a subroutine are similar to call by reference in the case of C. If you modify any value inside the subroutine, the value will be modified in the calling function too.

In order to tell the compiler the return value of a function, you must use the name of the function in an assignment statement that will tell the compiler the value to be returned. For example:

 REAL FUNCTION AVRAGE(X,Y,Z)
     REAL X,Y,Z,SUM
     SUM = X + Y + Z
     AVRAGE = SUM /3.0
 RETURN
 END

Arrays

Arrays are used/declared in a similar manner to C. For example, to declare an array:

INTEGER            IDUM1( 1 ), IDUM2( 1 )

Array elements can be accessed using round brackets:

ICTXT = DESCA( 7 )

By default, arrays in fortran begin from index 1.

One can also specify the kind parameter in the array to tell the compiler which of its suppported kinds it should use.

Multi-dimensional arrays are referenced in their indexing the same way as C arrays (row, col) but the internal storage is of course column major. See the second link below.

Link:

  • https://stackoverflow.com/questions/838310/fortran-90-kind-parameter
  • https://www.obliquity.com/computer/fortran/array.html

Logical and comparison expressions

Logical and comparison operators are written enclosed in dots. So && in C is .AND. in fortran. Similarly, != is .NE..

Loops

Fortran has a curious way of writing loops, given that I’m coming from the C world. Loops are written using the do-continue syntax. Each loop statement in a program requires a statement label. Any label number can be used but the do and continue of a single block must have the same label.

The variable that is defined in the line of the do block is the counter variable. Its default step is 1 but you can change that as you want.

The general form is:

do label var =  expr1, expr2, expr3
  ! statements
label continue

In the above loop, var is the loop variable (this must be an integer). expr1 specifies the initial value of var, expr2 is the terminating bound, and expr3 is the increment (step).

Many Fortran 77 compilers allow do-loops to be closed by the enddo statement. The advantage of this is that the statement label can then be omitted since it is assumed that an enddo closes the nearest previous do statement. The enddo construct is widely used, but it is not a part of ANSI Fortran 77.