complex.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by Pierre Muller,
  5. member of the Free Pascal development team.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. Unit COMPLEX;
  13. (* Bibliotheque mathematique pour type complexe *)
  14. (* Version a fonctions et pointeurs *)
  15. (* JD GAYRARD mai 95 *)
  16. (* modified for FPK by Pierre Muller *)
  17. (* FPK supports operator overloading *)
  18. (* This library is based on functions instead of procedures.
  19. To allow a function to return complex type, the trick is
  20. is to use a pointer on the result of the function. All
  21. functions are of Pcomplex type (^complexe).
  22. In the main program the function computation is accessed
  23. by z := function_name(param1, param2)^ *)
  24. {$G+}
  25. {$N+}
  26. {$E-}
  27. interface
  28. uses MATHLIB, HYPERBOL;
  29. const author = 'GAYRARD J-D';
  30. version = 'ver 0.0 - 05/95';
  31. type complex = record
  32. re : real;
  33. im : real;
  34. end;
  35. pcomplex = ^complex;
  36. const _i : complex = (re : 0.0; im : 1.0);
  37. _0 : complex = (re : 0.0; im : 0.0);
  38. (* quatre operations : +, -, * , / and = *)
  39. operator + (z1, z2 : complex) z : complex; (* addition *)
  40. { assignment overloading is not implement }
  41. { if it was the next two would not be unnecessary }
  42. operator + (z1 : complex; r : real) z : complex; (* addition *)
  43. operator + (r : real; z1 : complex) z : complex; (* addition *)
  44. operator - (z1, z2 : complex) z : complex; (* soustraction *)
  45. operator - (z1 : complex;r : real) z : complex; (* soustraction *)
  46. operator - (r : real; z1 : complex) z : complex; (* soustraction *)
  47. operator * (z1, z2 : complex) z : complex; (* multiplication *)
  48. operator * (z1 : complex; r : real) z : complex; (* multiplication *)
  49. operator * (r : real; z1 : complex) z : complex; (* multiplication *)
  50. operator / (znum, zden : complex) z : complex; (* division znum / zden *)
  51. operator / (znum : complex; r : real) z : complex; (* division znum / r *)
  52. operator / (r : real; zden : complex) z : complex; (* division r / zden *)
  53. { ^ is not built in FPK, but can be overloaded also }
  54. operator ^ (r1, r2 : real) r : real;
  55. operator ^ (z1, z2 : complex) z : complex;
  56. operator ^ (z1 : complex; r2 : real) z : complex;
  57. operator ^ (r : real; z1 : complex) z : complex;
  58. operator = (z1, z2 : complex) b : boolean;
  59. operator = (z1 : complex;r : real) b : boolean;
  60. operator = (r : real; z1 : complex) b : boolean;
  61. (* fonctions complexes particulieres *)
  62. function cneg (z : complex) : complex; (* negatif *)
  63. function ccong (z : complex) : complex; (* conjuge *)
  64. function crcp (z : complex) : complex; (* inverse *)
  65. function ciz (z : complex) : complex; (* multiplication par i *)
  66. function c_iz (z : complex) : complex; (* multiplication par -i *)
  67. function czero : complex; (* return zero *)
  68. (* fonctions complexes a retour non complex *)
  69. function cmod (z : complex) : real; (* module *)
  70. function cequal (z1, z2 : complex) : boolean; (* compare deux complexes *)
  71. function carg (z : complex) : real; (* argument : a / z = p.e^ia *)
  72. (* fonctions elementaires *)
  73. function cexp (z : complex) : complex; (* exponantielle *)
  74. function cln (z : complex) : complex; (* logarithme naturel *)
  75. function csqrt (z : complex) : complex; (* racine carre *)
  76. (* fonctions trigonometrique directe *)
  77. function ccos (z : complex) : complex; (* cosinus *)
  78. function csin (z : complex) : complex; (* sinus *)
  79. function ctg (z : complex) : complex; (* tangente *)
  80. (* fonctions trigonometriques inverses *)
  81. function carc_cos (z : complex) : complex; (* arc cosinus *)
  82. function carc_sin (z : complex) : complex; (* arc sinus *)
  83. function carc_tg (z : complex) : complex; (* arc tangente *)
  84. (* fonctions trigonometrique hyperbolique *)
  85. function cch (z : complex) : complex; (* cosinus hyperbolique *)
  86. function csh (z : complex) : complex; (* sinus hyperbolique *)
  87. function cth (z : complex) : complex; (* tangente hyperbolique *)
  88. (* fonctions trigonometrique hyperbolique inverse *)
  89. function carg_ch (z : complex) : complex; (* arc cosinus hyperbolique *)
  90. function carg_sh (z : complex) : complex; (* arc sinus hyperbolique *)
  91. function carg_th (z : complex) : complex; (* arc tangente hyperbolique *)
  92. implementation
  93. (* quatre operations de base +, -, * , / *)
  94. operator + (z1, z2 : complex) z : complex;
  95. (* addition : z := z1 + z2 *)
  96. begin
  97. z.re := z1.re + z2.re;
  98. z.im := z1.im + z2.im;
  99. end;
  100. operator + (z1 : complex; r : real) z : complex;
  101. (* addition : z := z1 + r *)
  102. begin
  103. z.re := z1.re + r;
  104. z.im := z1.im;
  105. end;
  106. operator + (r : real; z1 : complex) z : complex;
  107. (* addition : z := r + z1 *)
  108. begin
  109. z.re := z1.re + r;
  110. z.im := z1.im;
  111. end;
  112. operator - (z1, z2 : complex) z : complex;
  113. (* substraction : z := z1 - z2 *)
  114. begin
  115. z.re := z1.re - z2.re;
  116. z.im := z1.im - z2.im;
  117. end;
  118. operator - (z1 : complex; r : real) z : complex;
  119. (* substraction : z := z1 - r *)
  120. begin
  121. z.re := z1.re - r;
  122. z.im := z1.im;
  123. end;
  124. operator - (r : real; z1 : complex) z : complex;
  125. (* substraction : z := r + z1 *)
  126. begin
  127. z.re := r - z1.re;
  128. z.im := - z1.im;
  129. end;
  130. operator * (z1, z2 : complex) z : complex;
  131. (* multiplication : z := z1 * z2 *)
  132. begin
  133. z.re := (z1.re * z2.re) - (z1.im * z2.im);
  134. z.im := (z1.re * z2.im) + (z1.im * z2.re);
  135. end;
  136. operator * (z1 : complex; r : real) z : complex;
  137. (* multiplication : z := z1 * r *)
  138. begin
  139. z.re := z1.re * r;
  140. z.im := z1.im * r;
  141. end;
  142. operator * (r : real; z1 : complex) z : complex;
  143. (* multiplication : z := r + z1 *)
  144. begin
  145. z.re := z1.re * r;
  146. z.im := z1.im * r;
  147. end;
  148. operator / (znum, zden : complex) z : complex;
  149. (* division : z := znum / zden *)
  150. var denom : real;
  151. begin
  152. with zden do denom := (re * re) + (im * im);
  153. if denom = 0.0
  154. then begin
  155. writeln('******** function Cdiv ********');
  156. writeln('******* DIVISION BY ZERO ******');
  157. runerror(200);
  158. end
  159. else begin
  160. z.re := ((znum.re * zden.re) + (znum.im * zden.im)) / denom;
  161. z.im := ((znum.im * zden.re) - (znum.re * zden.im)) / denom;
  162. end;
  163. end;
  164. operator / (znum : complex; r : real) z : complex;
  165. (* division : z := znum / r *)
  166. begin
  167. if r = 0.0
  168. then begin
  169. writeln('******** function Cdiv ********');
  170. writeln('******* DIVISION BY ZERO ******');
  171. runerror(200);
  172. end
  173. else begin
  174. z.re := znum.re / r;
  175. z.im := znum.im / r;
  176. end;
  177. end;
  178. operator / (r : real; zden : complex) z : complex;
  179. (* division : z := r / zden *)
  180. var denom : real;
  181. begin
  182. with zden do denom := (re * re) + (im * im);
  183. if denom = 0.0
  184. then begin
  185. writeln('******** function Cdiv ********');
  186. writeln('******* DIVISION BY ZERO ******');
  187. runerror(200);
  188. end
  189. else begin
  190. z.re := (r * zden.re) / denom;
  191. z.im := - (r * zden.im) / denom;
  192. end;
  193. end;
  194. (* fonctions complexes particulieres *)
  195. function cneg (z : complex) : complex;
  196. (* negatif : cneg = - z *)
  197. begin
  198. cneg.re := - z.re;
  199. cneg.im := - z.im;
  200. end;
  201. function cmod (z : complex): real;
  202. (* module : r = |z| *)
  203. begin
  204. with z do cmod := sqrt((re * re) + (im * im))
  205. end;
  206. function carg (z : complex): real;
  207. (* argument : 0 / z = p ei0 *)
  208. begin
  209. carg := arctan2(z.re, z.im)
  210. end;
  211. function ccong (z : complex) : complex;
  212. (* conjuge : z := x + i.y alors r = x - i.y *)
  213. begin
  214. ccong.re := z.re;
  215. ccong.im := - z.im;
  216. end;
  217. function cinv (z : complex) : complex;
  218. (* inverse : r := 1 / z *)
  219. var denom : real;
  220. begin
  221. with z do denom := (re * re) + (im * im);
  222. if denom = 0.0
  223. then begin
  224. writeln('******** function Cinv ********');
  225. writeln('******* DIVISION BY ZERO ******');
  226. runerror(200);
  227. end
  228. else begin
  229. cinv.re := z.re / denom;
  230. cinv.im := - z.im / denom
  231. end;
  232. end;
  233. function ciz (z : complex) : complex;
  234. (* multiplication par i *)
  235. (* z = x + i.y , r = i.z = - y + i.x *)
  236. begin
  237. ciz.re := - z.im;
  238. ciz.im := z.re;
  239. end;
  240. function c_iz (z : complex) : complex;
  241. (* multiplication par -i *)
  242. (* z = x + i.y , r = -i.z = y - i.x *)
  243. begin
  244. c_iz.re := z.im;
  245. c_iz.im := - z.re;
  246. end;
  247. function czero : complex;
  248. (* return a zero complex *)
  249. begin
  250. czero.re := 0.0;
  251. czero.im := 0.0;
  252. end;
  253. operator = (z1, z2 : complex) b : boolean;
  254. (* returns TRUE if z1 = z2 *)
  255. begin
  256. b := (z1.re = z2.re) and (z1.im = z2.im)
  257. end;
  258. operator = (z1 : complex; r :real) b : boolean;
  259. (* returns TRUE if z1 = r *)
  260. begin
  261. b := (z1.re = r) and (z1.im = 0.0)
  262. end;
  263. operator = (r : real; z1 : complex) b : boolean;
  264. (* returns TRUE if z1 = r *)
  265. begin
  266. b := (z1.re = r) and (z1.im = 0.0)
  267. end;
  268. (* fonctions elementaires *)
  269. function cexp (z : complex) : complex;
  270. (* exponantielle : r := exp(z) *)
  271. (* exp(x + iy) = exp(x).exp(iy) = exp(x).[cos(y) + i sin(y)] *)
  272. var expz : real;
  273. begin
  274. expz := exp(z.re);
  275. cexp.re := expz * cos(z.im);
  276. cexp.im := expz * sin(z.im);
  277. end;
  278. function cln (z : complex) : complex;
  279. (* logarithme naturel : r := ln(z) *)
  280. (* ln( p exp(i0)) = ln(p) + i0 + 2kpi *)
  281. var modz : real;
  282. begin
  283. with z do modz := (re * re) + (im * im);
  284. if modz = 0.0
  285. then begin
  286. writeln('********* function Cln *********');
  287. writeln('****** LOGARITHME OF ZERO ******');
  288. runerror(200)
  289. end
  290. else begin
  291. cln.re := ln(modz);
  292. cln.im := arctan2(z.re, z.im);
  293. end
  294. end;
  295. function csqrt (z : complex) : complex;
  296. (* racine carre : r := sqrt(z) *)
  297. var root, q : real;
  298. begin
  299. if (z.re <> 0.0) or (z.im <> 0.0)
  300. then begin
  301. root := sqrt(0.5 * (abs(z.re) + cmod(z)));
  302. q := z.im / (2.0 * root);
  303. if z.re >= 0.0 then
  304. begin
  305. csqrt.re := root;
  306. csqrt.im := q;
  307. end
  308. else if z.im < 0.0
  309. then
  310. begin
  311. csqrt.re := - q;
  312. csqrt.im := - root
  313. end
  314. else
  315. begin
  316. csqrt.re := q;
  317. csqrt.im := root
  318. end
  319. end
  320. else result := z;
  321. end;
  322. operator ^ (z1, z2 : complex) z : complex;
  323. (* multiplication : z := z1 * z2 *)
  324. begin
  325. z.re := (z1.re * z2.re) - (z1.im * z2.im);
  326. z.im := (z1.re * z2.im) + (z1.im * z2.re);
  327. end;
  328. operator * (z1 : complex; r : real) z : complex;
  329. (* multiplication : z := z1 * r *)
  330. begin
  331. z.re := z1.re * r;
  332. z.im := z1.im * r;
  333. end;
  334. operator * (r : real; z1 : complex) z : complex;
  335. (* multiplication : z := r + z1 *)
  336. begin
  337. z.re := z1.re * r;
  338. z.im := z1.im * r;
  339. end;
  340. (* fonctions trigonometriques directes *)
  341. function ccos (z : complex) : complex;
  342. (* cosinus complex *)
  343. (* cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy) *)
  344. (* cos(ix) = ch(x) et sin(ix) = i.sh(x) *)
  345. begin
  346. ccos.re := cos(z.re) * ch(z.im);
  347. ccos.im := - sin(z.re) * sh(z.im);
  348. end;
  349. function csin (z : complex) : complex;
  350. (* sinus complex *)
  351. (* sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy) *)
  352. (* cos(ix) = ch(x) et sin(ix) = i.sh(x) *)
  353. begin
  354. csin.re := sin(z.re) * ch(z.im);
  355. csin.im := cos(z.re) * sh(z.im);
  356. end;
  357. function ctg (z : complex) : complex;
  358. (* tangente *)
  359. var ccosz, temp : complex;
  360. begin
  361. ccosz := ccos(z);
  362. if (ccosz.re = 0.0) and (ccosz.im = 0.0)
  363. then begin
  364. writeln('********* function Ctg *********');
  365. writeln('******* DIVISION BY ZERO ******');
  366. runerror(200)
  367. end
  368. else begin
  369. temp := csin(z);
  370. ctg := temp / ccosz;
  371. end
  372. end;
  373. (* fonctions trigonometriques inverses *)
  374. function carc_cos (z : complex) : complex;
  375. (* arc cosinus complex *)
  376. (* arccos(z) = -i.argch(z) *)
  377. begin
  378. z := carg_ch(z);
  379. carc_cos := c_iz(z);
  380. end;
  381. function carc_sin (z : complex) : complex;
  382. (* arc sinus complex *)
  383. (* arcsin(z) = -i.argsh(i.z) *)
  384. begin
  385. z := ciz(z);
  386. z := carg_sh(z);
  387. carc_sin := c_iz(z);
  388. end;
  389. function carc_tg (z : complex) : complex;
  390. (* arc tangente complex *)
  391. (* arctg(z) = -i.argth(i.z) *)
  392. begin
  393. z := ciz(z);
  394. z := carg_th(z);
  395. carc_tg := c_iz(z);
  396. end;
  397. (* fonctions trigonometriques hyperboliques *)
  398. function cch (z : complex) : complex;
  399. (* cosinus hyperbolique *)
  400. (* ch(x+iy) = ch(x).ch(iy) + sh(x).sh(iy) *)
  401. (* ch(iy) = cos(y) et sh(iy) = i.sin(y) *)
  402. begin
  403. cch.re := ch(z.re) * cos(z.im);
  404. cch.im := sh(z.re) * sin(z.im);
  405. end;
  406. function csh (z : complex) : complex;
  407. (* sinus hyperbolique *)
  408. (* sh(x+iy) = sh(x).ch(iy) + ch(x).sh(iy) *)
  409. (* ch(iy) = cos(y) et sh(iy) = i.sin(y) *)
  410. begin
  411. csh.re := sh(z.re) * cos(z.im);
  412. csh.im := ch(z.re) * sin(z.im);
  413. end;
  414. function cth (z : complex) : complex;
  415. (* tangente hyperbolique complex *)
  416. (* th(x) = sh(x) / ch(x) *)
  417. (* ch(x) > 1 qq x *)
  418. var temp : complex;
  419. begin
  420. temp := cch(z);
  421. z := csh(z);
  422. cth := z / temp;
  423. end;
  424. (* fonctions trigonometriques hyperboliques inverses *)
  425. function carg_ch (z : complex) : complex;
  426. (* arg cosinus hyperbolique *)
  427. (* _________ *)
  428. (* argch(z) = -/+ ln(z + i.V 1 - z.z) *)
  429. var temp : complex;
  430. begin
  431. with temp do begin
  432. re := 1 - z.re * z.re + z.im * z.im;
  433. im := - 2 * z.re * z.im
  434. end;
  435. temp := csqrt(temp);
  436. temp := ciz(temp);
  437. temp := temp + z;
  438. temp := cln(temp);
  439. carg_ch := cneg(temp);
  440. end;
  441. function carg_sh (z : complex) : complex;
  442. (* arc sinus hyperbolique *)
  443. (* ________ *)
  444. (* argsh(z) = ln(z + V 1 + z.z) *)
  445. var temp : complex;
  446. begin
  447. with temp do begin
  448. re := 1 + z.re * z.re - z.im * z.im;
  449. im := 2 * z.re * z.im
  450. end;
  451. temp := csqrt(temp);
  452. temp := cadd(temp, z);
  453. carg_sh := cln(temp);
  454. end;
  455. function carg_th (z : complex) : complex;
  456. (* arc tangente hyperbolique *)
  457. (* argth(z) = 1/2 ln((z + 1) / (1 - z)) *)
  458. var temp : complex;
  459. begin
  460. with temp do begin
  461. re := 1 + z.re;
  462. im := z.im
  463. end;
  464. with result do begin
  465. re := 1 - re;
  466. im := - im
  467. end;
  468. result := temp / result;
  469. carg_th.re := 0.5 * re;
  470. carg_th.im := 0.5 * im
  471. end;
  472. end.
  473. {
  474. $Log$
  475. Revision 1.2 1998-05-12 10:42:44 peter
  476. * moved getopts to inc/, all supported OS's need argc,argv exported
  477. + strpas, strlen are now exported in the systemunit
  478. * removed logs
  479. * removed $ifdef ver_above
  480. }