Fortran: FGSL
<< zur Fortran-Startseite | |
< BLAS und ATLAS | LAPACK > |
Allgemeines
[Bearbeiten]Bei der "GNU Scientific Library" (GSL) handelt es sich um eine in C geschriebene Bibliothek. Diese bietet Funktionen für ein weites Spektrum der Mathematik. Beispielhaft seien folgende Bereiche genannt:
- Komplexe Zahlen
- Lineare Algebra
- Polynome
- Statistik
- Fast Fourier Transformation (FFT)
- Numerische Differentiation
- Numerische Integration
- Gewöhnliche Differentialgleichungen
- IEEE Floating-Point-Arithmetik
FGSL ist ein Fortran-Interface für diese GSL-Bibliothek. FGSL selbst deckt nicht die komplette Funktionspalette von GSL ab, inzwischen sind aber auch lineare Algebra und die FFT-Funktionen Bestandteil von FGSL, auch wenn zu diesem Zweck der Einsatz der optimierten Bibliotheken LAPACK und FFTW empfohlen wird. Für einige Teilbereiche werden nicht alle in C implementierten Datentypen unterstützt.
FGSL wurde unter Verwendung einiger Fortran 2003-Sprachmerkmale erstellt. Die Einbindung von FGSL in eigene Programme setzt aus diesem Grunde einen entsprechenden Fortran-Compiler voraus. Der g95-Compiler erfüllt z.B. diese Voraussetzungen.
Derzeit ist die FGSL-Version 0.9.4 vom 31. Mai 2011 aktuell.
Beispiele
[Bearbeiten]Beispiel: Datentypen, Potenzierung und mathematische Konstanten
[Bearbeiten]C | Fortran |
---|---|
#include <stdio.h> #include <gsl/gsl_math.h> int main (void) { double a; double d = 5.0; a = gsl_pow_2 (d) * M_PI_4; printf ("Kreisflaeche = %f\n", a); return 0; } |
program bsp use fgsl implicit none real( kind = fgsl_double ) :: a real( kind = fgsl_double ) :: d = 5.0_fgsl_double a = d ** 2 * m_pi_4 write( *, * ) "Kreisflaeche = ", a end program bsp |
Kompilieren, Linken:
|
Kompilieren, Linken:
|
Der kind
-Wert fgsl_double
entspricht dem c_double
aus dem iso_c_binding
-Modul. FGSL kennt die speziellen pow
-Funktionen aus GSL nicht, da Fortran ohnehin über einen eigenen Potenzierungsoperator verfügt. Neben der m_pi_4
-Konstante ( = ) kennt FGSL noch eine ganze Reihe anderer mathematischer Konstanten, z.B.:
m_e |
... | e, Eulersche Zahl, 2,714... |
m_euler |
... | Eulersche Konstante, 0,577... |
m_pi |
... | |
m_pi_2 |
... | |
m_sqrt2 |
... |
Auch jede Menge physikalische Konstanten kennt FGSL, z.B.:
fgsl_const_mksa_speed_of_light |
... | Lichtgeschwindigkeit im Vakuum, 2.9979... x 108 m / s |
fgsl_const_mksa_molar_gas |
... | Allgemeine Gaskonstante, 8.314472 J / (K · mol) |
fgsl_const_mksa_inch |
... | 0.0254 m |
fgsl_const_mksa_torr |
... | 133.322... Pa |
fgsl_const_num_giga |
... | 109 |
Beispiel: Lösen einer quadratischen Gleichung
[Bearbeiten]Gesucht ist die Lösung der quadratischen Gleichung
C | Fortran |
---|---|
#include <stdio.h> #include <gsl/gsl_complex.h> #include <gsl/gsl_poly.h> int main (void) { double a, b, c; gsl_complex z1, z2; int i; a = 1.0; b = 12.0; c = 37.0; i = gsl_poly_complex_solve_quadratic(a, b, c, &z1, &z2); if(i == 1) { /* nur eine Lsg.*/ printf("z = (%f, %f)\n", z1.dat[0], z1.dat[1]); } else { /* 2 Lsg., reell oder komplex */ printf( "z1 = (%f, %f)\n", z1.dat[0], z1.dat[1]); printf( "z2 = (%f, %f)\n", z2.dat[0], z2.dat[1]); } return 0; /* Ausgabe: z1 = (-6.000000, -1.000000) z2 = (-6.000000, 1.000000) */ } |
program bsp use fgsl implicit none real( kind = fgsl_double ) :: a, b, c complex( fgsl_double ), dimension( 2 ) :: z integer( kind = fgsl_int ) :: i a = 1.0_fgsl_double b = 12.0_fgsl_double c = 37.0_fgsl_double i = fgsl_poly_complex_solve_quadratic( a, b, c, z(1), z(2) ) if( i == 1 ) then ! nur eine Lsg. write( *, * ) " z =", z(1) else ! 2 Lsg., reell oder komplex write( *, * ) " z1,2 =", z end if ! Ausgabe: ! z1,2 = (-6.,-1.) (-6.,1.) end program bsp |
Beispiel: Numerische Integration
[Bearbeiten]Gesucht ist die Lösung des Integrals
C | Fortran |
---|---|
#include <stdio.h> #include <math.h> #include <gsl/gsl_integration.h> double f(double x, void *params) { return(sin(x) / x); } int main () { double result, error; size_t neval; gsl_function func; func.function = &f; func.params = 0; gsl_integration_qng (&func, 0.0, 1.0, 1e-9, 1e-9, &result, &error, &neval); printf ("Ergebnis = %f\n", result); return 0; /* Ausgabe: Ergebnis = 0.946083 */ } |
module integral implicit none contains function f( x, params ) bind(c) use, intrinsic :: iso_c_binding implicit none real( kind = c_double ) :: f real( kind = c_double ), value :: x type( c_ptr ), value :: params f = sin( x ) / x end function f end module integral program bsp use fgsl use integral use, intrinsic :: iso_c_binding implicit none real( kind = fgsl_double ) :: result, error integer( kind = fgsl_size_t) :: neval integer( kind = fgsl_int) :: i type( fgsl_function ) :: func func = fgsl_function_init( f, c_null_ptr ) i = fgsl_integration_qng ( func, & 0.0_fgsl_double, & 1.0_fgsl_double, & 1e-9_fgsl_double, & 1e-9_fgsl_double, & result, error, neval ) write( *, * ) "Ergebnis =", result ! Ausgabe: ! Ergebnis = 0.946083070367183 end program bsp |
(F)GSL stellt verschiedene Möglichkeiten der numerischen Integration zur Verfügung. Hier wurde die Funktion für den QNG-Algorithmus (non-adaptive Gauss-Kronrod) gewählt.
Beispiel: IEEE-Floating-Point-Arithmetik
[Bearbeiten]Darstellung einer Fließkommazahl nach IEEE 754-Standard:
Beispielsweise wird eine 32-bit-Fließkommazahl binär so aufgegliedert:
seeeeeeeefffffffffffffffffffffff
- s ... sign, 1 bit
- e, E ... exponent, 8 bit (28 = 256; Emin = -127; Emax = 128)
- f ... fraction, 23 bit
Näheres zum IEEE 754-Standard findet sich z.B. bei IEEE 754
FGSL bietet Subroutinen, um Fießkommazahlen anschaulich entsprechend dem IEEE 754-Standard auszugeben:
fgsl_ieee_printf( x )
... Ausgabe der Zahl x im IEEE-Format aufstdout
fgsl_ieee_fprintf( str, x )
... Ausgabe der Zahl x im IEEE-Format.str
ist ein C-Zeiger (C:FILE *
, Fortran:type( c_ptr )
).
C | Fortran |
---|---|
#include <gsl/gsl_ieee_utils.h> int main() { float a = 1.5; double b = -2.6666666666666666; gsl_ieee_printf_float( &a ); gsl_ieee_printf_double( &b ); } |
program bsp use fgsl implicit none real( kind = fgsl_float ) :: a = 1.5 real( kind = fgsl_double ) :: b = -2.6666666666666666d0 call fgsl_ieee_printf( a ) call fgsl_ieee_printf( b ) end program bsp |
Ausgabe: 1.10000000000000000000000*2^0 -1.0101010101010101010101010101010101010101010101010101*2^1 |
Mit der Subroutine fgsl_ieee_env_setup()
lassen sich über die Environment-Variable GSL_IEEE_MODE
einige nützliche Attribute (Rundungsmodus etc.) festlegen.
C | Fortran |
---|---|
#include <stdio.h> #include <gsl/gsl_ieee_utils.h> int main() { float a = 1.5; int i; gsl_ieee_env_setup(); for(i = 0; i < 5; i++) { a /= 0.11; printf("%f\n", a); } } |
program bsp use fgsl implicit none real :: a = 1.5 integer :: i call fgsl_ieee_env_setup() do i = 0, 4 a = a / 0.11 write( *, * ) a end do end program bsp |
Programmaufruf: GSL_IEEE_MODE="round-to-nearest" ./a.out Ausgabe: GSL_IEEE_MODE="round-to-nearest,trap-common" 13.636364 123.966942 1126.972168 10245.201172 93138.195312 |
Programmaufruf: GSL_IEEE_MODE="round-to-nearest" ./a.out Ausgabe: GSL_IEEE_MODE="round-to-nearest,trap-common" 13.636364 123.96695 1126.9723 10245.203 93138.21 |
Programmaufruf: GSL_IEEE_MODE="round-up" ./a.out Ausgabe: GSL_IEEE_MODE="round-up,trap-common" 13.636364 123.966949 1126.972290 10245.203125 93138.210938 |
Programmaufruf: GSL_IEEE_MODE="round-up" ./a.out Ausgabe: GSL_IEEE_MODE="round-up,trap-common" 13.636364 123.96695 1126.9723 10245.203 93138.21 |
Programmaufruf: GSL_IEEE_MODE="round-down" ./a.out Ausgabe: GSL_IEEE_MODE="round-down,trap-common" 13.636363 123.966934 1126.972046 10245.200195 93138.179688 |
Programmaufruf: GSL_IEEE_MODE="round-down" ./a.out Ausgabe: GSL_IEEE_MODE="round-down,trap-common" 13.636363 123.966934 1126.972 10245.2 93138.18 |
Weblinks
[Bearbeiten]
<< zur Fortran-Startseite | |
< BLAS und ATLAS | LAPACK > |