home *** CD-ROM | disk | FTP | other *** search
- program Hilb;
- {
-
- Dieses Programm demonstriert die hohe Geschwindigkeit und
- Genauigkeit der Real-Arithmetik von Turbo Pascal.
-
- --------------------------------------------------
- Entnommen aus: Pascal Programs for Scientists and Engineers
-
- Alan R. Miller, Sybex
- n x n Inverse Hilbert-Matrix
- Lösung: 1 1 1 1 1
- --------------------------------------------------
-
- Die Matrix wird über das Gauss-Jordansche Eliminationsverfahren
- vereinfacht und simultan gelöst.
-
- 1. Setzen Sie den Compiler-Schalter O/C/Numeric processing auf "Software",
- bevor Sie das Programm compilieren und starten.
- 2. Wenn Ihr Computer mit einen numerischen Corprozessor ausgerüstet ist:
- Compilieren Sie das Programm mit O/C/Numeric processing.. "Hardware"
- ein zweites Mal und vergleichen Sie Geschwindigkeit und Genauigkeit.
- }
-
- const
- maxr = 10;
- maxc = 10;
-
- type
- {$IFOPT N+} { Wenn ein 80x87 installiert ist: }
- real = extended; { Verwendung des Formats Extended }
- {$ENDIF}
- ary = array[1..maxr] of real;
- arys = array[1..maxc] of real;
- ary2s = array[1..maxr, 1..maxc] of real;
-
- var
- y : arys;
- coef : arys;
- a, b : ary2s;
- n, m, i, j : integer;
- error : boolean;
-
- procedure gaussj
- (var b : ary2s; { Matrix mit den Quadraten der Koeffizienten }
- y : arys; { Konstanten-Vektor (zur Inversion) }
- var coef : arys; { Lösungsvektor (Koeffizienten) }
- ncol : integer; { Ordnung der Matrix (Spaltenzahl) }
- var error: boolean); { TRUE, wenn die Matrix singulär ist }
-
-
- { Gauss-Jordansche Inversion und Lösung, nach McCormick (8-FEB-81)
- B(N,N) ist die Koeffizienten-Matrix und wird invertiert
- Y(N) ist der originale Konstante Vektor
- W(N,M) besitzt konstante Vektoren und wird zur Lösung
- Determ ist die Determinante der Matrix
- Error bekommt den Wert TRUE bei singulären Matrizen
- nv ist die Anzahl der konstanten Vektoren
- }
-
- var
- w : array[1..maxc, 1..maxc] of real;
- index: array[1..maxc, 1..3] of integer;
- i, j, k, l, nv, irow, icol, n, l1 : integer;
- determ, pivot, hold, sum, t, ab, big: real;
-
- procedure swap(var a, b: real);
- var
- hold: real;
- begin
- hold := a; a := b; b := hold
- end; { swap }
-
-
- begin { gaussj }
- error := false;
- nv := 1; { Anzahl konstanter Vektoren }
- n := ncol;
- for i := 1 to n do
- begin
- w[i, 1] := y[i]; { Kopie des konstanten Vektors }
- index[i, 3] := 0
- end;
- determ := 1.0;
- for i := 1 to n do
- begin
- { Suche nach dem größten Element ("Drehpunkt") }
- big := 0.0;
- for j := 1 to n do
- if index[j, 3] <> 1 then
- for k := 1 to n do
- begin
- if index[k, 3] > 1 then
- begin
- writeln(' FEHLER: Matrix ist singulär');
- error := true;
- exit;
- end;
- if index[k, 3] < 1 then
- if abs(b[j, k]) > big then
- begin
- irow := j;
- icol := k;
- big := abs(b[j, k])
- end
- end; { for k }
- index[icol, 3] := index[icol, 3] + 1;
- index[i, 1] := irow;
- index[i, 2] := icol;
-
- { Austausch der Reihen -> größtes Element auf die Diagonale }
- if irow <> icol then
- begin
- determ := - determ;
- for l := 1 to n do
- swap(b[irow, l], b[icol, l]);
- if nv > 0 then
- for l := 1 to nv do
- swap(w[irow, l], w[icol, l])
- end; { if irow }
-
- { "Drehpunkt"-Reihe durch größtes Element dividieren }
- pivot := b[icol, icol];
- determ := determ * pivot;
- b[icol, icol] := 1.0;
- for l := 1 to n do
- b[icol, l] := b[icol, l] / pivot;
- if nv > 0 then
- for l := 1 to nv do
- w[icol, l] := w[icol, l] / pivot;
- { Reduktion der restlichen Reihen }
- for l1 := 1 to n do
- begin
- if l1 <> icol then
- begin
- t := b[l1, icol];
- b[l1, icol] := 0.0;
- for l := 1 to n do
- b[l1, l] := b[l1, l] - b[icol, l] * t;
- if nv > 0 then
- for l := 1 to nv do
- w[l1, l] := w[l1, l] - w[icol, l] * t;
- end { if l1 }
- end
- end { i loop };
-
- if error then exit;
- { Austausch der Spalten }
- for i := 1 to n do
- begin
- l := n - i + 1;
- if index[l, 1] <> index[l, 2] then
- begin
- irow := index[l, 1];
- icol := index[l, 2];
- for k := 1 to n do
- swap(b[k, irow], b[k, icol])
- end { if index }
- end { i loop };
- for k := 1 to n do
- if index[k, 3] <> 1 then
- begin
- writeln(' FEHLER: Matrix ist singulär');
- error := true;
- exit;
- end;
- for i := 1 to n do
- coef[i] := w[i, 1];
- end; { gaussj }
-
-
- procedure get_data(var a : ary2s;
- var y : arys;
- var n, m : integer);
-
- { erzeugt die Originalmatrix }
-
- var
- i, j : integer;
-
- begin
- for i := 1 to n do
- begin
- a[n,i] := 1.0/(n + i - 1);
- a[i,n] := a[n,i]
- end;
- a[n,n] := 1.0/(2*n -1);
- for i := 1 to n do
- begin
- y[i] := 0.0;
- for j := 1 to n do
- y[i] := y[i] + a[i,j]
- end;
- writeln;
- if n < 7 then
- begin
- for i:= 1 to n do
- begin
- for j:= 1 to m do
- write( a[i,j] :7:5, ' ');
- writeln( ' : ', y[i] :7:5)
- end;
- writeln
- end { if n<7 }
- end;
-
- procedure write_data;
-
- { Ausgabe der Lösungen }
-
- var
- i : integer;
-
- begin
- for i := 1 to m do
- write( coef[i] :13:9);
- writeln;
- end;
-
-
- begin { Hauptprogramm }
- a[1,1] := 1.0;
- n := 2;
- m := n;
- repeat
- get_data (a, y, n, m);
- for i := 1 to n do
- for j := 1 to n do
- b[i,j] := a[i,j] { Arbeits-Array initialisieren };
- gaussj (b, y, coef, n, error);
- if not error then write_data;
- n := n+1;
- m := n
- until n > maxr;
- end.