Contributor: VITUS WAGNER { From: "Victor B. Wagner"************************************************************ * ALGEBRA.PAS * * a simple matrix algebra unit * * Turbo Pascal 4.0 or higher * * Copyright (c) by Vitus Wagner,1990 * ************************************************************ } unit algebra; interface const MaxN=30;{You can increase it up to 100,not greater but each matrix variable would have size of sqr(MaxN)*sizeof(Real). It is possible to write unit for work with dinamically sized matrices, but i have no needs to do this. You can work with matrices with size less that MaxN, but while you work with this unit you must allocate memory for matrix MaxN x MaxN and leave rest of space unised} type vector=array[1..MaxN]of real; matrix=array[1..MaxN,1..MaxN]of real; sett=set of 1..MaxN; var algebrerr:boolean; function scalar(a,b:vector;n:integer):real; {Scalar multiplication of vectors a and b of n components} procedure systeq(a:matrix;b:vector;var x:vector;n:integer); { solving n line equation system A*X=B by Gauss method} { sets algebrerr to True if system cannot be solved} procedure matmult(a,b:matrix;var c:matrix;n:integer); { multiplication of two NxN matrixs A and B.Result - matrix C AxB=C} procedure matadd(a,b:matrix;var c :matrix;n:integer); { addition of two NxN matrixs A+B=C } procedure matconst(c:real;a:matrix;var b:matrix;n:integer); { multiplication matrix A on constant c cxA=B } procedure matcadd(c1:real;a1:matrix;c2:real;a2:matrix;var b:matrix;n:integer); { addition of two NxN matrixs with multiplication each of them on constant c1xA1+c2xA2=B } procedure matinv(a:matrix;var ainv:matrix;n:integer); { inversion of NxN matrix A} { sets algebrerr to True if matrix cannot be inverted} procedure matvec(a:matrix;b:vector;var c:vector;n:integer); { multiplication NxN matrix A to N-component vector B AxB=C} function det(a:matrix;n:integer):real; { determinant of NxN matrix } procedure compress(a:matrix;var b:matrix;n:integer;s:sett); { converse triangle matrix to simmetric,exclude rows and columns that is not in set s (type sett=set of 0..maxN)} function distance(a,b:vector;n:integer):real; { Calculate Euclide distantion in N-dimensioned space between A & B } Procedure Transpose(var A:Matrix;M,N:Integer); { Transpose MxN Matrix. Put result in the same place} Procedure EMatrix(var A:Matrix;N:Integer); {Fills matrix by 0 and main diagonal by 1} implementation function scalar(a,b:vector;n:integer):real; var i:integer; r:real; begin r:=0.0; for i:=1 to n do r:=r+a[i]*b[i]; scalar:=r; end; procedure systeq(a:matrix;b:vector;var x:vector;n:integer); var i,j,k:integer; max:real; begin algebrerr:=false; { Conversion matrix to triangle } for i:=1 to n do begin max:=abs(a[i,i]);k:=i; for j:=succ(i) to n do if abs(a[j,i])>max then begin max:=abs(a[j,i]);k:=j end; if max<1E-10 then begin algebrerr:=true;exit end; if k<>i then begin for j:=i to n do begin max:=a[k,j]; a[k,j]:=a[i,j]; a[i,j]:=max; end; max:=b[k]; b[k]:=b[i]; b[i]:=max; end; for j:=succ(i) to n do a[i,j]:=a[i,j]/a[i,i]; b[i]:=b[i]/a[i,i]; for j:=succ(i) to n do begin for k:=succ(i) to n do a[j,k]:=a[j,k]-a[i,k]*a[j,i]; b[j]:=b[j]-b[i]*a[j,i]; end; end; { X calculation} x[n]:=b[n]; for i:=pred(n) downto 1 do begin max:=b[i]; for j:=succ(i) to n do max:=max-a[i,j]*x[j]; x[i]:=max; end; end; procedure matmult(a,b:matrix;var c:matrix;n:integer); var i,j,k:integer;r:real; begin for i:=1 to n do for j:=1 to n do begin r:=0.0; for k:=1 to n do r:=r+a[i,k]*b[k,j]; c[i,j]:=r; end; end; procedure matadd(a,b:matrix;var c :matrix;n:integer); var i,j:integer; begin for i:=1 to n do for j:=1 to n do c[i,j]:=a[i,j]+b[i,j]; end; procedure matinv(a:matrix;var ainv:matrix;n:integer); var i,j,k:integer; e:matrix; max:real; begin algebrerr:=false; { creating single matrix } for i:=1 to n do for j:=1 to n do e[i,j]:=0.0; for i:=1 to n do e[i,i]:=1.0; { Conversion matrix to triangle } for i:=1 to n do {1} begin max:=abs(a[i,i]);k:=i; for j:=succ(i) to n do if abs(a[j,i])>max then {2} begin max:=abs(a[j,i]);k:=j {2} end; if max<1E-10 then begin algebrerr:=true;exit end; if k<>i then {2} begin for j:=i to n do {3} begin max:=a[k,j]; a[k,j]:=a[i,j]; a[i,j]:=max; {3} end; for j:=1 to n do {3} begin max:=e[k,j]; e[k,j]:=e[i,j]; e[i,j]:=max; {3} end; {2} end; for j:=succ(i) to n do a[i,j]:=a[i,j]/a[i,i]; for k:=1 to n do e[i,k]:=e[i,k]/a[i,i]; for j:=succ(i) to n do {2} begin for k:=succ(i) to n do a[j,k]:=a[j,k]-a[i,k]*a[j,i]; for k:=1 to n do e[j,k]:=e[j,k]-e[i,k]*a[j,i]; {2} end; {1} end; { ainv calculation} for k:=1 to n do {1} begin ainv[n,k]:=e[n,k]; for i:=pred(n) downto 1 do {2} begin max:=e[i,k]; for j:=succ(i) to n do max:=max-a[i,j]*ainv[j,k]; ainv[i,k]:=max; {2} end; {1} end; end; procedure matvec(a:matrix;b:vector;var c:vector;n:integer); var i,j:integer;r:real; begin for i:=1 to n do begin r:=0.0; for j:=1 to n do r:=r+a[i,j]*b[j]; c[i]:=r; end; end; function det(a:matrix;n:integer):real; var i,j,k:integer;d:real; begin for i:=1 to pred(n) do begin if abs(a[i,i])<1E-10 then begin det:=0.0;exit end; for j:=succ(i) to n do begin d:=a[j,i]/a[i,i]; for k:=i to n do a[j,k]:=a[j,k]-d*a[i,k]; end; end; d:=1.0; for i:=1 to n do d:=d*a[i,i]; det:=d; end; procedure matconst(c:real;a:matrix;var b:matrix;n:integer); var i,j:integer; begin for i:=1 to n do for j:=1 to n do b[i,j]:=c*a[i,j]; end; procedure matcadd(c1:real;a1:matrix;c2:real;a2:matrix;var b:matrix;n:integer); var i,j:integer; begin for i:=1 to n do for j:=1 to n do b[i,j]:=c1*a1[i,j]+c2*a2[i,j]; end; procedure compress(a:matrix;var b:matrix;n:integer;s:sett); var i,j,k,l:integer; begin k:=1; for i:=1 to pred(n) do if i in s then begin l:=1; b[k,k]:=a[i,i]; for j:=succ(i) to n do if j in s then begin b[k,l]:=a[i,j]; b[l,k]:=a[i,j]; inc(l); end; inc(k); end; end; function distance(a,b:vector;n:integer):real; var i:integer;r:real; begin r:=0; for i:=1 to n do r:=r+sqr(a[i]-b[i]); distance:=sqrt(r); end; Procedure Transpose(var A:Matrix;M,N:Integer); var i,j:Integer;Tmp:Real; begin For i:=1 to n do for j:=i+1 to m do begin Tmp:=A[i,j]; A[i,j]:=A[j,i]; A[J,i]:=Tmp; end; end; Procedure EMatrix(var A:Matrix;N:Integer); var I:Integer; begin FillChar(A,SizeOf(A),0); For i:=1 to n do A[i,i]:=1.0; end; end.