Fortran 77 wird abgelöst; (Teil 3)

Fortran 90: Neuer Entwurf zur Diskussion freigegeben

28.09.1990

*Karl-Heinz Rotthäuser ist wissenschaftlicher Mitarbeiter der Gesellschaft für Mathematik und Datenverarbeitung mbH in Sankt Augustin und Leiter des Arbeitskreises Fortran beim DIN.

** Zu beziehen als "DIS 1539, Ausgabe 1990 - Programming Language Fortran" bei der Beuth Verlag GmbH, Postfach 1145, 1000 Berlin 30.

Die im wissenschaftlich-technischen Bereich eingesetzte Programmiersprache Fortran hat eine Frischzellenkur erhalten. Karl-Heinz Rotthäuser* zeichnet in seinem dreiteiligen Beitrag nach, welche Veränderungen "Fortran 90" im Vergleich zu "Fortran 77" bringen wird. Gegen den bei der ISO erschienenen Entwurf "Draft International Standard Fortran"** kann noch bis Februar 1991 Einspruch erhoben werden.

Als neue, nichtausführbare Programmeinheit wurde das Modul eingeführt. Es enthält Definitionen und Spezifikationen, die in allen Programmeinheiten verwendbar sind. Sie umfassen Vereinbarungen für globale Datenobjekte, Typdeklarationen, Prozedurdefinitionen sowie Prozedur-Interface-Blöcke. Der Zweck eines Moduls ist, Vereinbarungen aufzunehmen, damit alle anderen Programmeinheiten eines ausführbaren Programmes darauf zugreifen können. Zusätzlich darf auch von solchen Programmeinheiten auf die Vereinbarungen zugegriffen werden, die in dem Modul enthalten sind.

Module ansprechen mit USE-Anweisung

Modulprozeduren wurden bereits oben angesprochen. Darüber hinaus ersetzt das Modul auch die Funktionalität von COMMON und BLOCK DATA, ohne sich auf die Speicherabbildung zu beziehen. Module werden einmal definiert und lassen sich danach mit der USE-Anweisung ansprechen.

Beispiel:

MODULE DATEN

INTEGER,

DIMENSION(100):: I

REAL,

DIMENSION(l0, 10) :: R

CHARACTER(LEN = 100)

TEXT

END MODULE DATEN

SUBROUTINE AUFRUF

USE DATEN, ONLY : R

...

X = R(J, K)

...

END SUBROUTINE AUFRUF

In diesem Beispiel werden im Modul DATEN drei unterschiedliche Datentypen definiert. Das Unterprogramm AUFRUF bezieht, sich mit der USE-Anweisung auf dieses Modul; die im Modul definierten Variablen können damit benutzt werden, sofern ihre Benutzung nicht eingeschränkt wurde.

Da im obigen Beispiel das Unterprogramm AUFRUF nur den Zugriff auf die Matrix R fordert, wurde die Zugriffsmöglichkeit von vornherein durch den Zusatz ONLY auf diese Variable beschränkt. Weitere Einschränkungen beim Zugriff auf Objekte eines Moduls über die USE-Anweisung ermöglichen die Attribute PRIVAT und PUBLIC. Auf Objekte eines Moduls, die mit dem Attribut PRIVAT versehen sind, kann außerhalb des Moduls nicht zugegriffen werden. Auf Objekte, die mit dem Attribut PUBLIC ausgezeichnet sind, können andere Programmeinheiten über die USE-Anweisung zugreifen.

Beispiel für ein Modul, das nur Datenobjekte enthält:

MODULE DATEN_PRO2

REAL A(10), B, C(20,20)

INTEGER ::I

DATE / I / 0

INTEGER,

PARAMETER, PRIVATE ::

J = 10

COMPLEX D(J, J)

END MODULE

Möglichkeiten der Benutzung:

USE DATEN_PRO2

In diesem Fall kann auf alle Datenobjekte mit Ausnahme von J zugegriffen werden, weil nur J als PRIVAT spezifiziert wurde.

USE DATEN_PRO2, ONLY : A, B, D

In diesem Beispiel kann nur auf die Variablen A, B und D zugegriffen werden.

USE DATEN_PRO2, ALPHA = > A, DELTA = > D

In diesem Fall werden die importierten Variablen A und D im Programm in ALPHA und DELTA umbenannt. Das ist zum Beispiel erforderlich, wenn bereits andere Variablen mit den Namen A und D im Programm existieren.

Datenstrukturen lassen sich ebenfalls in einem Modul definieren. Auf diese Art und Weise kann von verschiedenen Programmeinheiten auf dieselben Datenstrukturen zugegriffen werden.

Beispiel:

MODUL STRUKTUREN

TYPE PERSON

INTEGER ALTER

CHARACTER (LEN = 50)

NAME

END TYPE PERSON

END MODULE

Verarbeitung globaler Matrizen

Viele Programme müssen umfangreiche globale Matrizen verarbeiten, deren Speicherbedarf vor der Programmausführung nicht bekannt ist. Solche Matrizen deklariert man innerhalb eines Moduls. Ein einfaches Beispiel für solch ein Programm ist das folgende:

PROGRAM HAUPTPROGRAMM

CALL CONFIGURE_ARRAYS

CALL COMPUTE

END PROGRAM HAUPTPROGRAMM

MODULE WORK_ARRAYS

INTEGER N

REAL, ALLOCATABLE,

SAVE :: A(:), B(:,:), C(:,:,:)

END MODULE WORK_ARRAYS

SUBROUTINE CONFIGURE_ARRAYS

USE WORK_ARRAYS

READ (INPUT,*) N

ALLOCATE (A(N), B(N,N), C(N,N,2*N))

END SUBROUTINE CONFIGURE_ARRAYS

SUBROUTINE COMPUTE

USE WORK_ARRAYS,

ONLY: A, B, C

(Bearbeitung der Matrizen A, B und C)

END SUBROUTINE COMPUTE

Beim Aufruf des Unterprogramms CONFIGURE_ARRAYS wird den Matrizen A, B und C dynamisch Speicher zugewiesen; nach Ausführung der ALLOCATE-Anweisung läßt sich mit ihnen arbeiten. Im Beispiel werden die Matrizen in dem separaten Unterprogramm COMPUTE bearbeitet. Alle Unterprogramme, die auf diese Matrizen zugreifen wollen, brauchen nur das Modul WORK_ARRAYS zu importieren.

Schnittstellen in einem Modul zummmenfassen

Wenn man eine Bibliothek aus externen Unterprogrammen schreibt, kann man sämtliche Schnittstellen in einem einzigen Modul zusammenfassen. Damit lassen sich auch Schlüsselwörter und optionale Argumente benutzen. Außerdem können Unterprogrammaufrufe dadurch statisch auf ihre Korrektheit geprüft werden.

Beispiel:

MODULE MATHE_BIBLIOTHEK

INTERFACE COTAN

FUNCTION

R_COTAN (X)

REAL (KIND = 4),

INTEN T(IN) :: X

REAL (KIND = 4) ::

R_COTAN

FUNCTION D_COTAN

(X)

REAL(KIND = 8),

INTENT(IN) :: X

REAL (KIND = 8) ::

D_COTAN

...

END INTERFACE

END MODULE

Dieses Modul erlaubt den Aufruf der Funktion COTAN:

USE MATHE_BIBLIOTHEK

...

A = COTAN(X = ARCUS)

...

Beispiel für das CASE-Konstrukt (ganzzahlige Funktion Signum):

INTEGER

FUNCTION SIGNUM (N)

SELECT CASE (N)

CASE ( :-1)

SIGNUM = -1

CASE (0)

SIGNUM = 0

CASE (1:)

SIGNUM = 1

END SELECT

END FUNCTION SIGNUM

Bei der Ausführung der SELECT-CASE-Anweisung wird der Ausdruck in Klammern (hier N) berechnet. Das Ergebnis ist der CASE-Index, der höchstens mit einem der Selektoren einer CASE-Anweisung übereinstimmen darf. Für den Fall einer Bereichsangabe a:b muß der CASE-Index in dem Bereich a < = CASE-Index < = b liegen. Für a: gilt a < = CASE-Index, für :b gilt CASE-Index < = b. Wenn kein Selektor mit dem CASE-Index übereinstimmt und der Selektor DEFAULT angegeben ist, werden die dazugehörigen Anweisungen ausgeführt. Fehlt die Angabe DEFAULT, wird mit der Folge-Anweisung fortgefahren.

Eine Reihe neuer DO-Konstrukte

Beispiel für Laufanweisung:

SCHLEIFE: DO 100, I = 1, 10, 1

oder:

SCHLEIFE: DO 200, WHILE (SUM < SMAX)

SCHLEIFE ist ein frei wählbarer Name für eine DO-Schleife, der auch wegfallen kann. Wenn die Laufanweisung einen Namen hat, ist das DO-Konstrukt mit einer END-DO-Anweisung abzuschließen, die denselben Namen besitzt. Im zweiten Beispiel wird die Schleife solange durchlaufen, bis der Klammerausdruck den Wert FALSE annimmt.

Beispiel:

N = 0

SCHLEIFE : DO 100, I = 1, 10, 1

N = N + 1

100 END DO SCHLEIFE

Schleifenname, Marke (Label), nachfolgendes Komma und Schleifensteuerung können entfallen. Um in einem solchen Fall die Schleife abzubrechen, stehen zwei weitere Anweisungen zur Verfügung:

EXIT Schleifenname und

CYCLE Schleifenname.

Der Schleifenname (im Beispiel: SCHLEIFE) kann, entfallen.

Die EXIT-Anweisung führt zur Beendigung der DO-Schleife. Die Ausführung der CYCLE-Anweisung, die zu einer DO-Schleife gehört, verursacht, daß der Iterationszähler der Schleife (falls vorhanden) um eins und die Laufvariable um die Schrittweite vermindert wird. Als Iterationszähler wird der Ausdruck MAX(INT((m(2) - m1 + M(3)) / M(3)), 0) bezeichnet, weil er die Anzahl der noch auszuführenden Schleifendurchläufe angibt. Dabei bedeuten: m(1) Anfangswert, M(2) Endwert und m(3) Schrittweite der DO-Schleife. Danach wird mit dem Beginn der Schleife fortgefahren. Die CYCLE-Anweisung hat denselben Effekt wie ein Sprung an das Ende einer Schleife und dient somit in erster Linie der Verbesserung des Programmierstils.

Beispiel:

SUM = 0

DO , WHILE(SUM < SMAX)

READ (*,IOSTAT = IFEHLER) P, Q

IF (IFEHLER / = 0) EXIT CALL CALCULATE (P, Q, R)

SUM = SUM + R

END DO

In diesem Beispiel wird die Schleife so lange ausgeführt, wie der Inhalt von SUM kleiner als der von SMAX ist. Wenn die Variable IFEHLER durch die READ-Anweisung nicht auf Null gesetzt wird, bricht die Schleife vorzeitig ab.

In Fortran 90 gibt es zwei Quellformen: eine formatgebundene, die der bisherigen entspricht, und eine neue, die formatfrei ist. In der formatfreien Quellform enthält jede Zeile (Satz) zwischen Null und 132 Zeichen. Das Ausrufezeichen (!) leitet einen Kommentar ein, außer wenn es innerhalb einer Zeichenkette auftritt. Der Kommentar reicht bis zum Ende der Quellzeile. Mit dem Semikolon (;) trennt man die Anweisungen, wenn sie innerhalb einer Quellzeile auftreten. Innerhalb einer Zeichenkette hat das Semikolon keine Wirkung.

Zur Bedeutung des Et-Zeichens

Das Et-Zeichen (&) als letztes nicht-leeres Zeichen in einer Zeile außerhalb eines Kommentares kündigt an, daß die Anweisung in der nächsten Zeile fortgesetzt wird. Ein Kommentar kann nicht fortgesetzt werden. Ein Et-Zeichen innerhalb eines Kommentares hat keine Wirkung. Wenn das erste Zeichen in der nächsten Zeile, das verschieden vom Zwischenraum (Leer) ist, ebenfalls ein Et-Zeichen ist, wird die Anweisung mit dem darauf folgenden Zeichen fortgesetzt; andernfalls wird es mit dem Zeichen in Position 1 fortgesetzt. Bei Fortsetzung einer Anweisung mit dem Et-Zeichen gehört das Zeichen selbst nicht zur Anweisung.

Wenn eine Zeichenkette, die kein Kommentar ist, fortgesetzt wird, kann dem Et-Zeichen für Fortsetzung kein Kommentar folgen und der fortgesetzte Teil muß mit dem Et-Zeichen beginnen. Falls die Fortsetzung nicht innerhalb einer Zeichenkette stattfindet, darf dem Zeichen "&" ein Kommentar folgen.

Das Zeichen Zwischenraum ist signifikant und läßt sich deshalb nicht mehr an beliebigen Stellen einstreuen. Es ist dafür zu verwenden, Namen, Konstanten und Marken (Labels) voneinander zu trennen; so muß in der Anweisung " 10 DO I = 1,5" nach "10" und "DO" mindestens ein Zwischenraum vorhanden sein. Mit einer INCLUDE-Zeile kann man Quelltext in ein Fortran-90-Programm einfügen.

Die wichtigsten Erweiterungen im Bereich Input/Output:

- ein neuer Formatdeskriptor ES für Gleitkommazahlen,

- zeichenweise Ein- und Ausgabe in einen Satz,

- neue Spezifikationen in der OPEN- und INQUIRE-Anweisung,

- Ein- und Ausgabe mit NAMELIST.

Mit der NAMELIST-Anweisung gibt man einer Gruppe von Variablen einen Namen. Bei der Ein- und Ausgabe kann man sich danach auf diese Gruppe beziehen, indem nur noch der vereinbarte Gruppenname angegeben wird.

Beispiel:

NAMELIST /LISTE1/ A, B, C,/ LISTE2/ E, F

Das Komma hinter C darf wegfallen.

Bei den Ein- und Ausgabeanweisungen bezieht man sich auf den Gruppennamen:

READ

(UNIT = 6,

NML = LISTE1)

Die Zeichen im NAMELIST-Satz bestehen aus den Variablennamen, einem Gleichheitszeichen (=), gefolgt von den dazugehörigen Werten mit dazwischenliegenden Trennzeichen.

Zusammensetzung der NAMELIST-Gruppe

Die Eingabe für eine NAMELIST-Gruppe setzt sich aus folgenden Angaben zusammen: dem Et-Zeichen (&), unmittelbar gefolgt von jenem Gruppennamen, der auch in der Eingabeanweisung steht. Danach folgen die Variablennamen mit dem Gleichheitszeichen und den dazugehörigen Werten, wobei mehrere Angaben durch Trennzeichen separiert werden. Der Schrägstrich (/) beendet die Eingabeanweisung: &LISTE1 C = 17.32, B = 56.22/

In diesem Eingabebeispiel werden nur die Variablen B und C der LISTE1 verändert, der Wert der Variablen A hingegen bleibt derselbe. Die Inhalte der Variablen einer Gruppe dürfen in beliebiger Reihenfolge eingegeben werden.

Veraltete Merkmale wurden beibehalten

Damit Fortran-77-Programme auch unter Fortran 90 ablaufen können, wurden veraltete Sprachkonstrukte noch beibehalten, aber als "obsolescent" gekennzeichnet, weil sie voraussichtlich nicht in die nächste Norm (Fortran 9x) übernommen werden. Dazu zählen:

- arithmetisches IF,

- REAL- und DOUBLE-PRECISION-Variable als Schleifenvariable,

- mehrere DO-Schleifen, die von einer gemeinsamen Anweisung beendet werden,

- Sprung auf eine END-IF-Anweisung von außerhalb,

- Rücksprung aus einer Prozedur direkt auf eine Marke (RETURN I),

- PAUSE-Anweisung,

- ASSIGN und "assigned" GO TO,

- Zuweisung einer Marke einer FORMAT-Anweisung an eine ganzzahlige Variable mit der ASSIGN-Anweisung.

Alle übrigen Sprachmerkmale sind vollwertige Bestandteile von Fortran 90.

Einspruchsfrist läuft bis Februar 1991

Die lang erwartete Revision der Norm Fortran 77 (ISO 1539-1980 ist identisch mit ANSI X3.9-1978, mit der auch DIN 66027 übereinstimmt) ist nun durch die Registrierung und Veröffentlichung als Entwurf "Draft International Standar Fortran" bei ISO erschienen. Ein erster Vorschlag, der 1988 zur Abstimmung vorgelegt wurde, fand nicht die erforderlich Zustimmung, da alle wicht Industrieländer den damaligen Vorschlag ablehnten. Die dabei abgegebenen Kommentare wurden sorgfältig geprüft und der gesamte Entwurf nochmals überarbeitet, wobei die meisten berechtigten Einsprüche und Verbesserungsvorschläge Berücksichtigung fanden.

Mit der jetzigen Abstimmung ist auch die Möglichkeit verbunden, Kommentare abzugeben. Die Einspruchsfrist für Kommentare bei der ISO läuft vom 2. August 1990 bis 2. Februar 1991. Grundlage für eine Stellungnahme ist der "Draft International Standard Fortran".

Es wird erwartet, daß neue Entwurf mit geringfügigen Änderungen als nächste Fortran-Norm verabschiedet wird, so daß Fortran 90 als neuer "International Standard" 1991 verfügbar sein dürfte. Die dazugehörigen neuen Compiler werden frühestens in zwei Jahre ausgeliefert.

Die meisten Hersteller werden Fortran 90 wegen seines gewaltigen Umfanges stufenweise implementieren. Dabei können die Spracherweiterungen für Matrizen sicherlich von Anfang an bezogen werden. Dagegen werden die Sprachelemente, die im Zusammenhang mit Moduln stehen, wegen ihrer Komplexität zuletzt realisiert. In den USA hat deshalb die alte Fortran-77-Norm für eine Übergangszeit parallel zur neuen Norm Gültigkeit. +