📄 testrcondldltunit.pas
字号:
end
else
begin
V := 0;
end;
if NOUNIT then
begin
A[I,J] := V+A[I,I]*T[I];
end
else
begin
A[I,J] := V+T[I];
end;
Inc(I);
end;
for i_ := 0 to J-1 do
begin
A[i_,J] := AJJ*A[i_,J];
end;
end;
Inc(J);
end;
end
else
begin
//
// Compute inverse of lower triangular matrix.
//
J:=N-1;
while J>=0 do
begin
if NOUNIT then
begin
if A[J,J]=0 then
begin
Result := False;
Exit;
end;
A[J,J] := 1/A[J,J];
AJJ := -A[J,J];
end
else
begin
AJJ := -1;
end;
if J<N-1 then
begin
//
// Compute elements j+1:n of j-th column.
//
for i_ := J+1 to N-1 do
begin
T[i_] := A[i_,J];
end;
I:=J+1;
while I<=N-1 do
begin
if I>J+1 then
begin
V := APVDotProduct(@A[I][0], J+1, I-1, @T[0], J+1, I-1);
end
else
begin
V := 0;
end;
if NOUNIT then
begin
A[I,J] := V+A[I,I]*T[I];
end
else
begin
A[I,J] := V+T[I];
end;
Inc(I);
end;
for i_ := J+1 to N-1 do
begin
A[i_,J] := AJJ*A[i_,J];
end;
end;
Dec(J);
end;
end;
end;
(*************************************************************************
LU inverse
*************************************************************************)
function InvMatLU(var A : TReal2DArray;
const Pivots : TInteger1DArray;
N : Integer):Boolean;
var
WORK : TReal1DArray;
I : Integer;
IWS : Integer;
J : Integer;
JB : Integer;
JJ : Integer;
JP : Integer;
V : Double;
i_ : Integer;
begin
Result := True;
//
// Quick return if possible
//
if N=0 then
begin
Exit;
end;
SetLength(WORK, N-1+1);
//
// Form inv(U)
//
if not InvMatTR(A, N, True, False) then
begin
Result := False;
Exit;
end;
//
// Solve the equation inv(A)*L = inv(U) for inv(A).
//
J:=N-1;
while J>=0 do
begin
//
// Copy current column of L to WORK and replace with zeros.
//
I:=J+1;
while I<=N-1 do
begin
WORK[I] := A[I,J];
A[I,J] := 0;
Inc(I);
end;
//
// Compute current column of inv(A).
//
if J<N-1 then
begin
I:=0;
while I<=N-1 do
begin
V := APVDotProduct(@A[I][0], J+1, N-1, @WORK[0], J+1, N-1);
A[I,J] := A[I,J]-V;
Inc(I);
end;
end;
Dec(J);
end;
//
// Apply column interchanges.
//
J:=N-2;
while J>=0 do
begin
JP := Pivots[J];
if JP<>J then
begin
for i_ := 0 to N-1 do
begin
WORK[i_] := A[i_,J];
end;
for i_ := 0 to N-1 do
begin
A[i_,J] := A[i_,JP];
end;
for i_ := 0 to N-1 do
begin
A[i_,JP] := WORK[i_];
end;
end;
Dec(J);
end;
end;
(*************************************************************************
LU decomposition
*************************************************************************)
procedure MatLU(var A : TReal2DArray;
M : Integer;
N : Integer;
var Pivots : TInteger1DArray);
var
I : Integer;
J : Integer;
JP : Integer;
T1 : TReal1DArray;
s : Double;
i_ : Integer;
begin
SetLength(Pivots, Min(M-1, N-1)+1);
SetLength(T1, Max(M-1, N-1)+1);
Assert((M>=0) and (N>=0), 'Error in LUDecomposition: incorrect function arguments');
//
// Quick return if possible
//
if (M=0) or (N=0) then
begin
Exit;
end;
J:=0;
while J<=Min(M-1, N-1) do
begin
//
// Find pivot and test for singularity.
//
JP := J;
I:=J+1;
while I<=M-1 do
begin
if AbsReal(A[I,J])>AbsReal(A[JP,J]) then
begin
JP := I;
end;
Inc(I);
end;
Pivots[J] := JP;
if A[JP,J]<>0 then
begin
//
//Apply the interchange to rows
//
if JP<>J then
begin
APVMove(@T1[0], 0, N-1, @A[J][0], 0, N-1);
APVMove(@A[J][0], 0, N-1, @A[JP][0], 0, N-1);
APVMove(@A[JP][0], 0, N-1, @T1[0], 0, N-1);
end;
//
//Compute elements J+1:M of J-th column.
//
if J<M then
begin
JP := J+1;
S := 1/A[J,J];
for i_ := JP to M-1 do
begin
A[i_,J] := S*A[i_,J];
end;
end;
end;
if J<Min(M, N)-1 then
begin
//
//Update trailing submatrix.
//
JP := J+1;
I:=J+1;
while I<=M-1 do
begin
S := A[I,J];
APVSub(@A[I][0], JP, N-1, @A[J][0], JP, N-1, S);
Inc(I);
end;
end;
Inc(J);
end;
end;
(*************************************************************************
Matrix inverse
*************************************************************************)
function InvMat(var A : TReal2DArray; N : Integer):Boolean;
var
Pivots : TInteger1DArray;
begin
MatLU(A, N, N, Pivots);
Result := InvMatLU(A, Pivots, N);
end;
(*************************************************************************
reference RCond
*************************************************************************)
procedure RefRCond(const A : TReal2DArray;
N : Integer;
var RC1 : Double;
var RCInf : Double);
var
InvA : TReal2DArray;
Nrm1A : Double;
NrmInfA : Double;
Nrm1InvA : Double;
NrmInfInvA : Double;
V : Double;
K : Integer;
I : Integer;
begin
//
// inv A
//
MakeACopy(A, N, N, InvA);
if not InvMat(InvA, N) then
begin
RC1 := 0;
RCInf := 0;
Exit;
end;
//
// norm A
//
Nrm1A := 0;
NrmInfA := 0;
K:=0;
while K<=N-1 do
begin
V := 0;
I:=0;
while I<=N-1 do
begin
V := V+AbsReal(A[I,K]);
Inc(I);
end;
Nrm1A := Max(Nrm1A, V);
V := 0;
I:=0;
while I<=N-1 do
begin
V := V+AbsReal(A[K,I]);
Inc(I);
end;
NrmInfA := Max(NrmInfA, V);
Inc(K);
end;
//
// norm inv A
//
Nrm1InvA := 0;
NrmInfInvA := 0;
K:=0;
while K<=N-1 do
begin
V := 0;
I:=0;
while I<=N-1 do
begin
V := V+AbsReal(InvA[I,K]);
Inc(I);
end;
Nrm1InvA := Max(Nrm1InvA, V);
V := 0;
I:=0;
while I<=N-1 do
begin
V := V+AbsReal(InvA[K,I]);
Inc(I);
end;
NrmInfInvA := Max(NrmInfInvA, V);
Inc(K);
end;
//
// result
//
RC1 := 1.0/(Nrm1InvA*Nrm1A);
RCInf := 1.0/(NrmInfInvA*NrmInfA);
end;
(*************************************************************************
Silent unit test
*************************************************************************)
function testrcondldltunit_test_silent():Boolean;
begin
Result := TestRCondLDLT(True);
end;
(*************************************************************************
Unit test
*************************************************************************)
function testrcondldltunit_test():Boolean;
begin
Result := TestRCondLDLT(False);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -