Fortran: Fortran 2003: Intrinsische Module

Aus Wikibooks
<<< zur Fortran-Startseite
<< Fortran 2003 Bibliotheken >>
< Intrinsische Funktionen und Subroutinen OOP >


Grundlegendes[Bearbeiten]

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[Bearbeiten]

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.

Das intrinsische Modul iso_c_binding[Bearbeiten]

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[Bearbeiten]

Die bereits aus dem dem TR 15580 : 1998 (floating-point exception handling) bekannten Module

  • ieee_exceptions
  • ieee_arithmetic
  • ieee_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?[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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:
  • ieee_nearest
  • ieee_to_zero
  • ieee_up
  • ieee_down
  • ieee_other

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_nearest
  • ieee_to_zero
  • ieee_up
  • ieee_down
  • ieee_other

ieee_exceptions[Bearbeiten]

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_invalid
  • ieee_overflow
  • ieee_divide_by_zero
  • ieee_underflow
  • ieee_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[Bearbeiten]

Das ieee_features-Modul liefert einige benannte Konstanten, z.B. ieee_datatype, ieee_inf, ieee_sqrt.

Beispiel: Rundungsmodus[Bearbeiten]

IEEE-Subroutinen:

ieee_get_rounding_mode( val )
ieee_set_rounding_mode( flag )

Mögliche Wert für flag sind:

  • ieee_nearest
... default, Rundung zur nächstgelegenen Zahl (wenn das nicht eindeutig möglich ist, dann Rundung zur nächstgelegenen geraden Zahl)
  • ieee_to_zero
... Rundung in Richtung 0
  • ieee_down
... Rundung Richtung
  • ieee_up
... 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[Bearbeiten]

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_invalid
    • ieee_overflow
    • ieee_divide_by_zero
    • ieee_underflow
    • ieee_inexact
  • ieee_set_halting_mode( flag, mode ) ... setzt den Halting-Modus für ein bestimmtes Flag.
    • flag ... wie bei ieee_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. )
    
    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 (... für a)
  • 0.0 (... für b)

Ausgabe (bei Programmerstellung mit dem Sun-Express-Fortran-Compiler f95):

ieee_set_halting_mode( ieee_divide_by_zero, .false. ) ieee_set_halting_mode( ieee_divide_by_zero, .true. )
Resultat:  Inf
Programm wird fortgesetzt ...
Gleitkomma-Ausnahme


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 >