CMath.ob07 9.8 KB

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