MatLib.mod.m2pp
2181 lines (1979 with data), 73.7 kB
IMPLEMENTATION MODULE MatLib;
(*========================================================================*)
(* HINWEIS : Bitte nur die Datei MatLib.mod.m2pp editieren *)
(*========================================================================*)
(* Es sind 2 Versionen enthalten die mit *)
(* *)
(* m2pp -D __{Parameter}__ < MatLib.mod.m2pp > MatLib.mod *)
(* *)
(* mit Parameter = {XDS|GM2} erzeugt werden koennen. *)
(* *)
(* XDS : Der Export von Objekten aus lokalen Modulen wird mit *)
(* "IMPORT" angezeigt - das scheint nicht ganz "regelkonform" *)
(* GM2 : Normales "EXPORT" wird genutzt (ELSE-Fall). *)
(* *)
(* ansonsten gibt es keine Aenderungen am Quellcode *)
(*------------------------------------------------------------------------*)
(* Bibiliotek einiger Matrix- und Vektoroperationen. *)
(* Module provides some matrix and vector operations. *)
(*------------------------------------------------------------------------*)
(* Letzte Bearbeitung *)
(* *)
(* 09.11.95, MRi: Diverse Korrekturen *)
(* 12.02.15, MRi: Prozedur InsertMat eingefuegt *)
(* 05.05.15, MRi: Prozedur InitLRArray eingefuegt *)
(* 13.10.15, MRi: Ersetzen von LFLOAT(#) durch VAL(LONGREAL,#) *)
(* 23.01.16, MRi: Ersetzen von IMPORT Random durch IMPORT RandomLib *)
(* 23.01.16, MRi: Umstellen von InitMat und ZufallMat auf "OPEN ARRAY" *)
(* 03.02.16, MRi: Umstellen von Stuerz "OPEN ARRAY" *)
(* Umstellen von MatVekProd auf "OPEN ARRY", Erweiterung *)
(* auf transponierten Fall. *)
(* 15.04.16, MRi: Kommentarfelder im Definitionsteil angepasst. Prozedur *)
(* CSkalProd reaktiviert auf Basis von Aufrufen von *)
(* CMathLib Funktionen, SkalProd auf offene Felder umgest. *)
(* In der Prozedur InitLRArray den Parameter y eingefuegt *)
(* in InitMat dim durch m,n ersetzt, groessenabfragen *)
(* korrigiert und Aufrufe von InitLRArray eingefuegt *)
(* NormVek ueberarbeitet *)
(* 17.04.16, MRi: Prozedur erneut aus LibDBlas uebernommen, ebenso *)
(* SumVek & AbsSumVek (passen hier doch besser hin). *)
(* 19.04.16, MRi: Prozedur ZufallVec eingefuegt. *)
(* 21.04.16, MRi: Prozedur CopyMat eingefuegt. *)
(* 25.04.16, MRi: Prozedur SvVekProd eingefuegt *)
(* 02.05.16, MRi: Prozedur NormMat auf offene Felder umgestellt, ruft nun *)
(* nur noch NormVek auf. In NormVek idamax eingefuegt *)
(* 18.07.16, MRi: Prozeduren SumVekUR und AbsSumVekUR eingefuegt *)
(* 27.12.16, MRi: Prozeduren MatNormL1 eingefuegt *)
(* 11.01.17, MRi: Prozeduren Itab0 und IJtab0 eingefuegt, SvToMat auf *)
(* offene Felder umgestellt und Steuerparameter sauber *)
(* definiert (war etwas "chaotisch" ;-) *)
(* 26.05.17, MRi: Ersetzen der Routinen SvSvProd, MatSvProd, SvMatProd *)
(* durch SvSvProdNN, MatSvProdNN,MatSvProdTN,SvMatProdNN *)
(* und SvMatProdNT. Prozedure InitIndex veraendert, *)
(* SvToMat auf offene Felder umgestellt und Parameter *)
(* "steuer" logischer Aufgebaut. *)
(* 26.05.17, MRi: Erfuegen der Prozeduren MatMatProd{NN|NT|TN|TT}, *)
(* Transpose, MatMatProdNNl4 (erstellt 04.01.16) *)
(* 23.07.17, MRi: Erstellen der ersten Version von TransposeMN *)
(* 24.09.17, MRi: Umbenennen von LONGCOMPLEX in LONGCMPLX sowie *)
(* CVEKTOR in CRVEKTOR und CMATRIX in CRMATRIX *)
(* 26.09.17, MRi: CStuerz auf ISO Komplex umgestelle, InitLCArray und *)
(* InitCMat hinzugefuegt *)
(* 29.09.17, MRi: Umstellung auf ISO COMPLEX *)
(* 25.10.17, MRi: Einfuegen von TransposeMN aus Testumgebung *)
(* 07.12.17, MRi: Einfuegen von StuerzMN,NeumaierSum & NeumaierProdSum *)
(* aus Testumgebung *)
(* 30.05.18, MRi: Einfuegen von TriInfNorm *)
(* 10.06.18, MRi: ZufallMat um den nicht-quadratischen Fall ergaenzt *)
(* 12.09.18, MRi: CMatVekProd erweitert und an MatVekProd angepasst *)
(* 21.09.18, MRi: CStuerzMN eingefuegt *)
(* 28.09.18, MRi: MatNormL1 auf "Rechtecksfall" erweitert *)
(* 29.09.18, MRi: In StuerzMN & CStuerzMN das Nullsetzen der Restmatrix *)
(* ueberarbeitet, in CStuerzMN den Parameter IfConj *)
(* eingefuegt *)
(*------------------------------------------------------------------------*)
(* Offene Punkte *)
(* *)
(* - Nachsehen ob InitMat nicht "gelitten" hat *)
(* - Komplexe Typen auf ISO M2 umstellen *)
(* - SvToMat auf offene Felder umstellen, Code für ABS(steuer) = 1 *)
(* nutzen (ist auskommentiert) *)
(* - In SvVekProd erste Schleife eventuell ausrollen *)
(* - SvToMat pruefen und ggf. korrigieren *)
(* - CMatMatProd nochmal kurz pruefen *)
(*------------------------------------------------------------------------*)
(* Testroutinen *)
(* *)
(* - TestMatLib : (NormMat,NormVek,InitMat) *)
(* - TstMatSV : (SvVekProdNN, MatSvProd{NN|TN}, SvMatProd{NN|NT}) *)
(* - TstMaTran2 : TransposeMN *)
(* - TstRealMaMult : Matrix-Matrix Muliplitation (dgemm, Fortran dgemm) & *)
(* - TstCmplxMaMul : Matrix-Matrix Muliplitation (zgemm, CMatMatProd) *)
(* - TstMVP : Matrix-Vektor Muliplitation (dgemv, MatVekProd) *)
(* - TstMaTran2 : TransposeMN *)
(*------------------------------------------------------------------------*)
(* Implementation : Michael Riedl *)
(* Licence : GNU Lesser General Public License (LGPL) *)
(*------------------------------------------------------------------------*)
(* $Id: MatLib.mod.m2pp,v 1.17 2019/02/01 22:24:03 mriedl Exp mriedl $ *)
FROM SYSTEM IMPORT TSIZE,ADR;
FROM Storage IMPORT ALLOCATE,DEALLOCATE;
FROM Deklera IMPORT VEKTOR,MATRIX,SUPERVEKTOR,PMATRIX,MaxDim,
CVEKTOR,CMATRIX;
FROM Errors IMPORT Fehlerflag,Fehler;
IMPORT Errors;
FROM LongMath IMPORT sqrt;
IMPORT LongComplexMath;
FROM LMathLib IMPORT MaxCard;
FROM RandomLib IMPORT Zufall;
FROM LibDBlas IMPORT idamax,dscal;
IMPORT LibDBlasM2;
FROM DynMat IMPORT AllocMat,DeAllocMat;
CONST zero = CMPLX(0.0,0.0);
(* IF NOT DEFINED(__BAxx__) THEN *) (* NEW __BAxx__+ *) (* END *)
<* IF DEFINED(__BLAS__) THEN *>
FROM LibDBlas IMPORT dcopy,ddot,daxpy;
<* END *>
PROCEDURE InitIndex(VAR Index : ARRAY OF CARDINAL;
high : CARDINAL);
VAR i,ii : CARDINAL;
BEGIN
ii:=0; FOR i:=0 TO high-1 DO Index[i]:=ii; INC(ii,i+1); END;
END InitIndex;
MODULE Tabelle; (* Kapselt Index *)
IMPORT MaxDim;
<* IF (__XDS__) THEN *>
IMPORT Itab,IJtab,InvIJtab,Itab0,IJtab0; (* EXPORT *)
<* ELSE *>
EXPORT Itab,IJtab,InvIJtab,Itab0,IJtab0;
<* END *>
VAR Index : ARRAY [0..MaxDim] OF CARDINAL;
VAR Index0 : ARRAY [0..MaxDim-1] OF CARDINAL;
PROCEDURE Itab(i : CARDINAL) : CARDINAL; BEGIN RETURN Index[i]; END Itab;
PROCEDURE IJtab(i,j : CARDINAL) : CARDINAL;
BEGIN
IF (i > j) THEN RETURN Index[i] + j; ELSE RETURN Index[j] + i; END;
END IJtab;
PROCEDURE InvIJtab( ij : CARDINAL;
VAR i,j : CARDINAL);
VAR k,l,m : CARDINAL;
BEGIN
k:=1; l:=MaxDim+1;
REPEAT
m := (k + l) DIV 2;
IF (ij < Index[m]) THEN l:=m ELSE k:=m+1 END;
UNTIL (l <= k);
i:=l-1; IF (ij = Index[i]) THEN DEC(i); END;
j := ij - Index[i];
END InvIJtab;
PROCEDURE Itab0(i : CARDINAL) : CARDINAL;
BEGIN
IF (i < MaxDim) THEN
RETURN Index0[i];
ELSE
RETURN (i*(i+1)) DIV 2;
END;
END Itab0;
PROCEDURE IJtab0(i,j : CARDINAL) : CARDINAL;
BEGIN
IF (i > j) THEN RETURN Index0[i] + j; ELSE RETURN Index0[j] + i; END;
END IJtab0;
VAR i,ii : CARDINAL;
BEGIN
ii:=0; Index[0]:=0;
FOR i:=0 TO MaxDim-1 DO Index[i+1]:=ii; INC(ii,i+1) END;
ii:=1; Index0[0]:=0;
FOR i:=1 TO MaxDim-1 DO Index0[i]:=ii; INC(ii,i+1) END;
END Tabelle;
PROCEDURE InitLRArray(VAR X : ARRAY OF LONGREAL;
y : LONGREAL;
n : CARDINAL);
VAR i,mod : CARDINAL;
unrolled : BOOLEAN;
BEGIN
unrolled := n > 32;
IF NOT unrolled THEN
FOR i:=0 TO n-1 DO X[i]:=y; END;
ELSE
IF (n > 0) THEN
mod := n MOD 4;
IF (mod # 0) THEN
FOR i:=0 TO mod-1 DO X[i]:=y; END;
END;
IF (n > 3) THEN (* Unrolled loop *)
FOR i:=mod TO n-1 BY 4 DO
X[i ]:=y; X[i+1]:=y;
X[i+2]:=y; X[i+3]:=y;
END;
END;
END;
END; (* IF unrolled *)
END InitLRArray;
PROCEDURE InitLCArray(VAR X : ARRAY OF LONGCOMPLEX;
y : LONGCOMPLEX;
n : CARDINAL);
VAR i,mod : CARDINAL;
unrolled : BOOLEAN;
BEGIN
unrolled := n > 32;
IF NOT unrolled THEN
FOR i:=0 TO n-1 DO X[i]:=y; END;
ELSE
IF (n > 0) THEN
mod := n MOD 4;
IF (mod # 0) THEN
FOR i:=0 TO mod-1 DO X[i]:=y; END;
END;
IF (n > 3) THEN (* Unrolled loop *)
FOR i:=mod TO n-1 BY 4 DO
X[i ]:=y; X[i+1]:=y;
X[i+2]:=y; X[i+3]:=y;
END;
END;
END;
END; (* IF unrolled *)
END InitLCArray;
PROCEDURE InitMat(VAR M : ARRAY OF ARRAY OF LONGREAL;
m,n : CARDINAL;
Form : CHAR;
x : LONGREAL);
VAR i,j : CARDINAL;
BEGIN
Errors.Fehler:=FALSE;
IF (n = 0) THEN RETURN; END;
IF (m-1 > HIGH(M)) OR (n-1 > HIGH(M[0])) THEN
Errors.Fehler:=TRUE;
Errors.Fehlerflag:='Dimensionierungsfehler (MatLib.InitMat)';
Errors.ErrOut(Errors.Fehlerflag);
IF (m-1 > HIGH(M)) THEN m:=HIGH(M)-1; END;
IF (n-1 > HIGH(M[0])) THEN n:=HIGH(M[0])-1; END;
ELSIF (CAP(Form) = 'D') AND (m # n) THEN
Errors.Fehler:=TRUE;
Errors.Fehlerflag:='Matrix nicht symmetrisch (MatLib.InitMat)';
Errors.ErrOut(Errors.Fehlerflag);
END;
Form:=CAP(Form); (* Form immer gro3 *)
IF (Form # 'A') AND (Form # 'D') THEN Form:='A'; x:=0.0; END;
IF (CAP(Form) = 'A') THEN
FOR i:=0 TO m-1 DO
InitLRArray(M[i],x,n);
END;
ELSIF (CAP(Form) = 'D') THEN
IF (n = 1) THEN
M[0,0]:=x;
ELSE
M[0,0]:=x; FOR j:=1 TO n-1 DO M[0,j]:=0.0; END;
FOR i:=1 TO n-1 DO
FOR j:=0 TO i-1 DO M[i,j]:=0.0; END;
M[i,i]:=x;
FOR j:=i+1 TO n-1 DO M[i,j]:=0.0; END;
END;
END;
END; (* IF form *)
END InitMat;
PROCEDURE InitCMat(VAR M : ARRAY OF ARRAY OF LONGCOMPLEX;
m,n : CARDINAL;
Form : CHAR;
x : LONGCOMPLEX);
VAR i,j : CARDINAL;
BEGIN
Errors.Fehler:=FALSE;
IF (n = 0) THEN RETURN; END;
IF (m-1 > HIGH(M)) OR (n-1 > HIGH(M[0])) THEN
Errors.Fehler:=TRUE;
Errors.Fehlerflag:='Dimensionierungsfehler (MatLib.InitMat)';
Errors.ErrOut(Errors.Fehlerflag);
IF (m-1 > HIGH(M)) THEN m:=HIGH(M)-1; END;
IF (n-1 > HIGH(M[0])) THEN n:=HIGH(M[0])-1; END;
ELSIF (CAP(Form) = 'D') AND (m # n) THEN
Errors.Fehler:=TRUE;
Errors.Fehlerflag:='Matrix nicht symmetrisch (MatLib.InitMat)';
Errors.ErrOut(Errors.Fehlerflag);
END;
Form:=CAP(Form); (* Form immer gro3 *)
IF (Form # 'A') AND (Form # 'D') THEN Form:='A'; x:=zero; END;
IF (CAP(Form) = 'A') THEN
FOR i:=0 TO m-1 DO
InitLCArray(M[i],x,n);
END;
ELSIF (CAP(Form) = 'D') THEN
IF (n = 1) THEN
M[0,0]:=x;
ELSE
M[0,0]:=x; FOR j:=1 TO n-1 DO M[0,j]:=zero; END;
FOR i:=1 TO n-1 DO
FOR j:=0 TO i-1 DO M[i,j]:=zero; END;
M[i,i]:=x;
FOR j:=i+1 TO n-1 DO M[i,j]:=zero; END;
END;
END;
END; (* IF form *)
END InitCMat;
PROCEDURE InitSV(VAR Sv : SUPERVEKTOR;
dim : CARDINAL;
Form : CHAR;
x : LONGREAL);
VAR i,j,ij : CARDINAL;
BEGIN
Fehler:=FALSE;
IF (dim > MaxDim) THEN
Fehler:=TRUE; Fehlerflag:='dim > MaxDim (InitSV)';
Errors.ErrOut(Fehlerflag);
RETURN; (* !!! *)
END;
Form:=CAP(Form); (* Form immer gro\3 *)
IF (Form # 'A') AND (Form # 'D') THEN Form:='A'; x:=0.0; END;
IF (Form = 'A') THEN
ij:=0;
FOR i:=1 TO dim DO FOR j:=1 TO i DO INC(ij); Sv[ij]:=x; END; END;
ELSIF (Form = 'D') THEN
ij:=0;
FOR i:=1 TO dim DO
FOR j:=1 TO i-1 DO INC(ij); Sv[ij]:=0.0; END;
INC(ij); Sv[ij]:=x;
END;
END; (* IF Form *)
END InitSV;
PROCEDURE CopyMat(VAR B : ARRAY OF ARRAY OF LONGREAL; (* ==> *)
VAR A : ARRAY OF ARRAY OF LONGREAL; (* <== *)
m,n : CARDINAL);
VAR i : CARDINAL;
BEGIN
FOR i:=0 TO m-1 DO
LibDBlasM2.dcopy(n,A[i],1,B[i],1); (* copy A to B *)
END;
END CopyMat;
PROCEDURE VektorinSV(VAR SV : SUPERVEKTOR;
Vek : VEKTOR;
n : CARDINAL);
VAR i,ii : CARDINAL;
BEGIN
ii:=0; FOR i:=1 TO n DO INC(ii,i); SV[ii]:=SV[ii]+Vek[i]; END;
END VektorinSV;
PROCEDURE SvToMat(VAR SV : ARRAY OF LONGREAL; (* SUPERVEKTOR *)
VAR Mat : ARRAY OF ARRAY OF LONGREAL;
dim : CARDINAL;
steuer : INTEGER);
VAR i,j,ij : CARDINAL;
BEGIN
IF (ABS(steuer) > 2) THEN steuer:=0; END;
ij:=0;
IF (steuer = 0) THEN
FOR i:=0 TO dim-1 DO (* Belege untere Dreiecksmatrix mit SV. *)
FOR j:=0 TO i DO Mat[i,j]:=SV[ij]; INC(ij); END;
END;
FOR i:=0 TO dim-1 DO (* Belege obere Dreiecksmatrix mit SV. *)
FOR j:=i+1 TO dim-1 DO Mat[i,j]:=Mat[j,i]; END;
END;
ELSE
IF (steuer < 0) THEN
IF (steuer = -2) THEN
FOR i:=0 TO dim-1 DO (* Belege obere Dreiecksmatrix mit Null. *)
FOR j:=i+1 TO dim-1 DO Mat[i,j]:=0.0; END;
END;
END;
FOR i:=0 TO dim-1 DO (* Belege untere Dreiecksmatrix mit SV. *)
FOR j:=0 TO i DO Mat[i,j]:=SV[ij]; INC(ij); END;
END;
END;
IF (steuer > 0) THEN
IF (steuer = 2) THEN
FOR i:=1 TO dim-1 DO (* Belege untere Dreiecksmatrix mit Null. *)
FOR j:=0 TO i-1 DO Mat[i,j]:=0.0; END;
END;
END;
FOR i:=0 TO dim-1 DO (* Belege obere Dreiecksmatrix mit SV. *)
FOR j:=i TO dim-1 DO Mat[i,j]:=SV[IJtab0(i,j)]; END;
END;
END;
END; (* IF steuer = 0 *)
END SvToMat;
PROCEDURE MatToSv(VAR Mat : MATRIX;
VAR Sv : SUPERVEKTOR;
dim : CARDINAL;
steuer : INTEGER);
VAR i,j,ij : CARDINAL;
BEGIN
IF (ABS(steuer) > 1) THEN steuer:=0; END;
ij:=0;
Fehler:=FALSE;
IF (steuer < 0) THEN (* Testen !!! *)
FOR i:=1 TO dim DO
FOR j:=i TO dim DO INC(ij); Sv[ij]:=Mat[i,j]; END;
END;
ELSE
IF (steuer = 0) THEN
FOR i:=1 TO dim DO
FOR j:=1 TO i DO INC(ij); Sv[ij]:=Mat[i,j]; END;
END;
ELSE (* steuer = 1 *)
FOR i:=1 TO dim DO
FOR j:=1 TO i DO
IF (Mat[i,j] # Mat[j,i]) THEN
Fehler:=TRUE;
Fehlerflag := 'Matrix nicht symmetrisch (MatLib.MatToSv) !';
RETURN;
ELSE
INC(ij);
Sv[ij] := Mat[i,j];
END;
END; (* FOR j *)
END; (* FOR i *)
END; (* IF *)
END; (* IF *)
END MatToSv;
PROCEDURE TriMat(VAR Mat : MATRIX; (* resultierende Matrix *)
VAR HD,ND : VEKTOR; (* Haupt - Nebendiagonale *)
dim : CARDINAL;
Form : CARDINAL);
VAR i : CARDINAL;
BEGIN
IF (Form > 1) THEN Errors.FatalError(' Form > 1 (TriSv)'); END;
IF (Form = 0) THEN
InitMat(Mat,dim,dim,'a',0.0);
Mat[1,1]:=HD[1];
Mat[1,2]:=ND[1];
FOR i:=2 TO dim-1 DO
Mat[i,i]:=HD[i];
Mat[i,i-1]:=ND[i-1];
Mat[i,i+1]:=ND[i];
END;
Mat[dim,dim]:=HD[dim];
Mat[dim,dim-1]:=ND[dim-1];
ELSE
Mat[1,1]:=HD[1];
Mat[1,2]:=ND[1];
FOR i:=2 TO dim-1 DO
HD[i]:=Mat[i,i];
ND[i-1]:=Mat[i,i-1];
ND[i]:=Mat[i,i+1];
END;
HD[dim]:=Mat[dim,dim];
ND[dim-1]:=Mat[dim,dim-1];
ND[dim]:=0.0;
END;
END TriMat;
PROCEDURE TriSv(VAR SV : SUPERVEKTOR; (* resultierende Matrix *)
VAR HD,ND : VEKTOR; (* Haupt - Nebendiagonale *)
dim : CARDINAL;
Form : CARDINAL);
VAR i,ij,ii,SVdim : CARDINAL;
BEGIN
SVdim:=(dim*(dim+1)) DIV 2;
IF (Form > 1) THEN Errors.FatalError('Form > 1 (TriSv)'); END;
IF (Form = 0) THEN
FOR ij:=1 TO SVdim DO SV[ij]:=0.0; END;
SV[1]:=HD[1];
SV[2]:=ND[1];
ii:=1;
FOR i:=2 TO dim-1 DO
INC(ii,i);
SV[ii]:=HD[i];
SV[ii-1]:=ND[i-1];
END;
SV[SVdim]:=HD[dim];
SV[SVdim-1]:=ND[dim-1];
ELSE
HD[1]:=SV[1];
ND[2]:=SV[1];
ii:=1;
FOR i:=2 TO dim-1 DO
INC(ii,i);
HD[i]:=SV[ii];
ND[i-1]:=SV[ii-1];
END;
HD[dim]:=SV[SVdim];
ND[dim-1]:=SV[SVdim-1];
ND[dim]:=0.0;
END;
END TriSv;
PROCEDURE Stuerz(VAR Mat : ARRAY OF ARRAY OF LONGREAL;
dim : CARDINAL);
VAR i,j : CARDINAL;
Zw : LONGREAL;
BEGIN
FOR i:=0 TO dim-1 DO
FOR j:=i+1 TO dim-1 DO
Zw:=Mat[i,j]; Mat[i,j]:=Mat[j,i]; Mat[j,i]:=Zw;
END;
END;
END Stuerz;
PROCEDURE StuerzMN(VAR A : ARRAY OF ARRAY OF LONGREAL;
M,N : CARDINAL);
VAR i,j,mn : CARDINAL;
T : PMATRIX;
BEGIN
IF (M = N) THEN
Stuerz(A,N);
ELSE
mn := MaxCard(M,N);
IF (HIGH(A) < mn) OR (HIGH(A[0]) < mn) THEN
Errors.FatalError("Matrix A falsch dimensioniert (MatLib.StuerzMN)");
END;
AllocMat(T,M,N);
IF (T = NIL) THEN
Errors.FatalError("Kein Freispeicher vorhanden (MatLib.StuerzMN)");
END;
FOR i:=0 TO M-1 DO
FOR j:=0 TO N-1 DO T^[i+1]^[j+1]:=A[i,j]; END;
END;
IF (1 = 1) THEN (* This code is not really necessary *)
(* Initialisiere den Rest der (quadratischen) Matrix mit 0 *)
IF (N < M) THEN
FOR i:=N TO M-1 DO
FOR j:=0 TO M-1 DO A[i,j]:=0.0; END;
END;
ELSE
FOR i:=0 TO N-1 DO
FOR j:=M TO N-1 DO A[j,i]:=0.0; END;
END;
END; (* IF M > N *)
END; (* IF *)
FOR i:=0 TO M-1 DO
FOR j:=0 TO N-1 DO
A[j,i]:=T^[i+1]^[j+1];
END;
END;
DeAllocMat(T,M,N);
END;
END StuerzMN;
PROCEDURE CStuerzMN(VAR A : ARRAY OF ARRAY OF LONGCOMPLEX;
M,N : CARDINAL;
IfConj : BOOLEAN);
VAR i,j,mn : CARDINAL;
Tre,Tim : PMATRIX;
BEGIN
IF (M = N) THEN
CStuerz(A,N,IfConj);
ELSE
mn := MaxCard(M,N);
IF (HIGH(A) < mn) OR (HIGH(A[0]) < mn) THEN
Errors.FatalError("Matrix A falsch dimensioniert (MatLib.StuerzMN)");
END;
AllocMat(Tre,M,N);
AllocMat(Tim,M,N);
IF (Tre = NIL) OR (Tim = NIL) THEN
Errors.FatalError("Kein Freispeicher vorhanden (MatLib.CStuerzMN)");
END;
FOR i:=0 TO M-1 DO
FOR j:=0 TO N-1 DO
Tre^[i+1]^[j+1] := RE(A[i,j]);
Tim^[i+1]^[j+1] := IM(A[i,j]);
END;
END;
IF (1 = 1) THEN (* This code is not really necessary *)
(* Initialisiere den Rest der (quadratischen) Matrix mit 0 *)
IF (N < M) THEN
FOR i:=N TO M-1 DO
FOR j:=0 TO M-1 DO A[i,j]:=zero; END;
END;
ELSE
FOR i:=0 TO N-1 DO
FOR j:=M TO N-1 DO A[i,j]:=zero; END;
END;
END; (* IF M > N *)
END; (* IF *)
FOR i:=0 TO M-1 DO
IF IfConj THEN
FOR j:=0 TO N-1 DO
A[j,i]:=CMPLX(Tre^[i+1]^[j+1], - Tim^[i+1]^[j+1]);
END;
ELSE
FOR j:=0 TO N-1 DO
A[j,i]:=CMPLX(Tre^[i+1]^[j+1], Tim^[i+1]^[j+1]);
END;
END; (* IF *)
END;
DeAllocMat(Tre,M,N);
DeAllocMat(Tim,M,N);
END;
END CStuerzMN;
PROCEDURE Transpose(VAR A : ARRAY OF ARRAY OF LONGREAL;
n : CARDINAL);
(*----------------------------------------------------------------*)
(* The idea is comming form stackoverflow.com/questions/5200338/ *)
(* a-cache-efficient-matrix-transpose-program *)
(*----------------------------------------------------------------*)
CONST block = 64;
VAR i,j,nb : CARDINAL;
t : LONGREAL;
BEGIN
nb := 0;
WHILE nb+block-1 < n DO
FOR i:=nb TO nb+block-1 DO
FOR j:=i+1 TO nb+block-1 DO
t:=A[i,j]; A[i,j]:=A[j,i]; A[j,i]:=t;
END;
END;
FOR i:=nb+block TO n-1 DO
FOR j:=nb TO nb+block-1 DO
t:=A[i,j]; A[i,j]:=A[j,i]; A[j,i]:=t;
END;
END;
nb:=nb+block;
END; (* WHILE *)
FOR i:=nb TO n-1 DO (* clean up code *)
FOR j:=i+1 TO n-1 DO
t:=A[i,j]; A[i,j]:=A[j,i]; A[j,i]:=t;
END;
END;
END Transpose;
PROCEDURE TransposeMN( M,N : CARDINAL;
VAR A,T : ARRAY OF ARRAY OF LONGREAL);
(*----------------------------------------------------------------*)
(* Based on stackoverflow.com/questions/5200338 *)
(* "a-cache-efficient-matrix-transpose-program" *)
(*----------------------------------------------------------------*)
PROCEDURE CacheTranspose(rb,re : CARDINAL;
cb,ce : CARDINAL);
CONST BlockSize = 8;
VAR r,c,i,j : CARDINAL;
BEGIN
r := re - rb;
c := ce - cb;
IF (r <= BlockSize) AND (c <= BlockSize) THEN
FOR i:=rb TO re-1 DO
FOR j:=cb TO ce-1 DO
T[j,i] := A[i,j];
END;
END;
ELSIF (r >= c) THEN
CacheTranspose(rb, rb + (r DIV 2), cb, ce);
CacheTranspose(rb + (r DIV 2), re, cb, ce);
ELSE
CacheTranspose(rb, re, cb, cb + (c DIV 2));
CacheTranspose(rb, re, cb + (c DIV 2), ce);
END;
END CacheTranspose;
BEGIN
CacheTranspose(0,M+1, 0,N+1);
END TransposeMN;
PROCEDURE CStuerz(VAR Mat : ARRAY OF ARRAY OF LONGCOMPLEX;
dim : CARDINAL;
Conjug : BOOLEAN);
VAR i,j : CARDINAL;
Zw : LONGCOMPLEX;
BEGIN
FOR i:=0 TO dim-1 DO
FOR j:=i+1 TO dim-1 DO
Zw:=Mat[i,j]; Mat[i,j]:=Mat[j,i];
IF Conjug THEN
Mat[i,j] := LongComplexMath.conj(Mat[i,j]);
Zw := LongComplexMath.conj(Zw);
END;
Mat[j,i]:=Zw;
END;
END;
END CStuerz;
PROCEDURE StuerzRev(VAR A : MATRIX;
dim : CARDINAL);
VAR i,j,p,q : CARDINAL;
x : LONGREAL;
BEGIN
q:=dim; (* q = dim-i+1 *)
FOR i:=1 TO dim DO
p:=dim; (* p = dim-j+1 *)
FOR j:=1 TO q DO x:=A[i,j]; A[i,j]:=A[p,q]; A[p,q]:=x; DEC(p); END;
DEC(q);
END;
END StuerzRev;
PROCEDURE IntSort(VAR IVek : ARRAY OF INTEGER; (* Zu Sortierender Vektor *)
VAR I : ARRAY OF CARDINAL; (* Urspr"ungliche Positionen *)
dim : CARDINAL; (* Dimension von IVek *)
ord : INTEGER); (* Steuerparameter *)
VAR i,u,o,imin,imax : CARDINAL;
Min,Max,inter : INTEGER;
Abs,Aufsteigend : BOOLEAN;
BEGIN
FOR i:=0 TO dim-1 DO I[i]:=i+1; END;
IF (ord = 0) THEN RETURN; END;
IF (dim <= 1) THEN RETURN; END;
IF (ABS(ord) > 2) THEN
Errors.ErrOut('ABS(ord) > 2 (IntSort)');
ord:=1;
END;
IF (ABS(ord) = 1) THEN Abs:=FALSE ELSE Abs:=TRUE END;
IF (ord > 0) THEN Aufsteigend:=FALSE ELSE Aufsteigend:=TRUE END;
u:=0; o:=dim-1;
REPEAT
imax:=u; Max:=IVek[u];
imin:=u; Min:=IVek[u];
IF Abs THEN Max:=ABS(Max); Min:=ABS(Min); END;
FOR i:=u+1 TO o DO
IF NOT Abs THEN
IF (IVek[i] > Max) THEN Max:=IVek[i]; imax:=i;
ELSIF (IVek[i] < Min) THEN Min:=IVek[i]; imin:=i; END;
ELSE
IF (ABS(IVek[i]) > Max) THEN Max:=ABS(IVek[i]); imax:=i;
ELSIF (ABS(IVek[i]) < Min) THEN Min:=ABS(IVek[i]); imin:=i; END;
END;
END; (* FOR i *)
IF Aufsteigend THEN
IF (imax <> o) THEN
inter:=IVek[o]; IVek[o]:=IVek[imax]; IVek[imax]:=inter;
i:=I[o]; I[o]:=I[imax]; I[imax]:=i;
END;
IF (imin = o) THEN
IF (imax = u) THEN imin:=u;
ELSE imin:=imax; END;
END;
IF (imin <> u) THEN
inter:=IVek[u]; IVek[u]:=IVek[imin]; IVek[imin]:=inter;
i:=I[u]; I[u]:=I[imin]; I[imin]:=i;
END;
ELSE (* Absteigend sortieren *)
IF (imax <> u) THEN
inter:=IVek[u]; IVek[u]:=IVek[imax]; IVek[imax]:=inter;
i:=I[u]; I[u]:=I[imax]; I[imax]:=i;
END;
IF (imin = u) THEN
IF (imax = o) THEN imin:=o;
ELSE imin:=imax; END;
END;
IF (imin <> o) THEN
inter:=IVek[o]; IVek[o]:=IVek[imin]; IVek[imin]:=inter;
i:=I[o]; I[o]:=I[imin]; I[imin]:=i;
END;
END; (* IF Absteigend *)
INC(u); DEC(o);
UNTIL (u >= o);
END IntSort;
PROCEDURE QuickSort(VAR VEK : ARRAY OF LONGREAL;
VAR II : ARRAY OF CARDINAL;
dim : CARDINAL;
ord : INTEGER);
PROCEDURE Sort(l,r : CARDINAL);
(*-----------------------------------------------------------*)
(* F\"uhrt den eigentlichen Qicksortalgorithmus durch, damit *)
(* Rekursion in QickSort m\"oglich ist. *)
(*-----------------------------------------------------------*)
VAR i,j,m : CARDINAL;
x,y : LONGREAL;
BEGIN
i:=l; j:=r;
x:=VEK[((l+r) DIV 2) - 1];
REPEAT
IF (ord = -1) THEN (* Absteigende Reihenfolge *)
WHILE (VEK[i-1] < x) DO INC(i); END;
WHILE (x < VEK[j-1]) DO DEC(j); END;
ELSE (* Aufsteigende Reihenfolge *)
WHILE (VEK[i-1] > x) DO INC(i); END;
WHILE (x > VEK[j-1]) DO DEC(j); END;
END;
IF (i <= j) THEN
y:=VEK[i-1]; VEK[i-1]:=VEK[j-1]; VEK[j-1]:=y;
m:=II[i-1]; II[i-1]:=II[j-1]; II[j-1]:=m;
INC(i); DEC(j);
END;
UNTIL (i > j);
IF (l < j) THEN Sort(l,j); END;
IF (i < r) THEN Sort(i,r); END;
END Sort;
VAR i : CARDINAL;
BEGIN
FOR i:=1 TO dim DO II[i-1]:=i; END;
IF (ord = -1) OR (ord = 1) THEN Sort(1,dim); END;
END QuickSort;
PROCEDURE Sort(VAR VEK : VEKTOR;
dim : CARDINAL;
ord : INTEGER);
VAR i,l,iminmax : CARDINAL;
minmax,Interim : LONGREAL;
BEGIN
FOR l:=1 TO dim DO
minmax:=VEK[l]; iminmax:=l;
FOR i:=l+1 TO dim DO
IF (ord = 1) THEN (* Berechne Maximum von VEK[n] *)
IF (VEK[i] > minmax) THEN
minmax:=VEK[i];
iminmax:=i;
END;
ELSE (* Berechne Minimum von VEK[n] *)
IF (VEK[i] < minmax) THEN
minmax:=VEK[i];
iminmax:=i;
END;
END; (* IF *)
END; (* FOR i *)
IF (iminmax <> l) THEN (* Vertausche VEKi mit VEKimax *)
Interim:=VEK[l];
VEK[l]:=VEK[iminmax];
VEK[iminmax]:=Interim;
END; (* IF *)
END; (* FOR l *)
END Sort;
PROCEDURE SortVek(VAR X : ARRAY OF LONGREAL; (* Zu Sortierender Vektor *)
VAR I : ARRAY OF CARDINAL; (* Urspr\"ungliche Positionen *)
dim : CARDINAL; (* Dimension von X *)
ord : INTEGER); (* Steuerparameter *)
VAR i,u,o,imin,imax : CARDINAL;
Min,Max,x : LONGREAL;
Abs,Aufsteigend : BOOLEAN;
BEGIN
FOR i:=0 TO dim-1 DO I[i]:=i+1; END;
IF (ord = 0) THEN RETURN; END;
IF (dim <= 1) THEN RETURN; END;
IF (ABS(ord) > 2) THEN
Errors.ErrOut('ABS(ord) > 2 (SortVek)');
ord:=1;
END;
IF (ABS(ord) = 1) THEN Abs:=FALSE ELSE Abs:=TRUE END;
IF (ord > 0) THEN Aufsteigend:=FALSE ELSE Aufsteigend:=TRUE END;
u:=0; o:=dim-1;
REPEAT
imax:=u; Max:=X[u];
imin:=u; Min:=X[u];
IF Abs THEN Max:=ABS(Max); Min:=ABS(Min); END;
FOR i:=u+1 TO o DO
IF NOT Abs THEN
IF (X[i] > Max) THEN Max:=X[i]; imax:=i;
ELSIF (X[i] < Min) THEN Min:=X[i]; imin:=i; END;
ELSE
IF (ABS(X[i]) > Max) THEN Max:=ABS(X[i]); imax:=i;
ELSIF (ABS(X[i]) < Min) THEN Min:=ABS(X[i]); imin:=i; END;
END;
END; (* FOR i *)
IF Aufsteigend THEN
IF (imax <> o) THEN
x:=X[o]; X[o]:=X[imax]; X[imax]:=x;
i:=I[o]; I[o]:=I[imax]; I[imax]:=i;
END;
IF (imin = o) THEN
IF (imax = u) THEN imin:=u;
ELSE imin:=imax; END;
END;
IF (imin <> u) THEN
x:=X[u]; X[u]:=X[imin]; X[imin]:=x;
i:=I[u]; I[u]:=I[imin]; I[imin]:=i;
END;
ELSE (* Absteigend sortieren *)
IF (imax <> u) THEN
x:=X[u]; X[u]:=X[imax]; X[imax]:=x;
i:=I[u]; I[u]:=I[imax]; I[imax]:=i;
END;
IF (imin = u) THEN
IF (imax = o) THEN imin:=o;
ELSE imin:=imax; END;
END;
IF (imin <> o) THEN
x:=X[o]; X[o]:=X[imin]; X[imin]:=x;
i:=I[o]; I[o]:=I[imin]; I[imin]:=i;
END;
END; (* IF Absteigend *)
INC(u); DEC(o);
UNTIL (u >= o);
END SortVek;
PROCEDURE CSortVek(VAR X : ARRAY OF LONGCOMPLEX; (* Zu Sortierend *)
VAR I : ARRAY OF CARDINAL; (* Urspr\"ungl. Positionen *)
dim : CARDINAL; (* Dimension von X *)
ord : INTEGER); (* Steuerparameter *)
VAR i,u,o,imin,imax : CARDINAL;
Min,Max : LONGREAL;
x : LONGCOMPLEX;
Aufsteigend : BOOLEAN;
AbsX : ARRAY [0..MaxDim-1] OF LONGREAL;
BEGIN
FOR i:=0 TO dim-1 DO I[i]:=i; END;
IF (ord = 0) THEN RETURN; END;
FOR i:=0 TO dim-1 DO AbsX[i]:=LongComplexMath.abs(X[i]); END;
IF (dim <= 1) THEN RETURN; END;
IF (ABS(ord) > 1) THEN
Errors.ErrOut('ABS(ord) > 1 (CSortVek)');
ord:=1;
END;
IF (ord > 0) THEN Aufsteigend:=FALSE; ELSE Aufsteigend:=TRUE; END;
u:=0; o:=dim-1;
REPEAT
imax:=u; Max:=AbsX[u];
imin:=u; Min:=AbsX[u];
FOR i:=u+1 TO o DO
IF (AbsX[i] > Max) THEN
Max:=AbsX[i]; imax:=i;
ELSIF (AbsX[i] < Min) THEN
Min:=AbsX[i]; imin:=i;
END;
END; (* FOR i *)
IF Aufsteigend THEN
IF (imax <> o) THEN
x:=X[o]; X[o]:=X[imax]; X[imax]:=x; AbsX[imax]:=AbsX[o];
i:=I[o]; I[o]:=I[imax]; I[imax]:=i;
END;
IF (imin = o) THEN
IF (imax = u) THEN imin:=u; ELSE imin:=imax; END;
END;
IF (imin <> u) THEN
x:=X[u]; X[u]:=X[imin]; X[imin]:=x; AbsX[imin]:=AbsX[u];
i:=I[u]; I[u]:=I[imin]; I[imin]:=i;
END;
ELSE (* Absteigend sortieren *)
IF (imax <> u) THEN
x:=X[u]; X[u]:=X[imax]; X[imax]:=x; AbsX[imax]:=AbsX[u];
i:=I[u]; I[u]:=I[imax]; I[imax]:=i;
END;
IF (imin = u) THEN
IF (imax = o) THEN imin:=o; ELSE imin:=imax; END;
END;
IF (imin <> o) THEN
x:=X[o]; X[o]:=X[imin]; X[imin]:=x; AbsX[imin]:=AbsX[o];
i:=I[o]; I[o]:=I[imin]; I[imin]:=i;
END;
END; (* IF Absteigend *)
INC(u); DEC(o);
UNTIL (u >= o);
END CSortVek;
PROCEDURE MatVekProd(VAR Y : ARRAY OF LONGREAL;
VAR A : ARRAY OF ARRAY OF LONGREAL;
X : ARRAY OF LONGREAL;
M,N : CARDINAL;
trans : BOOLEAN);
VAR i,j : CARDINAL;
Xi,Yi : LONGREAL;
BEGIN
IF (NOT trans) THEN (* y = A*x *)
FOR i:=0 TO M-1 DO
Yi := 0.0;
FOR j:=0 TO N-1 DO Yi:=Yi + A[i,j]*X[j]; END;
Y[i]:=Yi;
END;
ELSE (* y = A^{tr}*x *)
FOR j:=0 TO N-1 DO Y[j]:=0.0; END;
FOR i:=0 TO M-1 DO
IF (X[i] # 0.0) THEN
Xi := X[i];
FOR j:=0 TO N-1 DO Y[j]:=Y[j] + A[i,j]*Xi; END;
END;
END;
END;
END MatVekProd;
PROCEDURE CMatVekProd(VAR Y : ARRAY OF LONGCOMPLEX;
VAR A : ARRAY OF ARRAY OF LONGCOMPLEX;
X : ARRAY OF LONGCOMPLEX;
M,N : CARDINAL;
trans : CHAR);
VAR i,j : CARDINAL;
Xi,Yi : LONGCOMPLEX;
BEGIN
IF (CAP(trans) = "N") THEN (* y = A*x *)
FOR i:=0 TO M-1 DO
Yi := zero;
FOR j:=0 TO N-1 DO Yi:=Yi + A[i,j]*X[j]; END;
Y[i]:=Yi;
END;
ELSIF (CAP(trans) = "T") THEN (* y = A^{tr}*x *)
FOR j:=0 TO N-1 DO Y[j]:=zero; END;
FOR i:=0 TO M-1 DO
IF (X[i] # zero) THEN
Xi := X[i];
FOR j:=0 TO N-1 DO Y[j]:=Y[j] + A[i,j]*Xi; END;
END;
END;
ELSIF (CAP(trans) = "C") THEN (* y = conj(A^{tr})*x *)
FOR j:=0 TO N-1 DO Y[j]:=zero; END;
FOR i:=0 TO M-1 DO
IF (X[i] # zero) THEN
Xi := X[i];
FOR j:=0 TO N-1 DO
Y[j]:=Y[j] + LongComplexMath.conj(A[i,j])*Xi;
END;
END;
END;
ELSE
Errors.FatalError("trans # CAP({N|T|C}) (CMatVekProd)");
END;
END CMatVekProd;
PROCEDURE SvVekProd(VAR Y : ARRAY OF LONGREAL; (* ==> *)
VAR A : ARRAY OF LONGREAL; (* <== SUPERVEKTOR *)
VAR X : ARRAY OF LONGREAL; (* <== *)
dim : CARDINAL);
VAR Nm1,i,j,ii,jj,ij : CARDINAL;
Sum : LONGREAL;
BEGIN
Nm1 := dim-1;
ii:=0;
FOR i:=0 TO Nm1 DO
Sum:=0.0;
ij:=ii;
(* OFFEN : Naechste Schleife eventuell ausrollen *)
FOR j:=0 TO i DO (* untere Haelfte + Diagonale *)
Sum:=Sum + A[ij]*X[j]; INC(ij);
END;
jj:=i+1;
INC(ij,i);
FOR j:=i+1 TO Nm1 DO (* obere Haelfte *)
Sum:=Sum + A[ij]*X[j];
INC(jj);
INC(ij,jj);
END;
Y[i]:=Sum;
INC(ii,i+1);
END;
END SvVekProd;
PROCEDURE MatMatProd(VAR C : MATRIX; (* Resultierende MATRIX *)
VAR A : MATRIX;
VAR B : MATRIX;
dim : CARDINAL);
VAR i,j,k : CARDINAL;
x : LONGREAL;
Vek : VEKTOR;
B0 : POINTER TO MATRIX;
BEGIN
NEW(B0);
IF (B0 = NIL) THEN
Errors.FatalError("kein Freispeicher vorhanden(MatLib.MatMatProd) !");
END;
FOR i:=1 TO dim DO FOR j:=1 TO dim DO B0^[i,j]:=B[i,j]; END; END;
FOR i:=1 TO dim DO
FOR j:=1 TO dim DO Vek[j]:=0.0; END;
FOR j:=1 TO dim DO
x:=A[i,j];
IF (x # 0.0) THEN
FOR k:=1 TO dim DO Vek[k]:=Vek[k] + x*B0^[j,k]; END;
END;
END;
FOR j:=1 TO dim DO C[i,j]:=Vek[j]; END;
END;
DISPOSE(B0);
END MatMatProd;
PROCEDURE MatMatProdNN( M,N,K : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR A,B : ARRAY OF ARRAY OF LONGREAL);
(*----------------------------------------------------------------*)
(* A[0..M-1][0..K-1] x B[0..K-1][0..N-1] = C[0..M-1][0..N-1] *)
(* Schleifen werden nur vierfach ausgerollt da nur eine Zeilen *)
(* der Matrix B in den Zwischenspeicher passen muss *)
(*----------------------------------------------------------------*)
CONST level = 4; (* Schleifen werden bis "level" ausgerollt *)
VAR Aik0,Aik1,Aik2,Aik3 : LONGREAL;
i,j,k,K2,Kmin : CARDINAL;
BEGIN
K2 := (K MOD level);
Kmin := K2 + level - 1;
IF (K2 # 0) THEN
FOR i:=0 TO M-1 DO
Aik0 := A[i,0];
FOR j:=0 TO N-1 DO C[i,j] := Aik0*B[0,j]; END;
IF (K2 > 1) THEN
Aik1 := A[i,1];
FOR j:=0 TO N-1 DO C[i,j]:=C[i,j] + Aik1*B[1,j]; END;
END;
IF (K2 > 2) THEN
Aik2 := A[i,2];
FOR j:=0 TO N-1 DO C[i,j]:=C[i,j] + Aik2*B[2,j]; END;
END;
END;
ELSE (* initialize C with zero *)
FOR i:=0 TO M-1 DO
FOR j:=0 TO N-1 DO C[i,j]:=0.0; END;
END;
END;
FOR i:=0 TO M-1 DO
FOR k:=Kmin TO K-1 BY level DO
Aik3 := A[i,k-3]; Aik2 := A[i,k-2];
Aik1 := A[i,k-1]; Aik0 := A[i,k-0];
FOR j:=0 TO N-1 DO
C[i,j]:=C[i,j] + Aik3*B[k-3,j] + Aik2*B[k-2,j]
+ Aik1*B[k-1,j] + Aik0*B[k-0,j];
END;
END;
END;
END MatMatProdNN;
PROCEDURE MatMatProdTN( M,N,K : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR A,B : ARRAY OF ARRAY OF LONGREAL);
(*----------------------------------------------------------------*)
(* A[0..K-1][0..M-1] x B[0..K-1][0..N-1] = C[0..M-1][0..N-1] *)
(* Schleifen werden nur doppelt ausgerollt da zwei Zeilen der *)
(* Matrix B in den Zwischenspeicher passen mussen *)
(*----------------------------------------------------------------*)
VAR A0i,Ak1i,Ak0i : LONGREAL;
i,j,k,K2,Kmin : CARDINAL;
Mm1,Nm1,Km1 : CARDINAL;
BEGIN
Mm1:=M-1; (*----------------------*)
Nm1:=N-1; (* Schleifenanalyse *)
Km1:=K-1; (* ijk 2A 2B *)
K2 := K MOD 2; (* ikj 2A *)
Kmin := K2 + 1; (* jik C^ 2A 2B *)
IF (K2 # 0) THEN (* jki C 2B *)
FOR i:=0 TO Mm1 DO (* kij *)
A0i:=A[0,i]; (* kji C *)
FOR j:=0 TO Nm1 DO (*----------------------*)
C[i,j]:=A0i*B[0,j];
END;
END;
ELSE
FOR i:=0 TO Mm1 DO
FOR j:=0 TO Nm1 DO C[i,j]:=0.0; END;
END;
END;
FOR k:=Kmin TO Km1 BY 2 DO
FOR i:=0 TO Mm1 DO
Ak1i:=A[k-1,i];
Ak0i:=A[k-0,i];
FOR j:=0 TO Nm1 DO
C[i,j]:=C[i,j] + Ak1i*B[k-1,j] + Ak0i*B[k+0,j];
END;
END;
END;
END MatMatProdTN;
PROCEDURE MatMatProdNT( M,N,K : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR A,B : ARRAY OF ARRAY OF LONGREAL);
(*----------------------------------------------------------------*)
(* A[0..M-1][0..K-1] x B[0..N-1][0..K-1] = C[0..M-1][0..N-1] *)
(* Schleifen werden nur doppelt ausgerollt da zwei Zeilen der *)
(* Matrix B in den Zwischenspeicher passen mussen *)
(*----------------------------------------------------------------*)
VAR Ai0,Aik1,Aik0 : LONGREAL;
i,j,k,K2,Kmin : CARDINAL;
Mm1,Nm1,Km1 : CARDINAL;
BEGIN
Mm1:=M-1; (*----------------------*)
Nm1:=N-1; (* Schleifenanalyse *)
Km1:=K-1; (* ijk *)
K2 := K MOD 2; (* ikj 2B *)
Kmin := K2 + 1; (* jik C^ *)
IF (K2 # 0) THEN (* jki C 2A *)
FOR i:=0 TO Mm1 DO (* kij 2A 2B *)
Ai0:=A[i,0]; (* kji C 2A 2B *)
FOR j:=0 TO Nm1 DO (*----------------------*)
C[i,j]:=Ai0*B[j,0];
END;
END;
ELSE
FOR i:=0 TO Mm1 DO
FOR j:=0 TO Nm1 DO C[i,j]:=0.0; END;
END;
END;
FOR k:=Kmin TO Km1 BY 2 DO
FOR i:=0 TO Mm1 DO
Aik1 := A[i,k-1];
Aik0 := A[i,k-0];
FOR j:=0 TO Nm1 DO
C[i,j]:=C[i,j] + Aik1*B[j,k-1] + Aik0*B[j,k+0];
END;
END;
END;
END MatMatProdNT;
PROCEDURE MatMatProdTT( M,N,K : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR A,B : ARRAY OF ARRAY OF LONGREAL);
(*----------------------------------------------------------------*)
(* A[0..K-1][0..M-1] x B[0..N-1][0..K-1] = C[0..M-1][0..N-1] *)
(* Schleifen werden nur doppelt ausgerollt da zwei Zeilen der *)
(* Matrix A in den Zwischenspeicher passen mussen *)
(*----------------------------------------------------------------*)
VAR Bj0,Bjk1,Bjk0 : LONGREAL;
i,j,k,K2,Kmin : CARDINAL;
Mm1,Nm1,Km1 : CARDINAL;
BEGIN
IF (N = K) THEN (* Erheblich schneller - much faster !!! *)
IF (N < 32) THEN Stuerz(B,N); ELSE Transpose(B,N); END;
MatMatProdTN(M,N,K,C,A,B);
IF (N < 32) THEN Stuerz(B,N); ELSE Transpose(B,N); END;
RETURN;
END;
Mm1:=M-1; (*----------------------*)
Nm1:=N-1; (* Schleifenanalyse *)
Km1:=K-1; (* ijk 2A *)
K2 := K MOD 2; (* ikj 2A + 2B *)
Kmin := K2 + 1; (* jik 1C^ + 2A *)
IF (K2 # 0) THEN (* jki 1C + 2A *)
FOR j:=0 TO Nm1 DO (* kij 2A^ + 2B *)
Bj0:=B[j,0]; (* kji 1C + 2A *)
FOR i:=0 TO Mm1 DO (*----------------------*)
C[i,j]:=A[0,i]*Bj0;
END;
END;
ELSE
FOR i:=0 TO Mm1 DO
FOR j:=0 TO Nm1 DO C[i,j]:=0.0; END;
END;
END;
FOR k:=Kmin TO Km1 BY 2 DO
FOR j:=0 TO Nm1 DO
Bjk1 := B[j,k-1];
Bjk0 := B[j,k+0];
FOR i:=0 TO Mm1 DO
C[i,j]:=C[i,j] + A[k-1,i]*Bjk1 + A[k+0,i]*Bjk0;
END;
END;
END;
END MatMatProdTT;
PROCEDURE CMatMatProd(VAR C : CMATRIX; (* Resultierende MATRIX *)
VAR A : CMATRIX;
VAR B : CMATRIX;
dim : CARDINAL);
VAR i,j,k : CARDINAL;
x : LONGCOMPLEX;
Vek : CVEKTOR;
B0 : POINTER TO CMATRIX;
BEGIN
NEW(B0);
IF (B0 = NIL) THEN
Errors.FatalError("kein Freispeicher vorhanden(MatLib.CMatMatProd) !");
END;
FOR i:=1 TO dim DO FOR j:=1 TO dim DO B0^[i,j]:=B[i,j]; END; END;
FOR i:=1 TO dim DO
FOR j:=1 TO dim DO Vek[j]:=zero; END;
FOR j:=1 TO dim DO
x:=A[i,j];
IF (x # zero) THEN (* Vek[k]:=Vek[k] + x*B[j,k]; *)
IF (RE(x) = 0.0) THEN
FOR k:=1 TO dim DO
Vek[k]:=Vek[k] + CMPLX(-IM(x)*IM(B0^[j,k]),IM(x)*RE(B0^[j,k]));
(* Vek[k].re:=Vek[k].re - x.im*B0^[j,k].im; *)
(* Vek[k].im:=Vek[k].im + x.im*B0^[j,k].re; *)
END;
ELSIF (IM(x) = 0.0) THEN
FOR k:=1 TO dim DO
Vek[k]:=Vek[k] + CMPLX(RE(x)*RE(B0^[j,k]),RE(x)*IM(B0^[j,k]));
(* Vek[k].re:=Vek[k].re + x.re*B0^[j,k].re; *)
(* Vek[k].im:=Vek[k].im + x.re*B0^[j,k].im; *)
END;
ELSE
FOR k:=1 TO dim DO
Vek[k]:=Vek[k] + x*B0^[j,k];
END;
END;
END; (* IF *)
END; (* FOR j *)
FOR j:=1 TO dim DO C[i,j]:=Vek[j]; END;
END; (* FOR i *)
DISPOSE(B0);
END CMatMatProd;
(*======================= Matrix x SUPERVEKTOR =============================*)
PROCEDURE MatSvProdNN( dim : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR A : ARRAY OF ARRAY OF LONGREAL;
VAR Bp : ARRAY OF LONGREAL); (* SUPERVEKTOR *)
VAR i,j,k,jj,kj : CARDINAL;
Sum : LONGREAL;
Ci : POINTER TO ARRAY [0..MAX(INTEGER)-1] OF LONGREAL;
BEGIN
ALLOCATE(Ci,dim*TSIZE(LONGREAL)); (* Speicher fuer Zwischenergebniss *)
IF (Ci = NIL) THEN
Errors.FatalError("Kein Freispeicher vorhanden (MatSvProd)");
END;
FOR i:=0 TO dim-1 DO
jj:=0;
FOR j:=0 TO dim-1 DO
Sum:=0.0; kj:=jj;
(* optimal *)
IF (j > 0) THEN
<* IF DEFINED(__BLAS__) THEN *>
Sum:=ddot(j,A[i][0],1,Bp[jj],1);
INC(kj,j);
<* ELSE *>
FOR k:=0 TO j-1 DO Sum:=Sum + A[i,k]*Bp[kj]; INC(kj); END;
<* END *>
END;
(* nicht optimal ... *)
FOR k:=j TO dim-1 DO Sum:=Sum + A[i,k]*Bp[kj]; INC(kj,k+1); END;
Ci^[j]:=Sum;
INC(jj,j+1);
END;
<* IF DEFINED(__BLAS__) THEN *>
dcopy(VAL(INTEGER,dim),Ci^[0],1,C[i][0],1);
<* ELSE *>
FOR j:=0 TO dim-1 DO C[i,j]:=Ci^[j]; END;
<* END *>
END;
DEALLOCATE(Ci,dim*TSIZE(LONGREAL));
END MatSvProdNN;
PROCEDURE MatSvProdTN( dim : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR A : ARRAY OF ARRAY OF LONGREAL;
VAR Bp : ARRAY OF LONGREAL); (* SUPERVEKTOR *)
VAR i,j,k,kk,kj : CARDINAL;
Aki : LONGREAL;
Bk : POINTER TO ARRAY [0..MaxDim-1] OF LONGREAL;
BEGIN
ALLOCATE(Bk,dim*TSIZE(LONGREAL));
IF (Bk = NIL) THEN
Errors.FatalError("kein Freispeicher vorhanden (MatLib.SvSvProd) !");
END;
FOR i:=0 TO dim-1 DO
FOR j:=0 TO dim DO C[i,j]:=0.0; END;
END;
kk:=0;
FOR k:=0 TO dim-1 DO
(* store colum B[k] in Bk to enable fast access in inner j loop *)
kj:=kk;
FOR j:=0 TO k DO Bk^[j]:=Bp[kj]; INC(kj); END;
INC(kj,k);
FOR j:=k+1 TO dim-1 DO Bk^[j]:=Bp[kj]; INC(kj,j+1); END;
(* ideale Struktur *)
FOR i:=0 TO dim-1 DO
Aki:=A[k,i];
<* IF DEFINED(__BLAS__) THEN *>
daxpy(dim,Aki,Bk^[0],1,C[i][0],1);
<* ELSE *>
FOR j:=0 TO dim-1 DO C[i,j]:=C[i,j] + Aki*Bk^[j]; END;
<* END *>
END;
INC(kk,k+1);
END;
DEALLOCATE(Bk,dim*TSIZE(LONGREAL));
END MatSvProdTN;
(*======================= SUPERVEKTOR x Matrix =============================*)
PROCEDURE SvMatProdNN( dim : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR Ap : ARRAY OF LONGREAL; (* SUPERVEKTOR *)
VAR B : ARRAY OF ARRAY OF LONGREAL);
VAR i,j,k,ii,ik : CARDINAL;
Aik : LONGREAL;
BEGIN
ii:=0;
FOR i:=0 TO dim-1 DO (* Loops reorderd i,k,j *)
FOR j:=0 TO dim-1 DO C[i,j]:=0.0; END;
ik:=ii;
(* ideale Struktur *)
IF (i > 0) THEN
FOR k:=0 TO i-1 DO
Aik := Ap[ik];
<* IF DEFINED(__BLAS__) THEN *>
daxpy(dim,Aik,B[k][0],1,C[i][0],1);
<* ELSE *>
FOR j:=0 TO dim-1 DO C[i,j]:=C[i,j] + Aik*B[k,j]; END;
<* END *>
INC(ik);
END;
END;
FOR k:=i TO dim-1 DO
Aik := Ap[ik];
<* IF DEFINED(__BLAS__) THEN *>
daxpy(dim,Aik,B[k][0],1,C[i][0],1);
<* ELSE *>
FOR j:=0 TO dim-1 DO C[i,j]:=C[i,j] + Aik*B[k,j]; END;
<* END *>
INC(ik,k+1);
END;
INC(ii,i+1);
END;
END SvMatProdNN;
PROCEDURE SvMatProdNT( dim : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR Ap : ARRAY OF LONGREAL; (* SUPERVEKTOR *)
VAR B : ARRAY OF ARRAY OF LONGREAL);
VAR i,j,ii,ij : CARDINAL;
<* IF NOT DEFINED(__BLAS__) THEN *>
k : CARDINAL;
<* END *>
Sum : LONGREAL;
Ai,Ci : POINTER TO ARRAY [0..MAX(INTEGER)-1] OF LONGREAL;
BEGIN
ALLOCATE(Ci,dim*TSIZE(LONGREAL));
ALLOCATE(Ai,dim*TSIZE(LONGREAL));
IF (Ci = NIL) OR (Ai = NIL) THEN
Errors.FatalError("Kein Freispeicher vorhanden (SvMatProdNT)");
END;
ii:=0;
FOR i:=0 TO dim-1 DO
(* store colum A[i] in Ai to enable fast access in inner k loop *)
ij:=ii;
FOR j:=0 TO i DO Ai^[j]:=Ap[ij]; INC(ij); END;
INC(ij,i);
FOR j:=i+1 TO dim-1 DO Ai^[j]:=Ap[ij]; INC(ij,j+1); END;
(* ideale Struktur *)
FOR j:=0 TO dim-1 DO
<* IF DEFINED(__BLAS__) THEN *>
Sum:=ddot(dim,Ai^[0],1,B[j][0],1);
<* ELSE *>
Sum:=0.0;
FOR k:=0 TO dim-1 DO Sum:=Sum + Ai^[k]*B[j,k]; END;
<* END *>
Ci^[j]:=Sum;
END; (* FOR j *)
INC(ii,i+1);
<* IF DEFINED(__BLAS__) THEN *>
dcopy(VAL(INTEGER,dim),Ci^[0],1,C[i][0],1);
<* ELSE *>
FOR j:=0 TO dim-1 DO C[i,j] := Ci^[j]; END;
<* END *>
END; (* FOR i *)
DEALLOCATE(Ai,dim*TSIZE(LONGREAL));
DEALLOCATE(Ci,dim*TSIZE(LONGREAL));
END SvMatProdNT;
(*======================= SUPERVEKTOR x SUPERVEKTOR ========================*)
PROCEDURE SvSvProdNN( dim : CARDINAL;
VAR C : ARRAY OF ARRAY OF LONGREAL;
VAR Ap,Bp : ARRAY OF LONGREAL); (* SUPERVEKTOR *)
VAR i,j,k : CARDINAL;
ii,jj,ij,jk : CARDINAL;
Sum : LONGREAL;
Ai : POINTER TO ARRAY [0..MaxDim-1] OF LONGREAL;
BEGIN
ALLOCATE(Ai,dim*TSIZE(LONGREAL));
IF (Ai = NIL) THEN
Errors.FatalError("kein Freispeicher vorhanden (MatLib.SvSvProd) !");
END;
ii:=0;
FOR i:=0 TO dim-1 DO
(* store colum A[i] in Ai to enable fast access in inner k loops *)
ij:=ii;
FOR j:=0 TO i DO Ai^[j]:=Ap[ij]; INC(ij); END;
INC(ij,i);
FOR j:=i+1 TO dim-1 DO Ai^[j]:=Ap[ij]; INC(ij,j+1); END;
jj:=0;
FOR j:=0 TO dim-1 DO
jk:=jj;
(* data for A & B the following loop should fit in cache ... *)
<* IF DEFINED(__BLAS__) THEN *>
Sum:=ddot(j+1,Ai^[0],1,Bp[jj],1);
INC(jk,j+1);
<* ELSE *>
Sum:=0.0; (* Inline code ... *)
FOR k:=0 TO j DO Sum:=Sum + Ai^[k]*Bp[jk]; INC(jk); END;
<* END *>
INC(jk,j);
(* Only data for A in the following loop fit in cache ... *)
FOR k:=j+1 TO dim-1 DO
Sum:=Sum + Ai^[k]*Bp[jk];
INC(jk,k+1); (* we cannot avoide this "jumping ahead" ... *)
END;
C[i,j]:=Sum;
INC(jj,j+1);
END; (* FOR j *)
INC(ii,i+1);
END; (* FOR i *)
DEALLOCATE(Ai,dim*TSIZE(LONGREAL));
END SvSvProdNN;
(*================= Ende Matrixmultiplikation SUPERVEKTOR ==================*)
PROCEDURE SkalarProd(VAR A,B : ARRAY OF LONGREAL;
dim : CARDINAL) : LONGREAL;
VAR i : CARDINAL;
Sum : LONGREAL;
BEGIN
Sum:=0.0; FOR i:=0 TO dim-1 DO Sum:=Sum + A[i]*B[i]; END;
RETURN Sum;
END SkalarProd;
PROCEDURE CSkalarProd(VAR A,B : ARRAY OF LONGCOMPLEX;
dim : CARDINAL) : LONGCOMPLEX;
VAR i : CARDINAL;
Sum : LONGCOMPLEX;
BEGIN
Sum:=zero;
FOR i:=0 TO dim-1 DO
Sum:=Sum + A[i]*B[i];
END;
RETURN Sum;
END CSkalarProd;
PROCEDURE MatSkalProd(VAR MAT : MATRIX; (* Resultierende MATRIX *)
x : LONGREAL;
dim : CARDINAL);
VAR i,j : CARDINAL;
BEGIN
FOR i:=1 TO dim DO
FOR j:=1 TO dim DO MAT[i,j]:=x*MAT[i,j]; END;
END;
END MatSkalProd;
PROCEDURE KreuzProd(VAR Mat : MATRIX; (* Resultierende Matrix *)
VAR Vec1 : VEKTOR;
VAR Vec2 : VEKTOR;
dim : CARDINAL); (* L\"ange der Vektoren *)
VAR i,j : CARDINAL;
BEGIN
FOR i:=1 TO dim DO
FOR j:=1 TO dim DO Mat[i,j] := Vec1[i] * Vec2[j]; END;
END;
END KreuzProd;
PROCEDURE SpaltVek(VAR SpVek : VEKTOR;
VAR MAT : MATRIX;
dim : CARDINAL;
j : CARDINAL); (* j.-Spalte wird SpVek *)
VAR i : CARDINAL;
BEGIN
FOR i:=1 TO dim DO SpVek[i]:=MAT[i,j]; END;
END SpaltVek;
PROCEDURE VekInMat(VAR VEK : VEKTOR;
VAR MAT : MATRIX;
j : CARDINAL;
dim : CARDINAL);
VAR i : CARDINAL;
BEGIN
FOR i:=1 TO dim DO MAT[i,j]:=VEK[i]; END;
END VekInMat;
PROCEDURE InsertMat(VAR A : MATRIX;
adimi : CARDINAL; (* first dimension of A *)
adimj : CARDINAL; (* second dimension of A *)
VAR B : MATRIX; (* Matrix to be inserted *)
in,jn : CARDINAL; (* 1. & 2. dimension ob B *)
is,js : CARDINAL; (* Startpoints where to insert *)
VAR ifehl : CARDINAL);
VAR i,j,ii : CARDINAL;
BEGIN
ifehl:=0;
IF (in > adimj) OR (jn > adimj) THEN
ifehl:=1;
END;
IF (is + in - 1 > adimi) THEN
ifehl:=ifehl+10;
END;
IF (js + jn - 1 > adimj) THEN
ifehl:=ifehl+100;
END;
IF (ifehl # 0) THEN
Errors.ErrOut(
"InsertMat : Matrix B kann nicht in Matrix A eingesetzt werden");
RETURN;
END;
FOR i:=1 TO in DO
ii:=is+i-1;
FOR j:=1 TO jn DO
A[ii,js+j-1]:=B[i,j];
END;
END;
END InsertMat;
PROCEDURE TriInfNorm( n : CARDINAL;
VAR D,E : ARRAY OF LONGREAL) : LONGREAL;
VAR norm,t1,t2 : LONGREAL;
i : CARDINAL;
BEGIN
IF (n = 1) THEN
norm := ABS(D[0]);
ELSE
t1 := ABS(D[0]) + ABS(E[0]);
t2 := ABS(D[n-1]) + ABS(E[n-2]);
IF (t1 > t2) THEN norm:=t1; ELSE norm:=t2; END;
FOR i:=1 TO n-2 DO
t1 := ABS(D[i]) + ABS(E[i]) + ABS(E[i-1]);
IF (t1 > norm) THEN norm:=t1; END;
END;
END;
RETURN norm;
END TriInfNorm;
PROCEDURE MatNormL1(VAR A : ARRAY OF ARRAY OF LONGREAL;
M,N : CARDINAL;
VAR Norm : LONGREAL);
VAR i,j : CARDINAL;
Sum : LONGREAL;
BEGIN
Norm:=0.0;
FOR i:=0 TO M-1 DO
Sum:=0.0;
FOR j:=0 TO N-1 DO Sum:=Sum + ABS(A[i,j]); END;
IF (Sum > Norm) THEN Norm:=Sum; END;
END;
END MatNormL1;
PROCEDURE ENorm(VAR X : ARRAY OF LONGREAL;
a,e : CARDINAL) : LONGREAL;
(*---------------------------------------------------------------*)
(* Argonne national laboratory. MINPACK project. March 1980. *)
(* Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More *)
(* *)
(* Anpassung an Modula-2 und "Uberarbeitung : M.Riedl, 23.11.93. *)
(*---------------------------------------------------------------*)
CONST MinLR = 3.834E-20;
MaxLR = 1.304E+19;
VAR i : CARDINAL;
S1,S2,S3,zw : LONGREAL;
Giant,AbsX,Max1,Max3 : LONGREAL;
Norm : LONGREAL;
BEGIN
S1:=0.0; S2:=0.0; S3:=0.0;
Max1:=0.0; Max3:=0.0;
Giant := MaxLR / VAL(LONGREAL,e-a+1);
FOR i:=a-1 TO e-1 DO
AbsX := ABS(X[i]);
IF (AbsX < MinLR) THEN (* Summiere kleine Elemente. *)
IF (AbsX > Max3) THEN
zw := Max3 / AbsX;
S3 := 1.0 + S3*(zw*zw);
Max3 := AbsX;
ELSE
IF (AbsX # 0.0) THEN zw := AbsX / Max3; S3:=S3 + zw*zw; END;
END;
ELSIF (AbsX > Giant) THEN (* Summiere gro\3e Elemente. *)
IF (AbsX > Max1) THEN
zw := Max1 / AbsX;
S1 := 1.0 + S1*(zw*zw);
Max1 := AbsX;
ELSE
zw := AbsX / Max1; S1:=S1 + zw*zw;
END;
ELSE (* Summiere mittlere Elemente. *)
S2 := S2 + AbsX*AbsX;
END;
END; (* FOR i *)
Norm:=0.0; (* Wg. XDS Compilerwarung, nicht noetig ! *)
IF (S1 # 0.0) THEN (* Berechne die Norm. *)
Norm := Max1*sqrt(S1 + (S2 / Max1) / Max1);
ELSE
IF (S2 # 0.0) THEN
IF (S2 >= Max3) THEN
Norm := sqrt(S2*(1.0 + (Max3 / S2)*(Max3*S3)));
END;
IF (S2 < Max3) THEN
Norm := sqrt(Max3*((S2 / Max3) + (Max3*S3)));
END;
ELSE
Norm := Max3*sqrt(S3);
END;
END;
RETURN Norm;
END ENorm;
PROCEDURE NormVek(VAR X : ARRAY OF LONGREAL;
dim : CARDINAL;
MaxNorm : BOOLEAN);
CONST klein = 32;
VAR i : CARDINAL;
Norm,Max : LONGREAL;
BEGIN
IF NOT MaxNorm THEN
Norm := ENorm(X,1,dim);
ELSE
IF (dim > klein) THEN
Max:=ABS(X[idamax(dim,X[0],1)-1]);
ELSE
Max:=ABS(X[0]);
FOR i:=1 TO dim-1 DO
IF (ABS(X[i]) > Max) THEN Max:=ABS(X[i]); END;
END;
END;
Norm := Max;
END;
IF (Norm > (100.0/MAX(LONGREAL))) THEN
Norm := 1.0 / Norm;
IF (dim > klein) THEN
dscal(dim,Norm,X[0],1);
ELSE
FOR i:=0 TO dim-1 DO X[i]:=Norm*X[i]; END;
END;
END;
END NormVek;
PROCEDURE NormMat(VAR A : ARRAY OF ARRAY OF LONGREAL;
dim : CARDINAL;
VekAnz : CARDINAL;
MaxNorm : BOOLEAN);
VAR i : CARDINAL;
BEGIN
FOR i:=0 TO VekAnz-1 DO
NormVek(A[i],dim,MaxNorm);
END;
END NormMat;
PROCEDURE CNormMat(VAR Mat : ARRAY OF ARRAY OF LONGCOMPLEX;
dim : CARDINAL;
VekAnz : CARDINAL;
MaxNorm: BOOLEAN);
VAR i,j : CARDINAL;
Norm,Sum,Max,abs : LONGREAL;
BEGIN
Norm:=0.0;
FOR i:=0 TO VekAnz-1 DO
IF MaxNorm THEN
Max:=0.0;
FOR j:=0 TO dim-1 DO
IF ABS(RE(Mat[i,j])) > Max THEN Max:=ABS(RE(Mat[i,j])); END;
IF ABS(RE(Mat[i,j])) > Max THEN Max:=ABS(RE(Mat[i,j])); END;
END;
IF (Max # 0.0) THEN Norm := 1.0 / Max; END;
ELSE (* Euklidische Norm. *)
Sum:=0.0;
FOR j:=0 TO dim-1 DO
abs := LongComplexMath.abs(Mat[i,j]); Sum:=Sum + abs*abs;
END;
IF (Sum # 0.0) THEN Norm := 1.0 / sqrt(Sum); END;
END; (* IF *)
IF (Norm # 0.0) THEN
FOR j:=0 TO dim-1 DO
Mat[i,j]:=LongComplexMath.scalarMult(Norm,Mat[i,j]);
END;
END;
END; (* FOR i *)
END CNormMat;
PROCEDURE MatSpur(VAR Spur : LONGREAL;
VAR MAT : MATRIX;
dim : CARDINAL);
VAR i :CARDINAL;
BEGIN
Spur:=0.0; FOR i:=1 TO dim DO Spur:=Spur + MAT[i,i]; END;
END MatSpur;
PROCEDURE SvSpur(VAR Spur : LONGREAL;
VAR SV : SUPERVEKTOR;
dim : CARDINAL);
VAR i,ii : CARDINAL;
BEGIN
Spur:=0.0; ii:=0;
FOR i:=1 TO dim DO INC(ii,i); Spur:=Spur+SV[ii]; END;
END SvSpur;
PROCEDURE MinMaxVek(VAR Min,Max : LONGREAL;
VAR Vek : ARRAY OF LONGREAL;
dim : CARDINAL;
Form : CARDINAL);
VAR i : CARDINAL;
BEGIN
Min:=Vek[0]; Max:=Vek[0];
IF (Form = 1) THEN
FOR i:=1 TO dim-1 DO
IF (ABS(Vek[i]) < ABS(Min)) THEN Min:=Vek[i]; END;
IF (ABS(Vek[i]) > ABS(Max)) THEN Max:=Vek[i]; END;
END;
ELSE
FOR i:=1 TO dim-1 DO
IF (Vek[i] < Min) THEN Min:=Vek[i]; END;
IF (Vek[i] > Max) THEN Max:=Vek[i]; END;
END;
END; (* IF Form *)
END MinMaxVek;
PROCEDURE MinMaxMat(VAR Min,Max : LONGREAL;
VAR Mat : MATRIX;
dim : CARDINAL; (* Dimension der Matrix *)
Form : CARDINAL);
VAR i,j : CARDINAL;
BEGIN
IF (Form > 5) THEN Form:=0; END;
CASE Form OF
0 : Min:=Mat[1,1]; Max:=Mat[1,1];
FOR i:=1 TO dim DO
FOR j:=1 TO dim DO
IF (Mat[i,j] > Max) THEN Max:=Mat[i,j]; END;
IF (Mat[i,j] < Min) THEN Min:=Mat[i,j]; END;
END;
END; |
1 : Min:=Mat[1,1]; Max:=Mat[1,1];
FOR i:=1 TO dim DO
FOR j:=1 TO dim DO
IF (ABS(Mat[i,j]) > ABS(Max)) THEN Max:=Mat[i,j]; END;
IF (ABS(Mat[i,j]) < ABS(Min)) THEN Min:=Mat[i,j]; END;
END;
END; |
2 : Min:=Mat[2,1]; Max:=Mat[2,1];
FOR i:=1 TO dim DO
FOR j:=1 TO i-1 DO
IF (Mat[i,j] > Max) THEN Max:=Mat[i,j]; END;
IF (Mat[i,j] < Min) THEN Min:=Mat[i,j]; END;
END;
FOR j:=i+1 TO dim DO
IF (Mat[i,j] > Max) THEN Max:=Mat[i,j]; END;
IF (Mat[i,j] < Min) THEN Min:=Mat[i,j]; END;
END;
END; |
3 : Min:=Mat[2,1]; Max:=Mat[2,1];
FOR i:=1 TO dim DO
FOR j:=1 TO i-1 DO
IF (ABS(Mat[i,j]) > ABS(Max)) THEN Max:=Mat[i,j]; END;
IF (ABS(Mat[i,j]) < ABS(Min)) THEN Min:=Mat[i,j]; END;
END;
FOR j:=i+1 TO dim DO
IF (ABS(Mat[i,j]) > ABS(Max)) THEN Max:=Mat[i,j]; END;
IF (ABS(Mat[i,j]) < ABS(Min)) THEN Min:=Mat[i,j]; END;
END;
END; |
4 : Min:=Mat[1,1]; Max:=Mat[1,1];
FOR i:=2 TO dim DO
IF (Mat[i,i] > Max) THEN Max:=Mat[i,i]; END;
IF (Mat[i,i] < Min) THEN Min:=Mat[i,i]; END;
END; |
5 : Min:=Mat[1,1]; Max:=Mat[1,1];
FOR i:=2 TO dim DO
IF (ABS(Mat[i,i]) > ABS(Max)) THEN Max:=Mat[i,i]; END;
IF (ABS(Mat[i,i]) < ABS(Min)) THEN Min:=Mat[i,i]; END;
END;
END; (* CASE *)
END MinMaxMat;
PROCEDURE MinMaxSv(VAR Min,Max : LONGREAL;
VAR SV : ARRAY OF LONGREAL; (* SUPERVEKTOR *)
dim : CARDINAL; (* Dimension der Matrix *)
Form : CARDINAL);
VAR i,j,ij,ii,SVdim : CARDINAL;
BEGIN
SVdim:=(dim*(dim+1) DIV 2) - 1;
IF (Form > 5) THEN Form:=0; END;
CASE Form OF
0 : Min:=SV[0]; Max:=SV[0];
FOR ij:=1 TO SVdim DO
IF (SV[ij] > Max) THEN Max:=SV[ij]; END;
IF (SV[ij] < Min) THEN Min:=SV[ij]; END;
END; |
1 : Min:=SV[0]; Max:=SV[0];
FOR ij:=1 TO SVdim DO
IF (ABS(SV[ij]) > ABS(Max)) THEN Max:=SV[ij]; END;
IF (ABS(SV[ij]) < ABS(Min)) THEN Min:=SV[ij]; END;
END; |
2 : Min:=SV[1]; Max:=SV[1]; ij:=0;
FOR i:=2 TO dim DO
FOR j:=1 TO i-1 DO
INC(ij);
IF (SV[ij] > Max) THEN Max:=SV[ij]; END;
IF (SV[ij] < Min) THEN Min:=SV[ij]; END;
END;
INC(ij);
END; |
3 : Min:=SV[1]; Max:=SV[1]; ij:=0;
FOR i:=2 TO dim DO
FOR j:=1 TO i-1 DO
INC(ij);
IF (ABS(SV[ij]) > ABS(Max)) THEN Max:=SV[ij]; END;
IF (ABS(SV[ij]) < ABS(Min)) THEN Min:=SV[ij]; END;
END;
INC(ij);
END; |
4 : Min:=SV[0]; Max:=SV[0]; ii:=0;
FOR i:=2 TO dim DO
INC(ii,i);
IF (SV[ii] > Max) THEN Max:=SV[ii]; END;
IF (SV[ii] < Min) THEN Min:=SV[ii]; END;
END; |
5 : Min:=SV[0]; Max:=SV[0]; ii:=0;
FOR i:=2 TO dim DO
INC(ii,i);
IF (ABS(SV[ii]) > ABS(Max)) THEN Max:=SV[ii]; END;
IF (ABS(SV[ii]) < ABS(Min)) THEN Min:=SV[ii]; END;
END;
END; (* CASE *)
END MinMaxSv;
PROCEDURE ZufallVec(VAR V : ARRAY OF LONGREAL;
dim : CARDINAL);
VAR i : CARDINAL;
BEGIN
IF (dim = 0) THEN RETURN; END;
IF (dim-1 > HIGH(V)) THEN
Errors.ErrOut('dim > HIGH(MAT) (MatLib.ZufallVec)');
RETURN;
END;
FOR i:=0 TO dim-1 DO V[i] := 1.0 - 2.0*Zufall(); END;
END ZufallVec;
PROCEDURE ZufallMat(VAR A : ARRAY OF ARRAY OF LONGREAL;
m,n : CARDINAL;
sym : BOOLEAN);
VAR i,j : CARDINAL;
x : LONGREAL;
BEGIN
Errors.Fehler:=FALSE;
IF (m = 0) AND (n = 0) THEN RETURN; END;
IF (m-1 > HIGH(A)) THEN
Errors.ErrOut('m > HIGH(A) (ZufallMat)');
Errors.Fehler:=TRUE;
RETURN;
END;
IF (n-1 > HIGH(A[0])) THEN
Errors.ErrOut('n > HIGH(A[0]) (ZufallMat)');
Errors.Fehler:=TRUE;
RETURN;
END;
IF sym AND (m # n) THEN
Errors.ErrOut('sym = wahr und m # n (ZufallMat)');
Errors.Fehler:=TRUE;
RETURN;
END;
(* InitZufall; *)
IF (m = 1) AND (n = 1) THEN A[0,0]:=1.0 - 2.0*Zufall(); RETURN; END;
IF sym THEN
FOR i:=0 TO n-1 DO
FOR j:=i+1 TO n-1 DO
x:=1.0 - 2.0*Zufall();
A[i,j]:=x; A[j,i]:=x;
END;
A[i,i]:= 1.0 - 2.0*Zufall();
END;
ELSE
FOR i:=0 TO m-1 DO
FOR j:=0 TO n-1 DO A[i,j] := 1.0 - 2.0*Zufall(); END;
END;
END;
END ZufallMat;
PROCEDURE ZufallSv(VAR SV : ARRAY OF LONGREAL; (* SUPERVEKTOR *)
dim : CARDINAL);
VAR i,j,ij : CARDINAL;
BEGIN
(* InitZufall; *)
ij:=0;
FOR i:=1 TO dim DO
FOR j:=1 TO i DO SV[ij]:=1.0 - 2.0*Zufall(); INC(ij); END;
END;
END ZufallSv;
PROCEDURE SumVek(VAR X : ARRAY OF LONGREAL;
a,e : CARDINAL) : LONGREAL;
VAR i : CARDINAL;
s,c,y,t : LONGREAL;
BEGIN
s := X[a-1];
c := 0.0;
FOR i:=a TO e-1 DO
y := X[i] - c;
t := s + y;
c := (t - s) - y;
s := t;
END;
RETURN s;
END SumVek;
PROCEDURE AbsSumVek(VAR X : ARRAY OF LONGREAL;
a,e : CARDINAL) : LONGREAL;
VAR i : CARDINAL;
s,c,y,t : LONGREAL;
BEGIN
s := ABS(X[a-1]);
c := 0.0;
FOR i:=a TO e-1 DO
y := ABS(X[i]) - c;
t := s + y;
c := (t - s) - y;
s := t;
END;
RETURN s;
END AbsSumVek;
PROCEDURE NeumaierSum(VAR X : ARRAY OF LONGREAL;
N : CARDINAL) : LONGREAL;
VAR sum,c,t : LONGREAL;
i : CARDINAL;
BEGIN
sum := X[0];
c := 0.0;
FOR i:=1 TO N-1 DO
t := sum + X[i];
IF (ABS(sum) >= ABS(X[i])) THEN
c:=c + (sum - t) + X[i];
ELSE
c:=c + (X[i] - t) + sum;
END;
sum := t;
END;
RETURN sum + c;
END NeumaierSum;
PROCEDURE NeumaierProdSum(VAR X,Y : ARRAY OF LONGREAL;
N : CARDINAL) : LONGREAL;
VAR sum,c,t,xy : LONGREAL;
i : CARDINAL;
BEGIN
sum := X[0]*Y[0];
c := 0.0;
FOR i:=1 TO N-1 DO
xy := X[i]*Y[i];
t := sum + xy;
IF (ABS(sum) >= ABS(xy)) THEN
c:=c + (sum - t) + xy;
ELSE
c:=c + (xy - t) + sum;
END;
sum := t;
END;
RETURN sum + c;
END NeumaierProdSum;
PROCEDURE SumVekUR(VAR X : ARRAY OF LONGREAL;
a,e : CARDINAL) : LONGREAL;
VAR i,mod,n : CARDINAL;
unrolled : BOOLEAN;
s : LONGREAL;
BEGIN
n:=e-a+1;
unrolled := n > 32;
IF NOT unrolled THEN
s:=X[a-1];
FOR i:=a TO e-1 DO s:=s + X[i]; END;
ELSE
s:=0.0;
mod := (n MOD 4);
IF (mod # 0) THEN
FOR i:=a-1 TO a+mod-2 DO s:=s + X[i]; END;
END;
FOR i:=a+mod-1 TO e-1 BY 4 DO
s:=s+ X[i] + X[i+1] + X[i+2] + X[i+3];
END;
END; (* IF unrolled *)
RETURN s;
END SumVekUR;
PROCEDURE AbsSumVekUR(VAR X : ARRAY OF LONGREAL;
a,e : CARDINAL) : LONGREAL;
VAR i,mod,n : CARDINAL;
unrolled : BOOLEAN;
s : LONGREAL;
BEGIN
n:=e-a+1;
unrolled := n > 32;
IF NOT unrolled THEN
s:=ABS(X[a-1]);
FOR i:=a TO e-1 DO s:=s + ABS(X[i]); END;
ELSE
s:=0.0;
mod := (n MOD 4);
IF (mod # 0) THEN
FOR i:=a-1 TO a+mod-2 DO s:=s + ABS(X[i]); END;
END;
FOR i:=a+mod-1 TO e-1 BY 4 DO
s:=s+ ABS(X[i]) + ABS(X[i+1]) + ABS(X[i+2]) + ABS(X[i+3]);
END;
END; (* IF unrolled *)
RETURN s;
END AbsSumVekUR;
END MatLib.