📄 testrcondunit.pas
字号:
T := V[I]*Lambda;
APVSub(@A[I][0], 1, N, @W[0], 1, N, T);
Inc(I);
end;
Inc(S);
end;
//
//
//
I:=1;
while I<=N do
begin
J:=1;
while J<=N do
begin
A0[I-1,J-1] := A[I,J];
Inc(J);
end;
Inc(I);
end;
end;
(*************************************************************************
triangular inverse
*************************************************************************)
function InvMatTR(var A : TReal2DArray;
N : Integer;
IsUpper : Boolean;
IsUnitTriangular : Boolean):Boolean;
var
NOUNIT : Boolean;
I : Integer;
J : Integer;
V : Double;
AJJ : Double;
T : TReal1DArray;
i_ : Integer;
begin
Result := True;
SetLength(T, N-1+1);
//
// Test the input parameters.
//
NOUNIT := not IsUnitTriangular;
if IsUpper then
begin
//
// Compute inverse of upper triangular matrix.
//
J:=0;
while J<=N-1 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;
//
// Compute elements 1:j-1 of j-th column.
//
if J>0 then
begin
for i_ := 0 to J-1 do
begin
T[i_] := A[i_,J];
end;
I:=0;
while I<=J-1 do
begin
if I<J-1 then
begin
V := APVDotProduct(@A[I][0], I+1, J-1, @T[0], I+1, J-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_ := 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;
(*************************************************************************
Matrix inverse
*************************************************************************)
function InvMat(var A : TReal2DArray; N : Integer):Boolean;
var
Pivots : TInteger1DArray;
begin
RMatrixLU(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 := Nrm1InvA*Nrm1A;
RCInf := NrmInfInvA*NrmInfA;
end;
(*************************************************************************
Silent unit test
*************************************************************************)
function testrcondunit_test_silent():Boolean;
begin
Result := TestRCond(True);
end;
(*************************************************************************
Unit test
*************************************************************************)
function testrcondunit_test():Boolean;
begin
Result := TestRCond(False);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -