Fortran: Fortran 2003: Intrinsische Module
| <<< zur Fortran-Startseite | |
| << Fortran 2003 | Bibliotheken >> |
| < Intrinsische Funktionen und Subroutinen | OOP > |
Grundlegendes
Module gab es bereits mit Fortran 90/95. Neu in Fortran 2003 sind die sogenannten "intrinsischen Module". Das sind jene Module, die bereits standardmäßig von Fortran-2003-Compilern bereitgestellt werden. Werden Datenelemente oder Funktionen aus solchen intrinsischen Modulen benötigt, so ist das entsprechende Modul mittels
| use, intrinsic :: modulname |
in die jeweilige Programmeinheit einzubinden.
Der Unterschied zu konventionellen (nonintrinsischen) Modulen ist das Wörtchen intrinsic, das dem Compiler mitteilt, dass er das Modul bereits mitbringt und nicht irgendwo extern danach suchen soll. Wird nach dem use-Schlüsselwort kein entsprechendes Attribut oder das non_intrinsic-Attribut angegeben, so zeigt dies an, dass ein nonintrinsisches Modul benutzt wird.
Das intrinsische Modul iso_fortran_env
Das iso_fortran_env-Modul enthält einige Fortran-umgebungsspezifische Konstanten.
Beispiel:
| Fortran 2003 (oder neuer)-Code |
program bsp use, intrinsic :: iso_fortran_env implicit none write( *, * ) INPUT_UNIT write( *, * ) OUTPUT_UNIT write( *, * ) ERROR_UNIT write( *, * ) IOSTAT_END write( *, * ) IOSTAT_EOR write( *, * ) NUMERIC_STORAGE_SIZE write( *, * ) CHARACTER_STORAGE_SIZE write( *, * ) FILE_STORAGE_SIZE ! Ausgabe, z.B.: ! 5 ! 6 ! 0 ! -1 ! -2 ! 32 ! 8 ! 8 end program bsp |
Erläuterung:
| Konstante | Anmerkung |
|---|---|
| INPUT_UNIT | Standard-Eingabeeinheit (entspricht unit=* bei read)
|
| OUTPUT_UNIT | Standard-Ausgabeeinheit (entspricht unit=* bei write)
|
| ERROR_UNIT | Standard-Fehlerausgabeeinheit |
| IOSTAT_END | end-of-file (EOF) |
| IOSTAT_EOR | end-of-record (EOR) |
| NUMERIC_STORAGE_SIZE | Speicherplatzbedarf (in bits) |
| CHARACTER_STORAGE_SIZE | Speicherplatzbedarf (in bits) |
| FILE_STORAGE_SIZE | Speicherplatzbedarf (in bits) |
All diese Konstanten sind Skalare vom Datentyp integer.
Des Weiteren können mittels INTEGER_KINDS, REAL_KINDS, LOGICAL_KINDS und CHARACTER_KINDS die auf dem jeweiligen System verfügbaren kind-Parameter ermittelt werden.
Beispiel:
| Fortran 2003 (oder neuer)-Code |
program bsp use, intrinsic :: iso_fortran_env implicit none print *, "integer_kinds = ", INTEGER_KINDS print *, "real_kinds = ", REAL_KINDS print *, "logical_kinds = ", LOGICAL_KINDS print *, "character_kinds = ", CHARACTER_KINDS ! Ausgabe, z.B.: ! integer_kinds = 1 2 4 8 ! real_kinds = 4 8 10 16 ! logical_kinds = 1 2 4 8 ! character_kinds = 1 4 end program bsp |
Beispiel (Ausgabe eines Unicode-Zeichens, siehe auch Programming in Modern Fortran - Unicode):
| Fortran 2003 (oder neuer)-Code |
program bsp
use, intrinsic :: iso_fortran_env, only: output_unit
implicit none
integer, parameter :: iso_10646 = selected_char_kind('ISO_10646')
character(kind=iso_10646) :: c
! Das €-Zeichen
c = iso_10646_'\u20AC'
open (output_unit, encoding='UTF-8')
print *, c
! Ausgabe:
! €
end program bsp
|
Compiler-Aufruf:
gfortran.exe bsp.f08 -fbackslash
Die Compiler-Option -fbackslash übersetzt u.a. \xnn, \unnnn und \Unnnnnnnn (n sind hexadezimale Ziffern) in Unicode-Zeichen. Steht diese Option in einem Compiler nicht zur Verfügung, so gibt es auch noch andere Möglichkeiten Unicode-Zeichen zu verarbeiten. Details dazu siehe unter obenstehenden Link.
Ab Fortran 2008 können auch Compiler-Eigenschaften abgefragt werden:
| Fortran 2003 (oder neuer)-Code |
program comp use, intrinsic :: iso_fortran_env implicit none print *, compiler_version() print *, compiler_options() end program comp |
Ausgabe (Programm compiliert mit gfortran), z.B.:
GCC version 7.5.0 -mtune=generic -march=x86-64
Das intrinsische Modul iso_c_binding
Das iso_c_binding-Modul liefert die Konstanten und Unterprogramme, die für die Einbindung von C-Bibliotheken in Fortran-Programme erforderlich sind. Näheres dazu findet sich im Kapitel Fortran 2003 und C.
Die intrinsischen IEEE-Module
Die bereits aus dem dem TR 15580 : 1998 (floating-point exception handling) bekannten Module
ieee_exceptionsieee_arithmeticieee_features
wurden in Fortran 2003 in Form von intrinsischen Modulen aufgenommen. Diese Module decken den IEEE 754-1985-Standard (auch IEC 559:1989) ab.
Wovon handelt der IEEE 754-1985-Standard?
Im Bereich der Gleitkommazahlen (real, float, ...) herrschte bis in die 1980er-Jahre Anarchie. Es gab keine verbindlichen Regeln wie Gleitkommazahlen repräsentiert werden, wie gerundet wird, wie Under- und Overflows gehandhabt werden, wie mit Unendlich und NaN verfahren wird, etc. Das führte dazu, dass das gleiche Computerprogramm auf unterschiedlichen Rechnerarchitekturen und mit verschiedenen Compilern unterschiedliche Resultate liefern konnte. Um diesem Manko zu begegnen wurde in den frühen 1980er-Jahren eine Standardisierung angestrebt. Resultat war die Verabschiedung des IEEE 754-1985-Standards (IEEE Standard for Binary Floating-Point Arithmetic for microprocessor systems).
Dieser Standard regelt im Wesentlichen
- die Repräsentation von Gleitkommazahlen:
Darstellung:
| s | ... | Vorzeichen |
| m | ... | Mantisse |
| b | ... | Basis (2 für normalisierte Zahlen) |
| e | ... | Exponent |
Zahlenformate:
| single | ... | 4 Bytes |
| double | ... | 8 Bytes |
| double-extended | ... | ≥10 Bytes, optional |
- die Darstellung normalisierter und denormalisierter Zahlen:
- Normalisierte Zahlen: Gleitkommazahlen#Normalisierung
- Denormalisierte Zahlen: Bereich zwischen der kleinsten darstellbaren normalisierten Zahl und Null (Exponent hat einen reservierten Wert, führende Bit der Mantisse ist 0)
- NaN (Not a Number), ,
- Rundungen (zur nächstgelegenen darstellbaren Zahl, in Richtung Null, in Richtung oder in Richtung )
- das Verhalten verschiedener Operationen (Grundrechenarten, Wurzelberechnung, Konvertierung Gleitkommazahl → Ganzzahl, Binär-Dezimal-Konvertierung, Vergleiche mit Nan und , etc.)
- Exception-Handling (Overflow, Underflow, Division by Zero, Inexact, Invalid)
Weiterführende Weblinks:
- IEEE 754
- Kahan, W.: Why do we need a floating-point arithmetic standard?, UC Berkeley, 1981, [1]
- Kahan, W.: Lecture Notes on the Status of IEEE Standard 754 for Binary Floating-Point Arithmetic, UC Berkeley, 1996, [2]
Implementierung in Fortran 2003
Wie bereits erwähnt, besitzt Fortran 2003 intrinsische Module, mit denen der Zugriff auf bestimmte IEEE-Eigenschaften erfolgen kann. Dazu stehen eine Reihe von Funktionen, Subroutinen, Verbundtypen und Konstanten zur Verfügung. Merkmal ist, dass diese immer mit dem Präfix ieee beginnen.
ieee_arithmetic
Das aus Programmiersicht umfangreichste Modul ist sicherlich ieee_arithmetic. Dieses enthält zahlreiche Funktionen, Subroutinen und Konstanten.
Abfragefunktionen für die Unterstützung bestimmter IEEE-Elemente, z.B.:
l = ieee_support_datatype( [x] ) |
Prüft ob die IEEE-Arithmetik für einen speziellen real-Datentyps, charakterisiert durch x (Zahl oder Feld), unterstützt wird. Wird kein Argument angegeben, so wird geprüft, ob die IEEE-Arithmetik für alle real-Datentypen unterstützt wird.
|
l = ieee_support_nan( [x] ) |
Prüft, ob NaN-Werte unterstützt werden |
l = ieee_support_rounding( round_value, [x] ) |
Prüft, ob ein bestimmter IEEE-Rundungsmodus unterstützt wird. Mögliche Rundungsmodi sind:
|
Elementare Funktionen, z.B.:
l = ieee_is_finite( x ) |
Prüft, ob der Wert x endlich ist
|
r = ieee_next_after( x, y ) |
Liefert die nächste darstellbare Zahl von x in Richtung y
|
r = ieee_rint( x ) |
Rundet gemäß eingestelltem Rundungsmodus zu einer Ganzzahl und liefert diese Zahl mit dem Datentyp von x zurück.
|
Die Kind-Funktion:
r = ieee_selected_real_kind( [p, r] ) |
Liefert einen kind-Wert |
Nichtelementare Subroutinen, z.B.:
ieee_get_underflow_mode( gradual ) |
Liefert den aktuellen Underflow-Modus |
ieee_set_rounding_mode( round_value ) |
Setzt den IEEE-Rundungsmodus, mögliche Werte für round_value
|
ieee_exceptions
Das ieee_exceptions-Modul enthält zwei Funktionen, mit denen abgefragt werden kann, welche Exceptions unterstützt werden bzw. inwieweit IEEE-Halting unterstützt wird:
l = ieee_support_flag( flag, [x] ) l = ieee_support_halting( flag )
Mögliche Flags sind
ieee_invalidieee_overflowieee_divide_by_zeroieee_underflowieee_inexact
Des Weiteren sind in diesem Modul einige Subroutinen zum Setzen bzw. Abfragen diverser Flags enthalten:
ieee_get_status( status_value ) ieee_set_flag( flag, flag_value ) ieee_set_halting_mode( flag, halting ) ieee_set_status( status_value )
Bei Einbindung des ieee_arithmetic-Moduls ist auch automatisch Zugriff auf die public-Elemente des Moduls ieee_exceptions gegeben.
ieee_features
Das ieee_features-Modul liefert einige benannte Konstanten, z.B. ieee_datatype, ieee_inf, ieee_sqrt.
Beispiel: Rundungsmodus
IEEE-Subroutinen:
ieee_get_rounding_mode( val ) ieee_set_rounding_mode( flag )
Mögliche Wert für flag sind:
|
... | default, Rundung zur nächstgelegenen Zahl (wenn das nicht eindeutig möglich ist, dann Rundung zur nächstgelegenen geraden Zahl) |
|
... | Rundung in Richtung 0 |
|
... | Rundung Richtung |
|
... | Rundung Richtung |
| Fortran 2003 (oder neuer)-Code |
program bsp use, intrinsic :: ieee_arithmetic implicit none real, dimension(6) :: a = (/ -1.5, -0.5, 0.5, 1.5, 2.5, 3.5 /) ! Standard-Fortran-Rundungsfunktion write( *, * ) anint( a ) ! IEEE-Rundungsfunktion (default) write( *, * ) ieee_rint( a ) ! IEEE-Rundungsfunktion mit Flag ieee_round_type = ieee_nearest call ieee_set_rounding_mode( ieee_nearest ) write( *, * ) ieee_rint( a ) ! IEEE-Rundungsfunktion mit Flag ieee_round_type = ieee_to_zero call ieee_set_rounding_mode( ieee_to_zero ) write( *, * ) ieee_rint( a ) ! IEEE-Rundungsfunktion mit Flag ieee_round_type = ieee_down call ieee_set_rounding_mode( ieee_down ) write( *, * ) ieee_rint( a ) ! IEEE-Rundungsfunktion mit Flag ieee_round_type = ieee_up call ieee_set_rounding_mode( ieee_up ) write( *, * ) ieee_rint( a ) end program bsp |
Ausgabe:
| Standard-Fortran | IEEE-Default | ieee_nearest | ieee_to_zero | ieee_down | ieee_up |
|---|---|---|---|---|---|
-2.0 -1.0 1.0 2.0 3.0 4.0 |
-2.0 0.0 0.0 2.0 2.0 4.0 |
-2.0 0.0 0.0 2.0 2.0 4.0 |
-1.0 0.0 0.0 1.0 2.0 3.0 |
-2.0 -1.0 0.0 1.0 2.0 3.0 |
-1.0 0.0 1.0 2.0 3.0 4.0 |
Beispiel: Halting-Modus
Dieser Modus bestimmt, ob nach einer Exception das Programm angehalten oder fortgesetzt wird. Die in diesem Beispiel eingesetzten IEEE-Unterprogramme sind:
ieee_support_halting( flag )... prüft, ob auf dem System das IEEE-Halting für das angegebenen Flag überhaupt unterstützt wird (Rückgabewert:.true.). Mögliche Flags:ieee_invalidieee_overflowieee_divide_by_zeroieee_underflowieee_inexact
ieee_set_halting_mode( flag, mode )... setzt den Halting-Modus für ein bestimmtes Flag.flag... wie beiieee_support_halting( flag )mode:.true.... anhalten.false.... Programm weiter ausführen
| Fortran 2003 (oder neuer)-Code |
program main
use, intrinsic :: ieee_arithmetic
implicit none
real :: a, b
if( ieee_support_halting( ieee_divide_by_zero ) ) then
call ieee_set_halting_mode( ieee_divide_by_zero, .false. )
print *, "Gib a und b ein:"
read( *, * ) a, b
write( *, * ) "Resultat: ", a / b
write( *, * ) "Programm wird fortgesetzt ..."
else
write( *, * ) "IEEE-Halting wird nicht unterstuetzt"
end if
end program main
|
Eingabe:
10.0 0.0
Ausgabe (bei Programmerstellung mit dem Intel ifx, 2025.2):
Resultat: Infinity Programm wird fortgesetzt ...
Wird
call ieee_set_halting_mode( ieee_divide_by_zero, .true. )
gesetzt, so ist die Ausgabe eine Fehlermeldung mit Programmabbruch
forrtl: error (73): floating divide by zero Image PC Routine Line Source libc.so.6 00007FC62B457900 Unknown Unknown Unknown a.out 000000000040461B Unknown Unknown Unknown ... Abgebrochen (Speicherabzug geschrieben)
Bei Programmerstellung mit gfortran (14.2.0, 2024) ist das Verhalten identisch.
Weitere Beispiele zum Thema "Exceptions and IEEE arithmetic" sind im Fortran 2003-Working Draft J3/04-007 ab Seite 386 enthalten.
| <<< zur Fortran-Startseite | |
| << Fortran 2003 | Bibliotheken >> |
| < Intrinsische Funktionen und Subroutinen | OOP > |