| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- (* ***********************************************
- Модуль работы с комплексными числами.
- Вадим Исаев, 2020
- Module for complex numbers.
- Vadim Isaev, 2020
- *************************************************** *)
- MODULE CMath;
- IMPORT Math, Out;
- TYPE
- complex* = POINTER TO RECORD
- re*: REAL;
- im*: REAL
- END;
- VAR
- result: complex;
- i* : complex;
- _0*: complex;
- (* Инициализация комплексного числа.
- Init complex number. *)
- PROCEDURE CInit* (re : REAL; im: REAL): complex;
- VAR
- temp: complex;
- BEGIN
- NEW(temp);
- temp.re:=re;
- temp.im:=im;
- RETURN temp
- END CInit;
- (* Четыре основных арифметических операций.
- Four base operations +, -, * , / *)
- (* Сложение
- addition : z := z1 + z2 *)
- PROCEDURE CAdd* (z1, z2: complex): complex;
- BEGIN
- result.re := z1.re + z2.re;
- result.im := z1.im + z2.im;
- RETURN result
- END CAdd;
- (* Сложение с REAL.
- addition : z := z1 + r1 *)
- PROCEDURE CAdd_r* (z1: complex; r1: REAL): complex;
- BEGIN
- result.re := z1.re + r1;
- result.im := z1.im;
- RETURN result
- END CAdd_r;
- (* Сложение с INTEGER.
- addition : z := z1 + i1 *)
- PROCEDURE CAdd_i* (z1: complex; i1: INTEGER): complex;
- BEGIN
- result.re := z1.re + FLT(i1);
- result.im := z1.im;
- RETURN result
- END CAdd_i;
- (* Смена знака.
- substraction : z := - z1 *)
- PROCEDURE CNeg (z1 : complex): complex;
- BEGIN
- result.re := -z1.re;
- result.im := -z1.im;
- RETURN result
- END CNeg;
- (* Вычитание.
- substraction : z := z1 - z2 *)
- PROCEDURE CSub* (z1, z2 : complex): complex;
- BEGIN
- result.re := z1.re - z2.re;
- result.im := z1.im - z2.im;
- RETURN result
- END CSub;
- (* Вычитание REAL.
- substraction : z := z1 - r1 *)
- PROCEDURE CSub_r1* (z1 : complex; r1 : REAL): complex;
- BEGIN
- result.re := z1.re - r1;
- result.im := z1.im;
- RETURN result
- END CSub_r1;
- (* Вычитание из REAL.
- substraction : z := r1 - z1 *)
- PROCEDURE CSub_r2* (r1 : REAL; z1 : complex): complex;
- BEGIN
- result.re := r1 - z1.re;
- result.im := - z1.im;
- RETURN result
- END CSub_r2;
- (* Вычитание INTEGER.
- substraction : z := z1 - i1 *)
- PROCEDURE CSub_i* (z1 : complex; i1 : INTEGER): complex;
- BEGIN
- result.re := z1.re - FLT(i1);
- result.im := z1.im;
- RETURN result
- END CSub_i;
- (* Умножение.
- multiplication : z := z1 * z2 *)
- PROCEDURE CMul (z1, z2 : complex): complex;
- BEGIN
- result.re := (z1.re * z2.re) - (z1.im * z2.im);
- result.im := (z1.re * z2.im) + (z1.im * z2.re);
- RETURN result
- END CMul;
- (* Умножение с REAL.
- multiplication : z := z1 * r1 *)
- PROCEDURE CMul_r (z1 : complex; r1 : REAL): complex;
- BEGIN
- result.re := z1.re * r1;
- result.im := z1.im * r1;
- RETURN result
- END CMul_r;
- (* Умножение с INTEGER.
- multiplication : z := z1 * i1 *)
- PROCEDURE CMul_i (z1 : complex; i1 : INTEGER): complex;
- BEGIN
- result.re := z1.re * FLT(i1);
- result.im := z1.im * FLT(i1);
- RETURN result
- END CMul_i;
- (* Деление.
- division : z := znum / zden *)
- PROCEDURE CDiv (z1, z2 : complex): complex;
- (* The following algorithm is used to properly handle
- denominator overflow:
- | a + b(d/c) c - a(d/c)
- | ---------- + ---------- I if |d| < |c|
- a + b I | c + d(d/c) a + d(d/c)
- ------- = |
- c + d I | b + a(c/d) -a+ b(c/d)
- | ---------- + ---------- I if |d| >= |c|
- | d + c(c/d) d + c(c/d)
- *)
- VAR
- tmp, denom : REAL;
- BEGIN
- IF ( ABS(z2.re) > ABS(z2.im) ) THEN
- tmp := z2.im / z2.re;
- denom := z2.re + z2.im * tmp;
- result.re := (z1.re + z1.im * tmp) / denom;
- result.im := (z1.im - z1.re * tmp) / denom;
- ELSE
- tmp := z2.re / z2.im;
- denom := z2.im + z2.re * tmp;
- result.re := (z1.im + z1.re * tmp) / denom;
- result.im := (-z1.re + z1.im * tmp) / denom;
- END;
- RETURN result
- END CDiv;
- (* Деление на REAL.
- division : z := znum / r1 *)
- PROCEDURE CDiv_r* (z1 : complex; r1 : REAL): complex;
- BEGIN
- result.re := z1.re / r1;
- result.im := z1.im / r1;
- RETURN result
- END CDiv_r;
- (* Деление на INTEGER.
- division : z := znum / i1 *)
- PROCEDURE CDiv_i* (z1 : complex; i1 : INTEGER): complex;
- BEGIN
- result.re := z1.re / FLT(i1);
- result.im := z1.im / FLT(i1);
- RETURN result
- END CDiv_i;
- (* fonctions elementaires *)
- (* Вывод на экран.
- out complex number *)
- PROCEDURE CPrint* (z: complex; width: INTEGER);
- BEGIN
- Out.Real(z.re, width);
- IF z.im>=0.0 THEN
- Out.String("+");
- END;
- Out.Real(z.im, width);
- Out.String("i");
- END CPrint;
- PROCEDURE CPrintLn* (z: complex; width: INTEGER);
- BEGIN
- CPrint(z, width);
- Out.Ln;
- END CPrintLn;
- (* Вывод на экран с фиксированным кол-вом знаков
- после запятой (p) *)
- PROCEDURE CPrintFix* (z: complex; width, p: INTEGER);
- BEGIN
- Out.FixReal(z.re, width, p);
- IF z.im>=0.0 THEN
- Out.String("+");
- END;
- Out.FixReal(z.im, width, p);
- Out.String("i");
- END CPrintFix;
- PROCEDURE CPrintFixLn* (z: complex; width, p: INTEGER);
- BEGIN
- CPrintFix(z, width, p);
- Out.Ln;
- END CPrintFixLn;
- (* Модуль числа.
- module : r = |z| *)
- PROCEDURE CMod* (z1 : complex): REAL;
- BEGIN
- RETURN Math.sqrt((z1.re * z1.re) + (z1.im * z1.im))
- END CMod;
- (* Квадрат числа.
- square : r := z*z *)
- PROCEDURE CSqr* (z1: complex): complex;
- BEGIN
- result.re := z1.re * z1.re - z1.im * z1.im;
- result.im := 2.0 * z1.re * z1.im;
- RETURN result
- END CSqr;
- (* Квадратный корень числа.
- square root : r := sqrt(z) *)
- PROCEDURE CSqrt* (z1: complex): complex;
- VAR
- root, q: REAL;
- BEGIN
- IF (z1.re#0.0) OR (z1.im#0.0) THEN
- root := Math.sqrt(0.5 * (ABS(z1.re) + CMod(z1)));
- q := z1.im / (2.0 * root);
- IF z1.re >= 0.0 THEN
- result.re := root;
- result.im := q;
- ELSE
- IF z1.im < 0.0 THEN
- result.re := - q;
- result.im := - root
- ELSE
- result.re := q;
- result.im := root
- END
- END
- ELSE
- result := z1;
- END;
- RETURN result
- END CSqrt;
- (* Экспонента.
- exponantial : r := exp(z) *)
- (* exp(x + iy) = exp(x).exp(iy) = exp(x).[cos(y) + i sin(y)] *)
- PROCEDURE CExp* (z: complex): complex;
- VAR
- expz : REAL;
- BEGIN
- expz := Math.exp(z.re);
- result.re := expz * Math.cos(z.im);
- result.im := expz * Math.sin(z.im);
- RETURN result
- END CExp;
- (* Натуральный логарифм.
- natural logarithm : r := ln(z) *)
- (* ln( p exp(i0)) = ln(p) + i0 + 2kpi *)
- PROCEDURE CLn* (z: complex): complex;
- BEGIN
- result.re := Math.ln(CMod(z));
- result.im := Math.arctan2(z.im, z.re);
- RETURN result
- END CLn;
- (* Число в степени.
- exp : z := z1^z2 *)
- PROCEDURE CPower* (z1, z2 : complex): complex;
- VAR
- a: complex;
- BEGIN
- a:=CLn(z1);
- a:=CMul(z2, a);
- result:=CExp(a);
- RETURN result
- END CPower;
- (* Число в степени REAL.
- multiplication : z := z1^r *)
- PROCEDURE CPower_r* (z1: complex; r: REAL): complex;
- VAR
- a: complex;
- BEGIN
- a:=CLn(z1);
- a:=CMul_r(a, r);
- result:=CExp(a);
- RETURN result
- END CPower_r;
- (* Обратное число.
- inverse : r := 1 / z *)
- PROCEDURE CInv* (z: complex): complex;
- VAR
- denom : REAL;
- BEGIN
- denom := (z.re * z.re) + (z.im * z.im);
- (* generates a fpu exception if denom=0 as for reals *)
- result.re:=z.re/denom;
- result.im:=-z.im/denom;
- RETURN result
- END CInv;
- (* direct trigonometric functions *)
- (* Косинус.
- complex cosinus *)
- (* cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy) *)
- (* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *)
- PROCEDURE CCos* (z: complex): complex;
- BEGIN
- result.re := Math.cos(z.re) * Math.cosh(z.im);
- result.im := - Math.sin(z.re) * Math.sinh(z.im);
- RETURN result
- END CCos;
- (* Синус.
- sinus complex *)
- (* sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy) *)
- (* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *)
- PROCEDURE CSin (z: complex): complex;
- BEGIN
- result.re := Math.sin(z.re) * Math.cosh(z.im);
- result.im := Math.cos(z.re) * Math.sinh(z.im);
- RETURN result
- END CSin;
- (* Тангенс.
- tangente *)
- PROCEDURE CTg* (z: complex): complex;
- VAR
- temp1, temp2: complex;
- BEGIN
- temp1:=CSin(z);
- temp2:=CCos(z);
- result:=CDiv(temp1, temp2);
- RETURN result
- END CTg;
- (* inverse complex hyperbolic functions *)
- (* Гиперболический арккосинус.
- hyberbolic arg cosinus *)
- (* _________ *)
- (* argch(z) = -/+ ln(z + i.V 1 - z.z) *)
- PROCEDURE CArcCosh* (z : complex): complex;
- BEGIN
- result:=CNeg(CLn(CAdd(z, CMul(i, CSqrt(CSub_r2(1.0, CMul(z, z)))))));
- RETURN result
- END CArcCosh;
- (* Гиперболический арксинус.
- hyperbolic arc sinus *)
- (* ________ *)
- (* argsh(z) = ln(z + V 1 + z.z) *)
- PROCEDURE CArcSinh* (z : complex): complex;
- BEGIN
- result:=CLn(CAdd(z, CSqrt(CAdd_r(CMul(z, z), 1.0))));
- RETURN result
- END CArcSinh;
- (* Гиперболический арктангенс.
- hyperbolic arc tangent *)
- (* argth(z) = 1/2 ln((z + 1) / (1 - z)) *)
- PROCEDURE CArcTgh (z : complex): complex;
- BEGIN
- result:=CDiv_r(CLn(CDiv(CAdd_r(z, 1.0), CSub_r2(1.0, z))), 2.0);
- RETURN result
- END CArcTgh;
- (* trigonometriques inverses *)
- (* Арккосинус.
- arc cosinus complex *)
- (* arccos(z) = -i.argch(z) *)
- PROCEDURE CArcCos* (z: complex): complex;
- BEGIN
- result := CNeg(CMul(i, CArcCosh(z)));
- RETURN result
- END CArcCos;
- (* Арксинус.
- arc sinus complex *)
- (* arcsin(z) = -i.argsh(i.z) *)
- PROCEDURE CArcSin* (z : complex): complex;
- BEGIN
- result := CNeg(CMul(i, CArcSinh(z)));
- RETURN result
- END CArcSin;
- (* Арктангенс.
- arc tangente complex *)
- (* arctg(z) = -i.argth(i.z) *)
- PROCEDURE CArcTg* (z : complex): complex;
- BEGIN
- result := CNeg(CMul(i, CArcTgh(CMul(i, z))));
- RETURN result
- END CArcTg;
- BEGIN
- result:=CInit(0.0, 0.0);
- i :=CInit(0.0, 1.0);
- _0:=CInit(0.0, 0.0);
- END CMath.
|