Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. (* ***********************************************
  2.     Модуль работы с комплексными числами.
  3.     Вадим Исаев, 2020
  4.     Module for complex numbers.
  5.     Vadim Isaev, 2020
  6. *************************************************** *)
  7.  
  8. MODULE CMath;
  9.  
  10. IMPORT Math, Out;
  11.  
  12. TYPE
  13.   complex* = POINTER TO RECORD
  14.     re*: REAL;
  15.     im*: REAL
  16.   END;
  17.  
  18. VAR
  19.   result: complex;
  20.  
  21.   i* : complex;
  22.   _0*: complex;
  23.  
  24. (* Инициализация комплексного числа.
  25.    Init complex number. *)
  26. PROCEDURE CInit* (re : REAL; im: REAL): complex;
  27. VAR
  28.   temp: complex;
  29. BEGIN
  30.   NEW(temp);
  31.   temp.re:=re;
  32.   temp.im:=im;
  33.  
  34.   RETURN temp
  35. END CInit;
  36.  
  37.  
  38. (* Четыре основных арифметических операций.
  39.    Four base operations  +, -, * , / *)
  40.  
  41. (* Сложение
  42.    addition : z := z1 + z2 *)
  43. PROCEDURE CAdd* (z1, z2: complex): complex;
  44. BEGIN
  45.   result.re := z1.re + z2.re;
  46.   result.im := z1.im + z2.im;
  47.  
  48.   RETURN result
  49. END CAdd;
  50.  
  51. (* Сложение с REAL.
  52.    addition : z := z1 + r1 *)
  53. PROCEDURE CAdd_r* (z1: complex; r1: REAL): complex;
  54. BEGIN
  55.   result.re := z1.re + r1;
  56.   result.im := z1.im;
  57.  
  58.   RETURN result
  59. END CAdd_r;
  60.  
  61. (* Сложение с INTEGER.
  62.    addition : z := z1 + i1 *)
  63. PROCEDURE CAdd_i* (z1: complex; i1: INTEGER): complex;
  64. BEGIN
  65.   result.re := z1.re + FLT(i1);
  66.   result.im := z1.im;
  67.  
  68.   RETURN result
  69. END CAdd_i;
  70.  
  71. (* Смена знака.
  72.    substraction : z := - z1 *)
  73. PROCEDURE CNeg (z1 : complex): complex;
  74. BEGIN
  75.   result.re := -z1.re;
  76.   result.im := -z1.im;
  77.  
  78.   RETURN result
  79. END CNeg;
  80.  
  81. (* Вычитание.
  82.    substraction : z := z1 - z2 *)
  83. PROCEDURE CSub* (z1, z2 : complex): complex;
  84. BEGIN
  85.   result.re := z1.re - z2.re;
  86.   result.im := z1.im - z2.im;
  87.  
  88.   RETURN result
  89. END CSub;
  90.  
  91. (* Вычитание REAL.
  92.    substraction : z := z1 - r1 *)
  93. PROCEDURE CSub_r1* (z1 : complex; r1 : REAL): complex;
  94. BEGIN
  95.   result.re := z1.re - r1;
  96.   result.im := z1.im;
  97.  
  98.   RETURN result
  99. END CSub_r1;
  100.  
  101. (* Вычитание из REAL.
  102.    substraction : z := r1 - z1 *)
  103. PROCEDURE CSub_r2* (r1 : REAL; z1 : complex): complex;
  104. BEGIN
  105.   result.re := r1 - z1.re;
  106.   result.im := - z1.im;
  107.  
  108.   RETURN result
  109. END CSub_r2;
  110.  
  111. (* Вычитание INTEGER.
  112.    substraction : z := z1 - i1 *)
  113. PROCEDURE CSub_i* (z1 : complex; i1 : INTEGER): complex;
  114. BEGIN
  115.   result.re := z1.re - FLT(i1);
  116.   result.im := z1.im;
  117.  
  118.   RETURN result
  119. END CSub_i;
  120.  
  121. (* Умножение.
  122.    multiplication : z := z1 * z2 *)
  123. PROCEDURE CMul (z1, z2 : complex): complex;
  124. BEGIN
  125.   result.re := (z1.re * z2.re) - (z1.im * z2.im);
  126.   result.im := (z1.re * z2.im) + (z1.im * z2.re);
  127.  
  128.   RETURN result
  129. END CMul;
  130.  
  131. (* Умножение с REAL.
  132.    multiplication : z := z1 * r1 *)
  133. PROCEDURE CMul_r (z1 : complex; r1 : REAL): complex;
  134. BEGIN
  135.   result.re := z1.re * r1;
  136.   result.im := z1.im * r1;
  137.  
  138.   RETURN result
  139. END CMul_r;
  140.  
  141. (* Умножение с INTEGER.
  142.    multiplication : z := z1 * i1 *)
  143. PROCEDURE CMul_i (z1 : complex; i1 : INTEGER): complex;
  144. BEGIN
  145.   result.re := z1.re * FLT(i1);
  146.   result.im := z1.im * FLT(i1);
  147.  
  148.   RETURN result
  149. END CMul_i;
  150.  
  151. (* Деление.
  152.    division : z := znum / zden *)
  153. PROCEDURE CDiv (z1, z2 : complex): complex;
  154.     (* The following algorithm is used to properly handle
  155.       denominator overflow:
  156.  
  157.                  |  a + b(d/c)   c - a(d/c)
  158.                  |  ---------- + ---------- I     if |d| < |c|
  159.       a + b I    |  c + d(d/c)   a + d(d/c)
  160.       -------  = |
  161.       c + d I    |  b + a(c/d)   -a+ b(c/d)
  162.                  |  ---------- + ---------- I     if |d| >= |c|
  163.                  |  d + c(c/d)   d + c(c/d)
  164.     *)
  165. VAR
  166.   tmp, denom : REAL;
  167. BEGIN
  168.    IF ( ABS(z2.re) > ABS(z2.im) ) THEN
  169.      tmp := z2.im / z2.re;
  170.      denom := z2.re + z2.im * tmp;
  171.      result.re := (z1.re + z1.im * tmp) / denom;
  172.      result.im := (z1.im - z1.re * tmp) / denom;
  173.    ELSE
  174.      tmp := z2.re / z2.im;
  175.      denom := z2.im + z2.re * tmp;
  176.      result.re := (z1.im + z1.re * tmp) / denom;
  177.      result.im := (-z1.re + z1.im * tmp) / denom;
  178.    END;
  179.  
  180.    RETURN result
  181. END CDiv;
  182.  
  183. (* Деление на REAL.
  184.    division : z := znum / r1 *)
  185. PROCEDURE CDiv_r* (z1 : complex; r1 : REAL): complex;
  186. BEGIN
  187.   result.re := z1.re / r1;
  188.   result.im := z1.im / r1;
  189.  
  190.   RETURN result
  191. END CDiv_r;
  192.  
  193. (* Деление на INTEGER.
  194.    division : z := znum / i1 *)
  195. PROCEDURE CDiv_i* (z1 : complex; i1 : INTEGER): complex;
  196. BEGIN
  197.   result.re := z1.re / FLT(i1);
  198.   result.im := z1.im / FLT(i1);
  199.  
  200.   RETURN result
  201. END CDiv_i;
  202.  
  203. (* fonctions elementaires *)
  204.  
  205. (* Вывод на экран.
  206.    out complex number *)
  207. PROCEDURE CPrint* (z: complex; width: INTEGER);
  208. BEGIN
  209.   Out.Real(z.re, width);
  210.   IF z.im>=0.0 THEN
  211.     Out.String("+");
  212.   END;
  213.   Out.Real(z.im, width);
  214.   Out.String("i");
  215. END CPrint;
  216.  
  217. PROCEDURE CPrintLn* (z: complex; width: INTEGER);
  218. BEGIN
  219.   CPrint(z, width);
  220.   Out.Ln;
  221. END CPrintLn;
  222.  
  223. (* Вывод на экран с фиксированным кол-вом знаков
  224.    после запятой (p) *)
  225. PROCEDURE CPrintFix* (z: complex; width, p: INTEGER);
  226. BEGIN
  227.   Out.FixReal(z.re, width, p);
  228.   IF z.im>=0.0 THEN
  229.     Out.String("+");
  230.   END;
  231.   Out.FixReal(z.im, width, p);
  232.   Out.String("i");
  233. END CPrintFix;
  234.  
  235. PROCEDURE CPrintFixLn* (z: complex; width, p: INTEGER);
  236. BEGIN
  237.   CPrintFix(z, width, p);
  238.   Out.Ln;
  239. END CPrintFixLn;
  240.  
  241. (* Модуль числа.
  242.    module : r = |z| *)
  243. PROCEDURE CMod* (z1 : complex): REAL;
  244. BEGIN
  245.   RETURN Math.sqrt((z1.re * z1.re) + (z1.im * z1.im))
  246. END CMod;
  247.  
  248. (* Квадрат числа.
  249.    square : r := z*z *)
  250. PROCEDURE CSqr* (z1: complex): complex;
  251. BEGIN
  252.   result.re := z1.re * z1.re - z1.im * z1.im;
  253.   result.im := 2.0 * z1.re * z1.im;
  254.  
  255.   RETURN result
  256. END CSqr;
  257.  
  258. (* Квадратный корень числа.
  259.    square root : r := sqrt(z) *)
  260. PROCEDURE CSqrt* (z1: complex): complex;
  261. VAR
  262.   root, q: REAL;
  263. BEGIN
  264.   IF (z1.re#0.0) OR (z1.im#0.0) THEN
  265.     root := Math.sqrt(0.5 * (ABS(z1.re) + CMod(z1)));
  266.     q := z1.im / (2.0 * root);
  267.     IF z1.re >= 0.0 THEN
  268.       result.re := root;
  269.       result.im := q;
  270.     ELSE
  271.       IF z1.im < 0.0 THEN
  272.         result.re := - q;
  273.         result.im := - root
  274.       ELSE
  275.         result.re :=  q;
  276.         result.im :=  root
  277.       END
  278.     END
  279.   ELSE
  280.     result := z1;
  281.   END;
  282.  
  283.   RETURN result
  284. END CSqrt;
  285.  
  286. (* Экспонента.
  287.    exponantial : r := exp(z) *)
  288. (* exp(x + iy) = exp(x).exp(iy) = exp(x).[cos(y) + i sin(y)] *)
  289. PROCEDURE CExp* (z: complex): complex;
  290. VAR
  291.   expz : REAL;
  292. BEGIN
  293.   expz := Math.exp(z.re);
  294.   result.re := expz * Math.cos(z.im);
  295.   result.im := expz * Math.sin(z.im);
  296.  
  297.   RETURN result
  298. END CExp;
  299.  
  300. (* Натуральный логарифм.
  301.    natural logarithm : r := ln(z) *)
  302. (* ln( p exp(i0)) = ln(p) + i0 + 2kpi *)
  303. PROCEDURE CLn* (z: complex): complex;
  304. BEGIN
  305.   result.re := Math.ln(CMod(z));
  306.   result.im := Math.arctan2(z.im, z.re);
  307.  
  308.   RETURN result
  309. END CLn;
  310.  
  311. (* Число в степени.
  312.    exp : z := z1^z2 *)
  313. PROCEDURE CPower* (z1, z2 : complex): complex;
  314. VAR
  315.   a: complex;
  316. BEGIN
  317.    a:=CLn(z1);
  318.    a:=CMul(z2, a);
  319.    result:=CExp(a);
  320.  
  321.    RETURN result
  322. END CPower;
  323.  
  324. (* Число в степени REAL.
  325.    multiplication : z := z1^r *)
  326. PROCEDURE CPower_r* (z1: complex; r: REAL): complex;
  327. VAR
  328.   a: complex;
  329. BEGIN
  330.   a:=CLn(z1);
  331.   a:=CMul_r(a, r);
  332.   result:=CExp(a);
  333.  
  334.   RETURN result
  335. END CPower_r;
  336.  
  337. (* Обратное число.
  338.    inverse : r := 1 / z *)
  339. PROCEDURE CInv* (z: complex): complex;
  340. VAR
  341.   denom : REAL;
  342. BEGIN
  343.   denom := (z.re * z.re) + (z.im * z.im);
  344.   (* generates a fpu exception if denom=0 as for reals *)
  345.   result.re:=z.re/denom;
  346.   result.im:=-z.im/denom;
  347.  
  348.   RETURN result
  349. END CInv;
  350.  
  351. (* direct trigonometric functions *)
  352.  
  353. (* Косинус.
  354.    complex cosinus *)
  355. (* cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy) *)
  356. (* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *)
  357. PROCEDURE CCos* (z: complex): complex;
  358. BEGIN
  359.   result.re := Math.cos(z.re) * Math.cosh(z.im);
  360.   result.im := - Math.sin(z.re) * Math.sinh(z.im);
  361.  
  362.   RETURN result
  363. END CCos;
  364.  
  365. (* Синус.
  366.    sinus complex *)
  367. (* sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy) *)
  368. (* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *)
  369. PROCEDURE CSin (z: complex): complex;
  370. BEGIN
  371.   result.re := Math.sin(z.re) * Math.cosh(z.im);
  372.   result.im := Math.cos(z.re) * Math.sinh(z.im);
  373.  
  374.   RETURN result
  375. END CSin;
  376.  
  377. (* Тангенс.
  378.    tangente *)
  379. PROCEDURE CTg* (z: complex): complex;
  380. VAR
  381.   temp1, temp2: complex;
  382. BEGIN
  383.   temp1:=CSin(z);
  384.   temp2:=CCos(z);
  385.   result:=CDiv(temp1, temp2);
  386.  
  387.   RETURN result
  388. END CTg;
  389.  
  390. (* inverse complex hyperbolic functions *)
  391.  
  392. (* Гиперболический арккосинус.
  393.    hyberbolic arg cosinus *)
  394. (*                          _________  *)
  395. (* argch(z) = -/+ ln(z + i.V 1 - z.z)  *)
  396. PROCEDURE CArcCosh* (z : complex): complex;
  397. BEGIN
  398.   result:=CNeg(CLn(CAdd(z, CMul(i, CSqrt(CSub_r2(1.0, CMul(z, z)))))));
  399.  
  400.   RETURN result
  401. END CArcCosh;
  402.  
  403. (* Гиперболический арксинус.
  404.    hyperbolic arc sinus       *)
  405. (*                    ________  *)
  406. (* argsh(z) = ln(z + V 1 + z.z) *)
  407. PROCEDURE CArcSinh* (z : complex): complex;
  408. BEGIN
  409.   result:=CLn(CAdd(z, CSqrt(CAdd_r(CMul(z, z), 1.0))));
  410.  
  411.   RETURN result
  412. END CArcSinh;
  413.  
  414. (* Гиперболический арктангенс.
  415.    hyperbolic arc tangent *)
  416. (* argth(z) = 1/2 ln((z + 1) / (1 - z)) *)
  417. PROCEDURE CArcTgh (z : complex): complex;
  418. BEGIN
  419.   result:=CDiv_r(CLn(CDiv(CAdd_r(z, 1.0), CSub_r2(1.0, z))), 2.0);
  420.  
  421.   RETURN result
  422. END CArcTgh;
  423.  
  424. (* trigonometriques inverses *)
  425.  
  426. (* Арккосинус.
  427.    arc cosinus complex *)
  428. (* arccos(z) = -i.argch(z) *)
  429. PROCEDURE CArcCos* (z: complex): complex;
  430. BEGIN
  431.   result := CNeg(CMul(i, CArcCosh(z)));
  432.  
  433.   RETURN result
  434. END CArcCos;
  435.  
  436. (* Арксинус.
  437.    arc sinus complex *)
  438. (* arcsin(z) = -i.argsh(i.z) *)
  439. PROCEDURE CArcSin* (z : complex): complex;
  440. BEGIN
  441.   result := CNeg(CMul(i, CArcSinh(z)));
  442.  
  443.   RETURN result
  444. END CArcSin;
  445.  
  446. (* Арктангенс.
  447.    arc tangente complex *)
  448. (* arctg(z) = -i.argth(i.z) *)
  449. PROCEDURE CArcTg* (z : complex): complex;
  450. BEGIN
  451.   result := CNeg(CMul(i, CArcTgh(CMul(i, z))));
  452.  
  453.   RETURN result
  454. END CArcTg;
  455.  
  456. BEGIN
  457.  
  458.   result:=CInit(0.0, 0.0);
  459.   i :=CInit(0.0, 1.0);
  460.   _0:=CInit(0.0, 0.0);
  461.  
  462. END CMath.
  463.