Fortran/Fortran overview
Part of the Fortran WikiBook
This section is a quick reference on changing from other languages to Fortran.
Common Mistakes
[edit | edit source]Listed below are some common mistakes made when using Fortran by users of C or Java:
- Perhaps the most common mistake when moving from one language to another is to try to make the new language look or act too much like the previous language in use. When switching to Fortran (for whatever reason) consider doing things the Fortran way, rather than as you would in some other language.
- In Fortran, variables need not be declared. A new variable beginning with
I
throughN
(the "in" group) is anINTEGER
. A variable beginning with some other letter is aREAL
. So, the disadvantage is that a typo could result in a new variable. The advantage is that coding is fast and easy, in that for most cases, no variables need be declared. If you want Fortran to act like declaration required languages, useIMPLICIT NONE
at the top of each program, function, and subroutine. - Arrays are indexed from 1 to N, not 0 to N−1.
- Arguments passed to functions and subroutines are passed by reference and not by value. Additionally, languages like C typically push each of their arguments onto the stack. Many (if not most) Fortran implementations build an array of argument addresses, and push the address of that array (only) onto the stack. This uses slightly more storage, but less executed code if you average more than 1 argument. The C-user error occurs when you think you know the addresses of argument references.
- Note that arguments may need to be declared, and might not, as per the rules above.
- For fixed form code, the first 6 columns have special meanings, and you can only use the first 72 columns.
- Trying to use allocation too much. When in Fortran, try to use static allocation of arrays whenever possible.
- Thinking you know how big a variable is—Here are the rules:
LOGICAL
can be any number of bytes.INTEGER
is at least as big asLOGICAL
.REAL
is at least as big asINTEGER
.DOUBLE PRECISION
is at least as big asREAL
. And finally,COMPLEX
is twice as big asREAL
. Typically, the sizes are 1, 4, 4, 8, and 8 bytes, respectively, but don't rely on that if you're writing portable code. A related mistake is thinking thatLOGICAL*4
orREAL*8
gives you data 4 or 8 bytes wide. The number following the*
is a suggestion, not a requirement.
Variables
[edit | edit source]C / C++
int i; double x[3]; double *y = NULL; y = new double[3]; delete[] y; { 1, 2, 3}; // <- Do the semantics match exactly?
Fortran (with two examples of allocation and deallocation—don't use both at once)
INTEGER i DOUBLE PRECISION x(3) DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: xx DOUBLE PRECISION, POINTER, DIMENSION(:) :: y => null() ALLOCATE(xx(3)) DEALLOCATE(xx) ALLOCATE(y(3)) ! memory allocation for pointer - similar syntax to array allocation DEALLOCATE(y) ! again similar syntax as for array allocation / deallocation (/ 1, 2, 3 /)
Caveat: Fortran's arrays are more flexible than plain C arrays. By default they are indexed from 1 not 0.
They may be declared to be indexed by different means:
REAL, DIMENSION(-2:10) :: A
means you can use A(10) as well as A(-2).
Multidimensional arrays should be declared this way:
REAL A(5,7,10)
You will have 5*7*10 elements from A(1,1,1) to A(5,7,10). Note memory is laid out in a way unique to Fortran. The element in memory following A(1,1,1) is A(2,1,1), and not A(1,1,2).
You can use parts of array this way:
REAL A(10,10) REAL B(3,3)
B(1:3,2:3)=A(4:6,7:8)
will act as
DO i=1,3 DO j=2,3 B(i,j)=A(i+3,j+5) END DO END DO
Which is the same as the archaic but shorter form
DO 1 i=1,3 DO 1 j=2,3 1 B(i,j)=A(i+3,j+5)
Functions & Subroutines
[edit | edit source]In Fortran, FUNCTION
s return a value whereas SUBROUTINE
s do not. In C/C++ this is simply the distinction between returning a value or returning void
. In Fortran, the name of the function is assigned to return a value from a function.
When calling, a subroutine is called with the CALL
keyword whereas a function is called as in C/C++. When there are no arguments, an empty parenthesis is not needed.
C/C++:
int foo(int i, int j) { ... return 42; } // then later: int x = foo(1, 2);
Fortran:
INTEGER FUNCTION foo(i, j) ... foo = 42 END C then later: k = foo(1, 2)
C/C++:
void bar(double j) { ... } void baz() { ... return; // Can return in the middle. ... return; // Optional for a function returning void. } // then later: bar(42.0); baz();
Fortran:
SUBROUTINE bar(x) ... RETURN ... END SUBROUTINE baz ... END C then later: CALL bar(42.0) CALL baz
Control structures
[edit | edit source]if → if, then, else, end if
[edit | edit source]C / C++
if (...) { ... } else if ( ... ) { ... } else { ... }
Fortran
if (...) then ... else if (...) then ... else ... end if
switch → select case, case, end select
[edit | edit source]C/C++
switch (...) { case ...: ...; break; // Without "break", control "falls through" to the next case. default: // The "default" case is optional but advisable. ...; break; // Not necessary for the last case. }
Fortran
select case(...) case (...) ... case default ... end select
Iteration
[edit | edit source]for → do, end do
[edit | edit source]C/C++
for (i = 1; i <= 10; i++) { ... }
Fortran
do i=1,10 ... end do