| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- program HilbDemo87;
- {
- TURBO-87 DEMONSTRATION PROGRAM Version 1.00A
- This program demonstrates the increased speed and precision
- of the TURBO-87 compiler:
- --------------------------------------------------
- From: Pascal Programs for Scientists and Engineers
- Alan R. Miller, Sybex
- n x n inverse hilbert matrix
- solution is 1 1 1 1 1
- double precision version
- --------------------------------------------------
- The program performs simultaneous solution by Gauss-Jordan
- elimination.
- INSTRUCTIONS
- 1. Compile the program using the TURBO-87.COM compiler.
- 2. Type Ctrl-C to interrupt the program.
- }
- CONST
- maxr = 10;
- maxc = 10;
- TYPE
- 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; (* square matrix of coefficients *)
- y : arys; (* constant vector *)
- VAR coef : arys; (* solution vector *)
- ncol : integer; (* order of matrix *)
- VAR error: boolean); (* true if matrix singular *)
- (* Gauss Jordan matrix inversion and solution *)
- (* Adapted from McCormick *)
- (* Feb 8, 81 *)
- (* B(N,N) coefficient matrix, becomes inverse *)
- (* Y(N) original constant vector *)
- (* W(N,M) constant vector(s) become solution vector *)
- (* DETERM is the determinant *)
- (* ERROR = 1 if singular *)
- (* INDEX(N,3) *)
- (* NV is number of constant vectors *)
- LABEL
- 99,98;
- 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 (* swap *)
- hold := a;
- a := b;
- b := hold
- END (* procedure swap *);
- BEGIN (* Gauss-Jordan main program *)
- error := false;
- nv := 1 (* single constant vector *);
- n := ncol;
- FOR i := 1 TO n DO
- BEGIN
- w[i, 1] := y[i] (* copy constant vector *);
- index[i, 3] := 0
- END;
- determ := 1.0;
- FOR i := 1 TO n DO
- BEGIN
- (* search for largest element *)
- big := 0.0;
- FOR j := 1 TO n DO
- BEGIN
- IF index[j, 3] <> 1 THEN
- BEGIN
- FOR k := 1 TO n DO
- BEGIN
- IF index[k, 3] > 1 THEN
- BEGIN
- writeln(' ERROR: matrix singular');
- error := true;
- GOTO 98 (* abort *)
- 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 (* k loop *)
- END
- END (* j loop *);
- index[icol, 3] := index[icol, 3] + 1;
- index[i, 1] := irow;
- index[i, 2] := icol;
- (* interchange rows to put pivot on diagonal *)
- 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 <> icol *)
- (* divide pivot row by pivot column *)
- 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;
- (* reduce nonpivot rows *)
- 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 <> icol *)
- END
- END (* i loop *);
- 98:
- IF error THEN GOTO 99;
- (* interchange columns *)
- 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(' ERROR: matrix singular');
- error := true;
- GOTO 99 (* abort *)
- END;
- FOR i := 1 TO n DO
- coef[i] := w[i, 1];
- 99:
- END (* procedure gaussj *);
- PROCEDURE get_data(VAR a : ary2s;
- VAR y : arys;
- VAR n, m : integer);
- (* setup n-by-n hilbert matrix *)
- 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 get_data *);
- PROCEDURE write_data;
- (* print out the answers *)
- VAR
- i : integer;
- BEGIN
- FOR i := 1 TO m DO
- write( coef[i] :13:9);
- writeln;
- END (* write_data *);
- BEGIN (* main program *)
- 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] (* setup work array *);
- gaussj (b, y, coef, n, error);
- IF not error THEN write_data;
- n := n+1;
- m := n
- UNTIL n > maxr;
- END.
|