FORTRAN: Difference between revisions

From BlueM
Jump to navigation Jump to search
Line 53: Line 53:


== Übergabe von Arrays ==
== Übergabe von Arrays ==
In Fortran ist es möglich Teile von Arrays an Funktionen zu übergeben. Wie genau das funktioniert, sollte hier erläutert werden:
In Fortran ist es möglich Teile von Arrays an Funktionen zu übergeben.  


Wird zum Beispiel von einem 3-dimensionalen Array <code>array(i, j, k)</code> der Ausdruck <code>array(1, 2, 1)</code> an eine Funktion übergeben, die einen Vektor erwartet, so bekommt diese einen <code>vektor(i)</code> der sich folgendermaßen zusammensetzt:
* <code>array(1, 2, 1)</code>
* <code>array(2, 2, 1)</code>
* <code>array(3, 2, 1)</code>
* etc.
Wenn die Funktion ein 2-dimensionales Array erwartet, erhält sie ein <code>array(i, j)</code>, usw.


Das Beispiel zeigt was genau übergeben wird:
Das Beispiel verdeutlicht dies:
<fortran>
<fortran>
!---------------------------------------------------------------
!---------------------------------------------------------------
Line 63: Line 69:
     integer i
     integer i
     integer j
     integer j


     do i = 1, ubound(arr,1)
     do i = 1, ubound(arr,1)

Revision as of 05:30, 29 October 2008

Real Werte und Vergleiche

Ein wichtiger Punkt bei der Programmierung mit Fortran ist die Behandlung der Real Werte. Insbesondere der vergleich, ob zwei Real Werte gleich sind, ist in FORTRAN nur durch eine erweiterte Syntax möglich.

Zuweisen von Werten

<fortran> real*4 a real*8 b

a = 0.123e0 !das e0 kennzeichnet den Wert als real*4 b = 0.123d0 !das d0 kennzeichnet den Wert als real*8</fortran>

Vergleich von Realzahlen

siehe Bug 367

Früher wurde im Rechenkern mit unterschiedlichen Vergleichen gerechnet (GLOBAL_NULL, GLOBAL_FASTNULL etc.)

Momentan verwendet: <fortran> R8_EPSILON = 2 * Epsilon(1.2345d0) R4_EPSILON = 2 * Epsilon(1.2654E0) ! entspricht 2**-23</fortran>

Diskussion: <fortran> real*4 a real*4 b logical isNull

isNull = (a == b) !wird so gut wie nie erfüllt

isNull = (ABS(a - b) < 1E-15) !früher im Projekt verwendet (GLOBAL_NULL)

!Alternativen (zur Diskussion) isNull = (ABS(a - b) < Epsilon(a)) !nach Rechenoperationen erwies sich Epsilon als zu ungenau bzw. genau isNull = (ABS(a / b - 1.0E0) < eps) !Relativvergleich - führte bei Tests aber zu Fehlern isNull = (ABS(a - b) < SPACING(0.0E0))</fortran>

Anmerkung

Im Code von BlueM sind ein paar nicht korrekte Anweisungen enthalten: <fortran> ! FALSCH MAX(dumdidum, R8_EPSILON) MAX(dumdidum, R4_EPSILON)</fortran> Korrekt ist aber: <fortran> ! RICHTIG MAX(dumdidum, 0.0D0) MAX(dumdidum, 0.0E0)</fortran>

Links

Übergabe von Arrays

In Fortran ist es möglich Teile von Arrays an Funktionen zu übergeben.

Wird zum Beispiel von einem 3-dimensionalen Array array(i, j, k) der Ausdruck array(1, 2, 1) an eine Funktion übergeben, die einen Vektor erwartet, so bekommt diese einen vektor(i) der sich folgendermaßen zusammensetzt:

  • array(1, 2, 1)
  • array(2, 2, 1)
  • array(3, 2, 1)
  • etc.

Wenn die Funktion ein 2-dimensionales Array erwartet, erhält sie ein array(i, j), usw.

Das Beispiel verdeutlicht dies: <fortran> !---------------------------------------------------------------

   subroutine TestArrayFortranFortran()
   integer arr(3,4)
   integer i
   integer j
   do i = 1, ubound(arr,1)
       do j = 1, ubound(arr,2)
           arr(i,j) = i + (j-1)*3
           write(*,'("Matrix (", I4,",",I4,") = ",I4)') i,j,arr(i,j)
       end do
   end do
   
   write(*,'("Aufruf mit arr(1,1) ")')
   call TestArrayFortranFortran_SUB(arr(1,1))
   write(*,'("Aufruf mit arr(2,1) ")')
   call TestArrayFortranFortran_SUB(arr(2,1))
   write(*,'("Aufruf mit arr(1,2) ")')
   call TestArrayFortranFortran_SUB(arr(1,2))
   write(*,'("Aufruf mit arr(2,2) ")')
   call TestArrayFortranFortran_SUB(arr(2,2))
   end subroutine

!---------------------------------------------------------------


!---------------------------------------------------------------

   subroutine TestArrayFortranFortran_SUB(arr)
   integer arr(2)
   integer i
   
   do i = 1, ubound(arr,1)
       write(*,'("Vektor ", I4)') arr(i)
   end do
   end subroutine

!--------------------------------------------------------------- </fortran>

Ausgabe: ConsolenAusgabe TestArray.png

Fixed Form und Free Form

Die Free Form ist der Fixed Form der übersichtlichkeitshalber vorzuziehen. Ausserdem können bei der Fixed Form Fehler entstehen, die der compiler nicht abfängt (z. B. Formeln die über den Rand gehen - in SMUSI war beispielsweise eine Stelle, wo statt mit 300 nur mit 3 multipliziert wurde.

Für die Umstellung gibts hier eine regular Expression, die alle Zeilen anzeigt die länger als 72 Zeichen sind:

Identifizieren von Problemstellen

^[^cC!][^!]^72

Bereinigen von Leerzeichen am Ende

(:b+)$