⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 complextype.pas

📁 Delphi math processing compononets and sources. Release.
💻 PAS
字号:
{
@abstract(EBK&NVS Pascal-Delphi Math Library: Complex Math Types and constants)
@author(Nikolai V. Shokhirev <nikolai@shokhirev.com> <nikolai@u.arizona.edu>)
@author(Eugene B. Krissinel <keb@ebi.ac.uk> <krissinel@fh.huji.ac.il>)
@created(02.02.1994)
@lastmod(04.04.2002)
This is a temporary publication (reduced variant), will be updated later
check: http://www.shokhirev.com/nikolai/programs/samplecode.html
㎞ikolai V. Shokhirev, 2002
}
unit ComplexType;

interface

uses
  MathTypes{, SpecFunc};
  
type

  Complex = record
              Re,Im: RealType;
            end;
{ The dimension in declarations can be of any value }
  CVector   =  array [1..999] of Complex;
  CVcPtr    =  ^CVector;
  CMatrix   =  array [1..999] of CVcPtr;
  CMtPtr    =  ^CMatrix;

procedure  GetCVectorMemory (var Vc: CVcPtr; N: integer );

procedure  FreeCVectorMemory(var Vc: CVcPtr; N: integer );

procedure  GetCMatrixMemory (var Mt: CMtPtr; M, N: integer );

procedure  FreeCMatrixMemory(var Mt: CMtPtr; M, N: integer );

{ Conversion functions for complex }

function CmplxToStr(z: complex): string;
function StrToCmplx(s: string): complex;

{ Basic functions for complex Calculations }

function cmplx(x: RealType; y: RealType = 0.0): complex; { result := x + i*y }
function Cabs (z: complex): RealType; { sqrt(sqr(Re)+sqr(Im))    }
function Cabs0(z: complex): RealType; { max(abs(z.re),abs(z.im)) }
function Cabs1(z: complex): RealType; { abs(z.Re) + abs(z.Im)    }
function Cabs2(z: complex): RealType; { sqr(z.Re)+ sqr(z.Im)     }
function Cneg(z: complex): complex; { result := -z }
function Cinv(z: complex): complex; { result := 1/z }
function conjug(z: complex): complex;  { result := z.Re -i*z.Im }
function Re(z: complex): RealType;  { result := z.Re }
function Im(z: complex): RealType;  { result := z.Im }
function Cunit(z: complex; var r: RealType): complex; { result := z/r r := Cabs (z) }
function Cadd(z: complex;  w: complex): complex; overload; { result := z + w }
function Cadd(z: complex;  x: RealType): complex; overload;
function Cadd(x: RealType; w: complex): complex; overload;
function Csub(z: complex;  w: complex): complex; overload; { result := z - w }
function Csub(z: complex;  x: RealType): complex; overload;
function Csub(x: RealType; w: complex): complex; overload;
function Cmul(z: complex;  w: complex): complex; overload; { result := z * w }
function Cmul(x: RealType; w: complex): complex; overload;
function Cmul(z: complex;  x: RealType): complex; overload;
function Cdiv(z: complex;  w: complex): complex; overload; { result := z / w }
function Cdiv(x: RealType; w: complex): complex; overload;
function Cdiv(z: complex;  x: RealType): complex; overload;
function Cexp(z: complex): complex;         { z := exp(v)  }
function Csqrt(z: complex): complex;        { result := sqrt(z), result.Re > 0 }
function Croot(x: RealType): complex;        { result := sqrt(x) }
procedure Csum(var s: complex; z: complex); overload; { s := s + z }
procedure Csum(var s: complex; x: RealType); overload; { s := s + x }

{ Special functions for Complex Calculations }

function cer(z: complex): complex; { result := er(z) }

const
  Cmplx1: complex = (Re: 1.0; Im: 0.0);  // cmplx(1.0, 0.0)
  Cmplx0: complex = (Re: 0.0; Im: 0.0);  // cmplx(0.0, 0.0)

{ ===================================================================== }

implementation

uses
  SpecFunc, sysutils, Dialogs;

var
  S: pointer;

procedure  GetCVectorMemory(  var  Vc: CVcPtr;  N : integer );
begin
  GetMem( S, N*SizeOf(complex) );
  Vc := S;
end;

procedure  FreeCVectorMemory(  var  Vc: CVcPtr;  N : integer );
begin
  S := Vc;
  FreeMem( S, N*SizeOf(complex) );
  Vc := nil;
end;

procedure  GetCMatrixMemory(  var  Mt: CMtPtr;  M,N : integer );
var  i : integer;
begin
  GetMem( S, SizeOf(CVcPtr)*M );
  Mt := S;
  for i:=1 to M  do
    begin
      GetMem( S, SizeOf(complex)*N );
      Mt^[i] := S;
    end;
end;

procedure  FreeCMatrixMemory(  var  Mt: CMtPtr;  M,N : integer );
var  i : integer;
begin
  for i:=M downto 1  do
    begin
      S := Mt^[i];
      FreeMem( S, SizeOf(complex)*N );
    end;
  S := Mt;
  FreeMem( S, SizeOf(CVcPtr)*M );
  Mt := nil;
end;

{ Conversion functions for complex }

function CmplxToStr(z: complex): string;
var
  s: string;
begin
  if z.Im = 0.0 then
    result := FloatToStr(z.Re)
  else
  begin
    if z.Im > 0 then s := ' + i*' else s := ' - i*';
    result := FloatToStr(z.Re)+s+FloatToStr(abs(z.Im));
  end;
end;

function StrToCmplx(s: string): complex;
//  2.2 + i*1.1
// +2.2 - I*1.1
// -2.2 + j 1.1
//  2.2 + J*1.1
var
  r, i, ss: string;
  n: IntType;
  sig: RealType;
begin
  ss := StringReplace(s, ' ', '', [rfReplaceAll, rfIgnoreCase]);
//  L := Length(ss);
  n := Pos('i',ss);
  if n = 0 then n := Pos('I',ss);
  if n = 0 then n := Pos('j',ss);
  if n = 0 then n := Pos('J',ss);
  if n = 0 then // real
  begin
    r := ss;
    i := '';
  end else
  begin
    case n of
    1: begin // imaginary
         sig := 1.0;
         r := '';
         if ss[n+1] = '*' then i := copy(ss, n+2,512)
         else i := copy(ss, n+1,512);
       end;
    2: begin // imaginary
         r := '';
         if ss[1] = '-' then sig := -1.0 else sig := 1.0;
         if ss[n+1] = '*' then i := copy(ss, n+2,512)
         else i := copy(ss, n+1,512);
       end;
    else
      sig := 1.0;
      if ss[n-1] = '-' then
      begin
        sig := -1.0;
        r := copy(ss, 1, n-2);
      end else
        if ss[n-1] = '+' then
          r := copy(ss, 1, n-2)
        else // no sign = +
          r := copy(ss, 1, n-1);
      if n = Length(ss) then i := '1.0' else
        if ss[n+1] = '*' then i := copy(ss, n+2,512)
        else i := copy(ss, n+1,512);
    end;
  end;

  if r ='' then
    result.Re := 0.0
  else
    result.Re := StrToFloat(r);
    
  if i ='' then
    result.Im := 0.0 
  else
    result.Im := sig*StrToFloat(i);
end;

{ Basic functions for complex Calculations }

function cmplx(x: RealType; y: RealType = 0.0): complex;
{ result := x + i*y }
begin
  result.Re := x;
  result.Im := y;
end;

function Cabs (z: complex ): RealType;
{ sqrt(sqr(Re)+sqr(Im)) }
begin
  result := sqroot2(z.Re, z.Im);
end;

function Cabs0(z: complex): RealType;
{ max(abs(z.re),abs(z.im)) }
begin
  if (abs(z.re)>abs(z.im))
  then result := abs(z.re) else result := abs(z.im);
end;

function Cabs1(z: complex ): RealType;
{ abs(z.Re) + abs(z.Im)    }
begin
  result := abs(z.re) + abs(z.im);
end;

function Cabs2(z: complex ): RealType;
{ sqr(z.Re)+ sqr(z.Im)     }
begin
  result := sqr(z.re) + sqr(z.im);
end;

function Re(z: complex):RealType;
begin
  result := z.re;
end;

function Im(z: complex):RealType;
begin
  result := z.im;
end;

function Cneg(z: complex): complex;
{ result := -z }
begin
  result.Re := -z.Re;
  result.Im := -z.Im;
end;

function Cinv(z: complex): complex;
{ result := 1/z }
var
  r: RealType;
begin
  if Cabs0(z) > MinReal then
  begin
    r := Cabs2(z);
    result.Re :=  z.Re/r;
    result.Im := -z.Im/r;
  end else
  begin
    result.Re :=  sign(z.Re)*MaxReal;
    result.Im := -sign(z.Im)*MaxReal;
  end;
end;

function conjug(z: complex): complex;
{ result := z.Re -i*z.Im }
begin
  result.Re :=  z.Re;
  result.Im := -z.Im;
end;

function Cunit(z: complex; var r: RealType): complex;
{ result := z/r r := Cabs (z) }
begin
  r := Cabs(z);
  if r > MinReal then
  begin
    result.Re := z.Re/r;
    result.Im := z.Im/r;
  end else
  begin
    r := 0.0;
    result.Re := 0.0;
    result.Im := 0.0;
  end;
end;

function Cadd(z: complex;  w: complex): complex;
{ result := z + w }
begin
  result.Re :=  z.Re + w.Re;
  result.Im :=  z.Im + w.Im;
end;

function Cadd(z: complex;  x: RealType): complex;
begin
  result.Re :=  z.Re + x;
  result.Im :=  z.Im;
end;

function Cadd(x: RealType; w: complex): complex;
begin
  result.Re :=  w.Re + x;
  result.Im :=  w.Im;
end;

function Csub(z: complex;  w: complex): complex;
{ result := z - w }
begin
  result.Re :=  z.Re - w.Re;
  result.Im :=  z.Im - w.Im;
end;

function Csub(z: complex;  x: RealType): complex;
begin
  result.Re :=  z.Re - x;
  result.Im :=  z.Im;
end;

function Csub(x: RealType; w: complex): complex;
begin
  result.Re :=  x - w.Re;
  result.Im :=    - w.Im;
end;

function Cmul(z: complex;  w: complex): complex;
{ result := z * w }
begin
  result.Re :=  z.Re*w.Re - z.Im*w.Im;
  result.Im :=  z.Im*w.Re + z.Re*w.Im;
end;

function Cmul(x: RealType; w: complex): complex;
begin
  result.Re :=  x*w.Re;
  result.Im :=  x*w.Im;
end;

function Cmul(z: complex;  x: RealType): complex;
begin
  result.Re :=  z.Re*x;
  result.Im :=  z.Im*x;
end;

function Cdiv(z: complex;  w: complex): complex;
{ result := z / w }
var
  rz, rw: RealType;
  zu, wu: complex;
begin
  wu := Cunit(w, rw);
  if rw > MinReal then
  begin
    zu := Cunit(z, rz);
    try
      result := Cmul(Cmul(zu, conjug(wu)),rz/rw);
    except
      on E:Exception do
        ShowMessage(Format('Complex division Error: %s',[E.Message]));
    end;
  end;
end;

function Cdiv(x: RealType; w: complex): complex;
var
  rw: RealType;
  wu: complex;
begin
  wu := Cunit(w, rw);
  if rw > MinReal then
  begin
    try
      result := Cmul(x/rw, conjug(wu));
    except
      on E:Exception do
        ShowMessage(Format('Complex division Error: %s',[E.Message]));
    end;
  end;
end;

function Cdiv(z: complex;  x: RealType): complex;
begin
  try
    result.Re :=  z.Re/x;
    result.Im :=  z.Im/x;
  except
    on E:Exception do
      ShowMessage(Format('Complex division Error: %s',[E.Message]));
  end;
end;

function Cexp(z: complex): complex;
{ z := exp(v)  }
begin
  result.Re := exp1(z.re)*cos(z.im);
  result.Im := exp1(z.re)*sin(z.im);
end;

function Csqrt(z: complex): complex;
{ result := sqrt(z), result.Re > 0 }
begin
  result.Re :=  sqrt(abs(0.5*(Cabs(z) + z.re)));
  result.Im :=  sqrt(abs(0.5*(Cabs(z) - z.re)));
end;

function Croot(x: RealType): complex;
{ result := sqrt(x) }
begin
  if x < 0.0 then result := cmplx(0.0, sqrt(-x))
             else result := cmplx(sqrt(x));
end;

procedure Csum(var s: complex; z: complex);
{ s := s + z }
begin
  s := Cadd(s, z);
end;
procedure Csum(var s: complex; x: RealType);
{ s := s + x }
begin
  s := Cadd(s, x);
end;

{ Special functions for Complex Calculations }

function cer(z: complex): complex;
{ result := er(z) }

  function cerser(z: complex): complex;
  { series expansion of er(z) }
  const
    epsilon = 1.0E-14;
         sp = 1.7724538509055160;{ sqrt(pi) }
  var
    s, t, m, zz, zz2: complex;
  begin
    m := cmplx1;
    t := cmplx1;
    s := cmplx0;
    zz := Cmul(z, z);
    zz2 := Cmul(zz, 2.0);
    repeat
      Csum(s, t);
      Csum(m, 2.0);
      t := Cmul(t, zz2);
      t := Cdiv(t, m);
    until (Cabs0(t) < epsilon);
    s := Cmul(s, z);
    s := Cmul(s, 2.0/sp);
    t := Cexp(zz);
    result := Csub(t, s);
  end;

  function cerabr(z: complex): complex;
  { approximation of er(z): asimptotics from Abramowitz }
  const
    a1 = 0.4613135;    b1 = 0.1901635;
    a2 = 0.09999216;   b2 = 1.7844927;
    a3 = 0.002883894;  b3 = 5.5253437;
  var
    u, v, zz                : complex;
  begin
    zz := Cmul(z, z);
    u := Cadd(zz, b1);    v := Cdiv(a1, u);
    u := Cadd(zz, b2);    u := Cdiv(a2, u);
    Csum(v, u);
    u := Cadd(zz, b3);    u := Cdiv(a3, u);
    Csum(v, u);
    result := Cmul(v, z);
  end;

begin
  if (abs(z.re) > 3.0) or (abs(z.im) > 3.9)
     then result := cerabr(z)
     else result := cerser(z);
end;{ of cer }

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -