📄 testcrcondunit.pas
字号:
unit testcrcondunit;
interface
uses Math, Ap, Sysutils, clu, ctrlinsolve, crcond;
function TestCRCond(Silent : Boolean):Boolean;
function testcrcondunit_test_silent():Boolean;
function testcrcondunit_test():Boolean;
implementation
procedure MakeACopy(const A : TComplex2DArray;
M : Integer;
N : Integer;
var B : TComplex2DArray);forward;
procedure GenerateRandomMatrix(var A0 : TComplex2DArray; N : Integer);forward;
function InvMatTR(var A : TComplex2DArray;
N : Integer;
IsUpper : Boolean;
IsUnitTriangular : Boolean):Boolean;forward;
function InvMatLU(var A : TComplex2DArray;
const Pivots : TInteger1DArray;
N : Integer):Boolean;forward;
function InvMat(var A : TComplex2DArray; N : Integer):Boolean;forward;
procedure RefRCond(const A : TComplex2DArray;
N : Integer;
var RC1 : Double;
var RCInf : Double);forward;
function TestCRCond(Silent : Boolean):Boolean;
var
A : TComplex2DArray;
LUA : TComplex2DArray;
P : TInteger1DArray;
N : Integer;
MaxN : Integer;
I : Integer;
J : Integer;
Pass : Integer;
PassCount : Integer;
WasErrors : Boolean;
Err50 : Boolean;
Err90 : Boolean;
ErrLess : Boolean;
ERC1 : Double;
ERCInf : Double;
Q50 : TReal1DArray;
Q90 : TReal1DArray;
V : Double;
Threshold50 : Double;
Threshold90 : Double;
begin
WasErrors := False;
Err50 := False;
Err90 := False;
ErrLess := False;
MaxN := 10;
PassCount := 100;
Threshold50 := 0.5;
Threshold90 := 0.1;
SetLength(Q50, 3+1);
SetLength(Q90, 3+1);
//
// process
//
N:=1;
while N<=MaxN do
begin
SetLength(A, N-1+1, N-1+1);
I:=0;
while I<=3 do
begin
Q50[I] := 0;
Q90[I] := 0;
Inc(I);
end;
Pass:=1;
while Pass<=PassCount do
begin
GenerateRandomMatrix(A, N);
MakeACopy(A, N, N, LUA);
CMatrixLU(LUA, N, N, P);
RefRCond(A, N, ERC1, ERCInf);
//
// 1-norm, normal
//
V := 1/CMatrixRCond1(A, N);
if V>=Threshold50*ERC1 then
begin
Q50[0] := Q50[0]+1/PassCount;
end;
if V>=Threshold90*ERC1 then
begin
Q90[0] := Q90[0]+1/PassCount;
end;
ErrLess := ErrLess or (V>ERC1*1.001);
//
// 1-norm, LU
//
V := 1/CMatrixLURCond1(LUA, N);
if V>=Threshold50*ERC1 then
begin
Q50[1] := Q50[1]+1/PassCount;
end;
if V>=Threshold90*ERC1 then
begin
Q90[1] := Q90[1]+1/PassCount;
end;
ErrLess := ErrLess or (V>ERC1*1.001);
//
// Inf-norm, normal
//
V := 1/CMatrixRCondInf(A, N);
if V>=Threshold50*ERCInf then
begin
Q50[2] := Q50[2]+1/PassCount;
end;
if V>=Threshold90*ERCInf then
begin
Q90[2] := Q90[2]+1/PassCount;
end;
ErrLess := ErrLess or (V>ERCInf*1.001);
//
// Inf-norm, LU
//
V := 1/CMatrixLURCondInf(LUA, N);
if V>=Threshold50*ERCInf then
begin
Q50[3] := Q50[3]+1/PassCount;
end;
if V>=Threshold90*ERCInf then
begin
Q90[3] := Q90[3]+1/PassCount;
end;
ErrLess := ErrLess or (V>ERCInf*1.001);
Inc(Pass);
end;
I:=0;
while I<=3 do
begin
Err50 := Err50 or (Q50[I]<0.50);
Err90 := Err90 or (Q90[I]<0.90);
Inc(I);
end;
Inc(N);
end;
//
// report
//
WasErrors := Err50 or Err90 or ErrLess;
if not Silent then
begin
Write(Format('TESTING RCOND (COMPLEX)'#13#10'',[]));
Write(Format('50%% within [0.5*cond,cond]: ',[]));
if Err50 or ErrLess then
begin
Write(Format('FAILED'#13#10'',[]));
end
else
begin
Write(Format('OK'#13#10'',[]));
end;
Write(Format('90%% within [0.1*cond,cond] ',[]));
if Err90 or ErrLess then
begin
Write(Format('FAILED'#13#10'',[]));
end
else
begin
Write(Format('OK'#13#10'',[]));
end;
if WasErrors then
begin
Write(Format('TEST FAILED'#13#10'',[]));
end
else
begin
Write(Format('TEST PASSED'#13#10'',[]));
end;
Write(Format(''#13#10''#13#10'',[]));
end;
Result := not WasErrors;
end;
(*************************************************************************
Copy
*************************************************************************)
procedure MakeACopy(const A : TComplex2DArray;
M : Integer;
N : Integer;
var B : TComplex2DArray);
var
I : Integer;
J : Integer;
begin
SetLength(B, M-1+1, N-1+1);
I:=0;
while I<=M-1 do
begin
J:=0;
while J<=N-1 do
begin
B[I,J] := A[I,J];
Inc(J);
end;
Inc(I);
end;
end;
(*************************************************************************
Generate matrix with given condition number C (2-norm)
*************************************************************************)
procedure GenerateRandomMatrix(var A0 : TComplex2DArray; N : Integer);
var
I : Integer;
J : Integer;
begin
I:=0;
while I<=N-1 do
begin
J:=0;
while J<=N-1 do
begin
A0[I,J].X := 2*RandomReal-1;
A0[I,J].Y := 2*RandomReal-1;
Inc(J);
end;
Inc(I);
end;
end;
(*************************************************************************
triangular inverse
*************************************************************************)
function InvMatTR(var A : TComplex2DArray;
N : Integer;
IsUpper : Boolean;
IsUnitTriangular : Boolean):Boolean;
var
NOUNIT : Boolean;
I : Integer;
J : Integer;
V : Complex;
AJJ : Complex;
T : TComplex1DArray;
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 C_EqualR(A[J,J],0) then
begin
Result := False;
Exit;
end;
A[J,J] := C_RDiv(1,A[J,J]);
AJJ := C_Opposite(A[J,J]);
end
else
begin
AJJ := C_Complex(-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 := C_Complex(0.0);
for i_ := I+1 to J-1 do
begin
V := C_Add(V,C_Mul(A[I,i_],T[i_]));
end;
end
else
begin
V := C_Complex(0);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -