Home > Fortran, Linux > Using Fortran preprocessor (1)

Using Fortran preprocessor (1)

Library like BLAS or LAPACK are both very efficient and pretty often installed on linux computer.  Anyway, when you have to share a source code, you can’t rely on the fact that those libraries are set up on the host computer. So the safe solution is to find a potentially less efficient alternative, which may sound annoying for people used to BLAS and LAPACK.

Fortunately, for this kind of dilemma there is the PreProcessor, that although not part of the standard, is understood by several fortran compiler (at least gfortran, ifort and xlf).

The basic idea of preprocessing is to allow conditional compilation : depending on certain conditions, one part or another of the code will be compiled.

A first exemple

To illustrate let’s make a  sample program, that should be named “TestPreProcessor.F90”, the extension should be written with capital letters (i.e .F90 and not .f90). That’s the way most compilers automatically know that they should preprocess the code.

program TestPreProcessor
implicit none
#if TEST
 write(*,*)"Compiled with Test Flag"
#ELIF
 write(*,*)"Not Compiled with Test Flag"
#END
end program TestPreProcessor

Now we have two ways  to compile our program.

The classical way

#Compile with no flag
ifort  TestPreProcessor.F90 -o TestPreProcessor
#Test
./TestPreProcessor
#You should see something like this:
Not Compiled with Test Flag

Now the alternative way

#Compile with no flag
ifort  -DTEST TestPreProcessor.F90 -o TestPreProcessor
#Test
./TestPreProcessor
#You should see something like this:
Compiled with Test Flag

The important point is that the flag -D stand for “define”, then during preprocessing, the keyword written after -D will be considered as defined. The keys  #IF…#ELIF…#END will then be examined.”#if TEST” will stand for “is TEST defined ?” if it is true then code below the #if will compiled otherwise code above #elif will be compiled. That ‘s as simple as it seems !

Wrap up and useful example

So we ‘ve explained the basic idea with preprocessing, let apply this to a real problem. Suppose, we want to make a dot product a two vectors, and would like to offer the possibility to use either the dot_product  intrinsic or the equivalent lapack subroutine.

program Dotprod
 implicit none
 integer,parameter::n=1000000
 real(kind=4)::V1(n),V2(n),results
 real,external::sdot

 V1=1.0; V2=1.0
 !//Use BLAS if asked//
#if BLAS
 results=sdot(n,V1,1,V2,1)
#else
 results=dot_product(V1,V2)
#endif
 !//only a test//
 write(*,*)results
end program Dotprod

And the corresponding makefile could look like :

PROG=Dotprod
COMP=ifort
#--------------------------------------------------------------------
#Compilations options + Library path
#--------------------------------------------------------------------
BLAS= -DBLAS -lblas
FF= -O3 $(BLAS) # Comment or uncomment $(BLAS)
#--------------------------------------------------------------------
#Main rules
#--------------------------------------------------------------------
$(PROG): $(PROG).F90
$(COMP) $(FF) -o $(PROG) $(PROG).F90

These should  allow to use either a BLAS subroutine or a standard internal subroutine throughout your code, and ask for very few changes to the end-user who would like to compile your code.

There are several other very useful preprocessor reserved key…but we will see them in an other post 🙂

Categories: Fortran, Linux Tags: ,
  1. No comments yet.
  1. No trackbacks yet.

Leave a comment