mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-18 07:06:39 +02:00
578 lines
15 KiB
ObjectPascal
578 lines
15 KiB
ObjectPascal
{
|
|
$Id$
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 1993,97 by Pierre Muller,
|
|
member of the Free Pascal development team.
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
Unit COMPLEX;
|
|
|
|
(* Bibliotheque mathematique pour type complexe *)
|
|
(* Version a fonctions et pointeurs *)
|
|
(* JD GAYRARD mai 95 *)
|
|
|
|
(* modified for FPK by Pierre Muller *)
|
|
(* FPK supports operator overloading *)
|
|
(* This library is based on functions instead of procedures.
|
|
To allow a function to return complex type, the trick is
|
|
is to use a pointer on the result of the function. All
|
|
functions are of Pcomplex type (^complexe).
|
|
In the main program the function computation is accessed
|
|
by z := function_name(param1, param2)^ *)
|
|
|
|
{$G+}
|
|
{$N+}
|
|
{$E-}
|
|
|
|
interface
|
|
|
|
uses MATHLIB, HYPERBOL;
|
|
|
|
const author = 'GAYRARD J-D';
|
|
version = 'ver 0.0 - 05/95';
|
|
|
|
type complex = record
|
|
re : real;
|
|
im : real;
|
|
end;
|
|
|
|
pcomplex = ^complex;
|
|
|
|
const _i : complex = (re : 0.0; im : 1.0);
|
|
_0 : complex = (re : 0.0; im : 0.0);
|
|
|
|
|
|
(* quatre operations : +, -, * , / and = *)
|
|
operator + (z1, z2 : complex) z : complex; (* addition *)
|
|
{ assignment overloading is not implement }
|
|
{ if it was the next two would not be unnecessary }
|
|
operator + (z1 : complex; r : real) z : complex; (* addition *)
|
|
operator + (r : real; z1 : complex) z : complex; (* addition *)
|
|
|
|
operator - (z1, z2 : complex) z : complex; (* soustraction *)
|
|
operator - (z1 : complex;r : real) z : complex; (* soustraction *)
|
|
operator - (r : real; z1 : complex) z : complex; (* soustraction *)
|
|
|
|
operator * (z1, z2 : complex) z : complex; (* multiplication *)
|
|
operator * (z1 : complex; r : real) z : complex; (* multiplication *)
|
|
operator * (r : real; z1 : complex) z : complex; (* multiplication *)
|
|
|
|
operator / (znum, zden : complex) z : complex; (* division znum / zden *)
|
|
operator / (znum : complex; r : real) z : complex; (* division znum / r *)
|
|
operator / (r : real; zden : complex) z : complex; (* division r / zden *)
|
|
|
|
{ ^ is not built in FPK, but can be overloaded also }
|
|
operator ^ (r1, r2 : real) r : real;
|
|
operator ^ (z1, z2 : complex) z : complex;
|
|
operator ^ (z1 : complex; r2 : real) z : complex;
|
|
operator ^ (r : real; z1 : complex) z : complex;
|
|
|
|
operator = (z1, z2 : complex) b : boolean;
|
|
operator = (z1 : complex;r : real) b : boolean;
|
|
operator = (r : real; z1 : complex) b : boolean;
|
|
|
|
(* fonctions complexes particulieres *)
|
|
function cneg (z : complex) : complex; (* negatif *)
|
|
function ccong (z : complex) : complex; (* conjuge *)
|
|
function crcp (z : complex) : complex; (* inverse *)
|
|
function ciz (z : complex) : complex; (* multiplication par i *)
|
|
function c_iz (z : complex) : complex; (* multiplication par -i *)
|
|
function czero : complex; (* return zero *)
|
|
|
|
(* fonctions complexes a retour non complex *)
|
|
function cmod (z : complex) : real; (* module *)
|
|
function cequal (z1, z2 : complex) : boolean; (* compare deux complexes *)
|
|
function carg (z : complex) : real; (* argument : a / z = p.e^ia *)
|
|
|
|
(* fonctions elementaires *)
|
|
function cexp (z : complex) : complex; (* exponantielle *)
|
|
function cln (z : complex) : complex; (* logarithme naturel *)
|
|
function csqrt (z : complex) : complex; (* racine carre *)
|
|
|
|
(* fonctions trigonometrique directe *)
|
|
function ccos (z : complex) : complex; (* cosinus *)
|
|
function csin (z : complex) : complex; (* sinus *)
|
|
function ctg (z : complex) : complex; (* tangente *)
|
|
|
|
(* fonctions trigonometriques inverses *)
|
|
function carc_cos (z : complex) : complex; (* arc cosinus *)
|
|
function carc_sin (z : complex) : complex; (* arc sinus *)
|
|
function carc_tg (z : complex) : complex; (* arc tangente *)
|
|
|
|
(* fonctions trigonometrique hyperbolique *)
|
|
function cch (z : complex) : complex; (* cosinus hyperbolique *)
|
|
function csh (z : complex) : complex; (* sinus hyperbolique *)
|
|
function cth (z : complex) : complex; (* tangente hyperbolique *)
|
|
|
|
(* fonctions trigonometrique hyperbolique inverse *)
|
|
function carg_ch (z : complex) : complex; (* arc cosinus hyperbolique *)
|
|
function carg_sh (z : complex) : complex; (* arc sinus hyperbolique *)
|
|
function carg_th (z : complex) : complex; (* arc tangente hyperbolique *)
|
|
|
|
|
|
|
|
implementation
|
|
|
|
(* quatre operations de base +, -, * , / *)
|
|
|
|
operator + (z1, z2 : complex) z : complex;
|
|
(* addition : z := z1 + z2 *)
|
|
begin
|
|
z.re := z1.re + z2.re;
|
|
z.im := z1.im + z2.im;
|
|
end;
|
|
|
|
operator + (z1 : complex; r : real) z : complex;
|
|
(* addition : z := z1 + r *)
|
|
begin
|
|
z.re := z1.re + r;
|
|
z.im := z1.im;
|
|
end;
|
|
|
|
operator + (r : real; z1 : complex) z : complex;
|
|
(* addition : z := r + z1 *)
|
|
begin
|
|
z.re := z1.re + r;
|
|
z.im := z1.im;
|
|
end;
|
|
|
|
operator - (z1, z2 : complex) z : complex;
|
|
(* substraction : z := z1 - z2 *)
|
|
begin
|
|
z.re := z1.re - z2.re;
|
|
z.im := z1.im - z2.im;
|
|
end;
|
|
|
|
operator - (z1 : complex; r : real) z : complex;
|
|
(* substraction : z := z1 - r *)
|
|
begin
|
|
z.re := z1.re - r;
|
|
z.im := z1.im;
|
|
end;
|
|
|
|
operator - (r : real; z1 : complex) z : complex;
|
|
(* substraction : z := r + z1 *)
|
|
begin
|
|
z.re := r - z1.re;
|
|
z.im := - z1.im;
|
|
end;
|
|
|
|
operator * (z1, z2 : complex) z : complex;
|
|
(* multiplication : z := z1 * z2 *)
|
|
begin
|
|
z.re := (z1.re * z2.re) - (z1.im * z2.im);
|
|
z.im := (z1.re * z2.im) + (z1.im * z2.re);
|
|
end;
|
|
|
|
operator * (z1 : complex; r : real) z : complex;
|
|
(* multiplication : z := z1 * r *)
|
|
begin
|
|
z.re := z1.re * r;
|
|
z.im := z1.im * r;
|
|
end;
|
|
|
|
operator * (r : real; z1 : complex) z : complex;
|
|
(* multiplication : z := r + z1 *)
|
|
begin
|
|
z.re := z1.re * r;
|
|
z.im := z1.im * r;
|
|
end;
|
|
|
|
operator / (znum, zden : complex) z : complex;
|
|
(* division : z := znum / zden *)
|
|
var denom : real;
|
|
begin
|
|
with zden do denom := (re * re) + (im * im);
|
|
if denom = 0.0
|
|
then begin
|
|
writeln('******** function Cdiv ********');
|
|
writeln('******* DIVISION BY ZERO ******');
|
|
runerror(200);
|
|
end
|
|
else begin
|
|
z.re := ((znum.re * zden.re) + (znum.im * zden.im)) / denom;
|
|
z.im := ((znum.im * zden.re) - (znum.re * zden.im)) / denom;
|
|
end;
|
|
end;
|
|
|
|
operator / (znum : complex; r : real) z : complex;
|
|
(* division : z := znum / r *)
|
|
begin
|
|
if r = 0.0
|
|
then begin
|
|
writeln('******** function Cdiv ********');
|
|
writeln('******* DIVISION BY ZERO ******');
|
|
runerror(200);
|
|
end
|
|
else begin
|
|
z.re := znum.re / r;
|
|
z.im := znum.im / r;
|
|
end;
|
|
end;
|
|
|
|
operator / (r : real; zden : complex) z : complex;
|
|
(* division : z := r / zden *)
|
|
var denom : real;
|
|
begin
|
|
with zden do denom := (re * re) + (im * im);
|
|
if denom = 0.0
|
|
then begin
|
|
writeln('******** function Cdiv ********');
|
|
writeln('******* DIVISION BY ZERO ******');
|
|
runerror(200);
|
|
end
|
|
else begin
|
|
z.re := (r * zden.re) / denom;
|
|
z.im := - (r * zden.im) / denom;
|
|
end;
|
|
end;
|
|
|
|
(* fonctions complexes particulieres *)
|
|
|
|
function cneg (z : complex) : complex;
|
|
(* negatif : cneg = - z *)
|
|
begin
|
|
cneg.re := - z.re;
|
|
cneg.im := - z.im;
|
|
end;
|
|
|
|
function cmod (z : complex): real;
|
|
(* module : r = |z| *)
|
|
begin
|
|
with z do cmod := sqrt((re * re) + (im * im))
|
|
end;
|
|
|
|
function carg (z : complex): real;
|
|
(* argument : 0 / z = p ei0 *)
|
|
begin
|
|
carg := arctan2(z.re, z.im)
|
|
end;
|
|
|
|
function ccong (z : complex) : complex;
|
|
(* conjuge : z := x + i.y alors r = x - i.y *)
|
|
begin
|
|
ccong.re := z.re;
|
|
ccong.im := - z.im;
|
|
end;
|
|
|
|
function cinv (z : complex) : complex;
|
|
(* inverse : r := 1 / z *)
|
|
var denom : real;
|
|
begin
|
|
with z do denom := (re * re) + (im * im);
|
|
if denom = 0.0
|
|
then begin
|
|
writeln('******** function Cinv ********');
|
|
writeln('******* DIVISION BY ZERO ******');
|
|
runerror(200);
|
|
end
|
|
else begin
|
|
cinv.re := z.re / denom;
|
|
cinv.im := - z.im / denom
|
|
end;
|
|
end;
|
|
|
|
function ciz (z : complex) : complex;
|
|
(* multiplication par i *)
|
|
(* z = x + i.y , r = i.z = - y + i.x *)
|
|
begin
|
|
ciz.re := - z.im;
|
|
ciz.im := z.re;
|
|
end;
|
|
|
|
function c_iz (z : complex) : complex;
|
|
(* multiplication par -i *)
|
|
(* z = x + i.y , r = -i.z = y - i.x *)
|
|
begin
|
|
c_iz.re := z.im;
|
|
c_iz.im := - z.re;
|
|
end;
|
|
|
|
function czero : complex;
|
|
(* return a zero complex *)
|
|
begin
|
|
czero.re := 0.0;
|
|
czero.im := 0.0;
|
|
end;
|
|
|
|
operator = (z1, z2 : complex) b : boolean;
|
|
(* returns TRUE if z1 = z2 *)
|
|
begin
|
|
b := (z1.re = z2.re) and (z1.im = z2.im)
|
|
end;
|
|
|
|
operator = (z1 : complex; r :real) b : boolean;
|
|
(* returns TRUE if z1 = r *)
|
|
begin
|
|
b := (z1.re = r) and (z1.im = 0.0)
|
|
end;
|
|
|
|
operator = (r : real; z1 : complex) b : boolean;
|
|
(* returns TRUE if z1 = r *)
|
|
begin
|
|
b := (z1.re = r) and (z1.im = 0.0)
|
|
end;
|
|
|
|
|
|
(* fonctions elementaires *)
|
|
|
|
function cexp (z : complex) : complex;
|
|
(* exponantielle : r := exp(z) *)
|
|
(* exp(x + iy) = exp(x).exp(iy) = exp(x).[cos(y) + i sin(y)] *)
|
|
var expz : real;
|
|
begin
|
|
expz := exp(z.re);
|
|
cexp.re := expz * cos(z.im);
|
|
cexp.im := expz * sin(z.im);
|
|
end;
|
|
|
|
function cln (z : complex) : complex;
|
|
(* logarithme naturel : r := ln(z) *)
|
|
(* ln( p exp(i0)) = ln(p) + i0 + 2kpi *)
|
|
var modz : real;
|
|
begin
|
|
with z do modz := (re * re) + (im * im);
|
|
if modz = 0.0
|
|
then begin
|
|
writeln('********* function Cln *********');
|
|
writeln('****** LOGARITHME OF ZERO ******');
|
|
runerror(200)
|
|
end
|
|
else begin
|
|
cln.re := ln(modz);
|
|
cln.im := arctan2(z.re, z.im);
|
|
end
|
|
end;
|
|
|
|
function csqrt (z : complex) : complex;
|
|
(* racine carre : r := sqrt(z) *)
|
|
var root, q : real;
|
|
begin
|
|
if (z.re <> 0.0) or (z.im <> 0.0)
|
|
then begin
|
|
root := sqrt(0.5 * (abs(z.re) + cmod(z)));
|
|
q := z.im / (2.0 * root);
|
|
if z.re >= 0.0 then
|
|
begin
|
|
csqrt.re := root;
|
|
csqrt.im := q;
|
|
end
|
|
else if z.im < 0.0
|
|
then
|
|
begin
|
|
csqrt.re := - q;
|
|
csqrt.im := - root
|
|
end
|
|
else
|
|
begin
|
|
csqrt.re := q;
|
|
csqrt.im := root
|
|
end
|
|
end
|
|
else result := z;
|
|
end;
|
|
|
|
operator ^ (z1, z2 : complex) z : complex;
|
|
(* multiplication : z := z1 * z2 *)
|
|
begin
|
|
z.re := (z1.re * z2.re) - (z1.im * z2.im);
|
|
z.im := (z1.re * z2.im) + (z1.im * z2.re);
|
|
end;
|
|
|
|
operator * (z1 : complex; r : real) z : complex;
|
|
(* multiplication : z := z1 * r *)
|
|
begin
|
|
z.re := z1.re * r;
|
|
z.im := z1.im * r;
|
|
end;
|
|
|
|
operator * (r : real; z1 : complex) z : complex;
|
|
(* multiplication : z := r + z1 *)
|
|
begin
|
|
z.re := z1.re * r;
|
|
z.im := z1.im * r;
|
|
end;
|
|
|
|
(* fonctions trigonometriques directes *)
|
|
|
|
function ccos (z : complex) : complex;
|
|
(* cosinus complex *)
|
|
(* cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy) *)
|
|
(* cos(ix) = ch(x) et sin(ix) = i.sh(x) *)
|
|
begin
|
|
ccos.re := cos(z.re) * ch(z.im);
|
|
ccos.im := - sin(z.re) * sh(z.im);
|
|
end;
|
|
|
|
function csin (z : complex) : complex;
|
|
(* sinus complex *)
|
|
(* sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy) *)
|
|
(* cos(ix) = ch(x) et sin(ix) = i.sh(x) *)
|
|
begin
|
|
csin.re := sin(z.re) * ch(z.im);
|
|
csin.im := cos(z.re) * sh(z.im);
|
|
end;
|
|
|
|
function ctg (z : complex) : complex;
|
|
(* tangente *)
|
|
var ccosz, temp : complex;
|
|
begin
|
|
ccosz := ccos(z);
|
|
if (ccosz.re = 0.0) and (ccosz.im = 0.0)
|
|
then begin
|
|
writeln('********* function Ctg *********');
|
|
writeln('******* DIVISION BY ZERO ******');
|
|
runerror(200)
|
|
end
|
|
else begin
|
|
temp := csin(z);
|
|
ctg := temp / ccosz;
|
|
end
|
|
end;
|
|
|
|
(* fonctions trigonometriques inverses *)
|
|
|
|
function carc_cos (z : complex) : complex;
|
|
(* arc cosinus complex *)
|
|
(* arccos(z) = -i.argch(z) *)
|
|
begin
|
|
z := carg_ch(z);
|
|
carc_cos := c_iz(z);
|
|
end;
|
|
|
|
function carc_sin (z : complex) : complex;
|
|
(* arc sinus complex *)
|
|
(* arcsin(z) = -i.argsh(i.z) *)
|
|
begin
|
|
z := ciz(z);
|
|
z := carg_sh(z);
|
|
carc_sin := c_iz(z);
|
|
end;
|
|
|
|
function carc_tg (z : complex) : complex;
|
|
(* arc tangente complex *)
|
|
(* arctg(z) = -i.argth(i.z) *)
|
|
begin
|
|
z := ciz(z);
|
|
z := carg_th(z);
|
|
carc_tg := c_iz(z);
|
|
end;
|
|
|
|
(* fonctions trigonometriques hyperboliques *)
|
|
|
|
function cch (z : complex) : complex;
|
|
(* cosinus hyperbolique *)
|
|
(* ch(x+iy) = ch(x).ch(iy) + sh(x).sh(iy) *)
|
|
(* ch(iy) = cos(y) et sh(iy) = i.sin(y) *)
|
|
begin
|
|
cch.re := ch(z.re) * cos(z.im);
|
|
cch.im := sh(z.re) * sin(z.im);
|
|
end;
|
|
|
|
function csh (z : complex) : complex;
|
|
(* sinus hyperbolique *)
|
|
(* sh(x+iy) = sh(x).ch(iy) + ch(x).sh(iy) *)
|
|
(* ch(iy) = cos(y) et sh(iy) = i.sin(y) *)
|
|
begin
|
|
csh.re := sh(z.re) * cos(z.im);
|
|
csh.im := ch(z.re) * sin(z.im);
|
|
end;
|
|
|
|
function cth (z : complex) : complex;
|
|
(* tangente hyperbolique complex *)
|
|
(* th(x) = sh(x) / ch(x) *)
|
|
(* ch(x) > 1 qq x *)
|
|
var temp : complex;
|
|
begin
|
|
temp := cch(z);
|
|
z := csh(z);
|
|
cth := z / temp;
|
|
end;
|
|
|
|
(* fonctions trigonometriques hyperboliques inverses *)
|
|
|
|
function carg_ch (z : complex) : complex;
|
|
(* arg cosinus hyperbolique *)
|
|
(* _________ *)
|
|
(* argch(z) = -/+ ln(z + i.V 1 - z.z) *)
|
|
var temp : complex;
|
|
begin
|
|
with temp do begin
|
|
re := 1 - z.re * z.re + z.im * z.im;
|
|
im := - 2 * z.re * z.im
|
|
end;
|
|
temp := csqrt(temp);
|
|
temp := ciz(temp);
|
|
temp := temp + z;
|
|
temp := cln(temp);
|
|
carg_ch := cneg(temp);
|
|
end;
|
|
|
|
function carg_sh (z : complex) : complex;
|
|
(* arc sinus hyperbolique *)
|
|
(* ________ *)
|
|
(* argsh(z) = ln(z + V 1 + z.z) *)
|
|
var temp : complex;
|
|
begin
|
|
with temp do begin
|
|
re := 1 + z.re * z.re - z.im * z.im;
|
|
im := 2 * z.re * z.im
|
|
end;
|
|
temp := csqrt(temp);
|
|
temp := cadd(temp, z);
|
|
carg_sh := cln(temp);
|
|
end;
|
|
|
|
function carg_th (z : complex) : complex;
|
|
(* arc tangente hyperbolique *)
|
|
(* argth(z) = 1/2 ln((z + 1) / (1 - z)) *)
|
|
var temp : complex;
|
|
begin
|
|
with temp do begin
|
|
re := 1 + z.re;
|
|
im := z.im
|
|
end;
|
|
with result do begin
|
|
re := 1 - re;
|
|
im := - im
|
|
end;
|
|
result := temp / result;
|
|
carg_th.re := 0.5 * re;
|
|
carg_th.im := 0.5 * im
|
|
end;
|
|
|
|
end.
|
|
{
|
|
$Log$
|
|
Revision 1.1 1998-03-25 11:18:43 root
|
|
Initial revision
|
|
|
|
Revision 1.3 1998/01/26 11:59:25 michael
|
|
+ Added log at the end
|
|
|
|
|
|
|
|
Working file: rtl/inc/complex.pp
|
|
description:
|
|
----------------------------
|
|
revision 1.2
|
|
date: 1997/12/01 15:33:30; author: michael; state: Exp; lines: +14 -0
|
|
+ added copyright reference in header.
|
|
----------------------------
|
|
revision 1.1
|
|
date: 1997/11/27 08:33:46; author: michael; state: Exp;
|
|
Initial revision
|
|
----------------------------
|
|
revision 1.1.1.1
|
|
date: 1997/11/27 08:33:46; author: michael; state: Exp; lines: +0 -0
|
|
FPC RTL CVS start
|
|
=============================================================================
|
|
}
|