ucomplex.pp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Pierre Muller,
  4. member of the Free Pascal development team.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. Unit UComplex;
  12. { created for FPC by Pierre Muller }
  13. { inpired from the complex unit from JD GAYRARD mai 95 }
  14. { FPC supports operator overloading }
  15. interface
  16. uses math;
  17. type complex = record
  18. re : real;
  19. im : real;
  20. end;
  21. pcomplex = ^complex;
  22. const i : complex = (re : 0.0; im : 1.0);
  23. _0 : complex = (re : 0.0; im : 0.0);
  24. { assignment overloading is also used in type conversions
  25. (beware also in implicit type conversions)
  26. after this operator any real can be passed to a function
  27. as a complex arg !! }
  28. operator := (r : real) z : complex;
  29. {$ifdef TEST_INLINE}
  30. inline;
  31. {$endif TEST_INLINE}
  32. { operator := (i : longint) z : complex;
  33. not needed because longint can be converted to real }
  34. { four operator : +, -, * , / and comparison = }
  35. operator + (z1, z2 : complex) z : complex;
  36. {$ifdef TEST_INLINE}
  37. inline;
  38. {$endif TEST_INLINE}
  39. { these ones are created because the code
  40. is simpler and thus faster }
  41. operator + (z1 : complex; r : real) z : complex;
  42. {$ifdef TEST_INLINE}
  43. inline;
  44. {$endif TEST_INLINE}
  45. operator + (r : real; z1 : complex) z : complex;
  46. {$ifdef TEST_INLINE}
  47. inline;
  48. {$endif TEST_INLINE}
  49. operator - (z1, z2 : complex) z : complex;
  50. {$ifdef TEST_INLINE}
  51. inline;
  52. {$endif TEST_INLINE}
  53. operator - (z1 : complex;r : real) z : complex;
  54. {$ifdef TEST_INLINE}
  55. inline;
  56. {$endif TEST_INLINE}
  57. operator - (r : real; z1 : complex) z : complex;
  58. {$ifdef TEST_INLINE}
  59. inline;
  60. {$endif TEST_INLINE}
  61. operator * (z1, z2 : complex) z : complex;
  62. {$ifdef TEST_INLINE}
  63. inline;
  64. {$endif TEST_INLINE}
  65. operator * (z1 : complex; r : real) z : complex;
  66. {$ifdef TEST_INLINE}
  67. inline;
  68. {$endif TEST_INLINE}
  69. operator * (r : real; z1 : complex) z : complex;
  70. {$ifdef TEST_INLINE}
  71. inline;
  72. {$endif TEST_INLINE}
  73. operator / (znum, zden : complex) z : complex;
  74. {$ifdef TEST_INLINE}
  75. inline;
  76. {$endif TEST_INLINE}
  77. operator / (znum : complex; r : real) z : complex;
  78. {$ifdef TEST_INLINE}
  79. inline;
  80. {$endif TEST_INLINE}
  81. operator / (r : real; zden : complex) z : complex;
  82. {$ifdef TEST_INLINE}
  83. inline;
  84. {$endif TEST_INLINE}
  85. { ** is the exponentiation operator }
  86. operator ** (z1, z2 : complex) z : complex;
  87. {$ifdef TEST_INLINE}
  88. inline;
  89. {$endif TEST_INLINE}
  90. operator ** (z1 : complex; r : real) z : complex;
  91. {$ifdef TEST_INLINE}
  92. inline;
  93. {$endif TEST_INLINE}
  94. operator ** (r : real; z1 : complex) z : complex;
  95. {$ifdef TEST_INLINE}
  96. inline;
  97. {$endif TEST_INLINE}
  98. operator = (z1, z2 : complex) b : boolean;
  99. {$ifdef TEST_INLINE}
  100. inline;
  101. {$endif TEST_INLINE}
  102. operator = (z1 : complex;r : real) b : boolean;
  103. {$ifdef TEST_INLINE}
  104. inline;
  105. {$endif TEST_INLINE}
  106. operator = (r : real; z1 : complex) b : boolean;
  107. {$ifdef TEST_INLINE}
  108. inline;
  109. {$endif TEST_INLINE}
  110. operator - (z1 : complex) z : complex;
  111. {$ifdef TEST_INLINE}
  112. inline;
  113. {$endif TEST_INLINE}
  114. { complex functions }
  115. function cong (z : complex) : complex; { conjuge }
  116. { inverse function 1/z }
  117. function cinv (z : complex) : complex;
  118. { complex functions with real return values }
  119. function cmod (z : complex) : real; { module }
  120. function carg (z : complex) : real; { argument : a / z = p.e^ia }
  121. { fonctions elementaires }
  122. function cexp (z : complex) : complex; { exponential }
  123. function cln (z : complex) : complex; { natural logarithm }
  124. function csqrt (z : complex) : complex; { square root }
  125. { complex trigonometric functions }
  126. function ccos (z : complex) : complex; { cosinus }
  127. function csin (z : complex) : complex; { sinus }
  128. function ctg (z : complex) : complex; { tangent }
  129. { inverse complex trigonometric functions }
  130. function carc_cos (z : complex) : complex; { arc cosinus }
  131. function carc_sin (z : complex) : complex; { arc sinus }
  132. function carc_tg (z : complex) : complex; { arc tangent }
  133. { hyperbolic complex functions }
  134. function cch (z : complex) : complex; { hyperbolic cosinus }
  135. function csh (z : complex) : complex; { hyperbolic sinus }
  136. function cth (z : complex) : complex; { hyperbolic tangent }
  137. { inverse hyperbolic complex functions }
  138. function carg_ch (z : complex) : complex; { hyperbolic arc cosinus }
  139. function carg_sh (z : complex) : complex; { hyperbolic arc sinus }
  140. function carg_th (z : complex) : complex; { hyperbolic arc tangente }
  141. { functions to write out a complex value }
  142. function cstr(z : complex) : string;
  143. function cstr(z:complex;len : integer) : string;
  144. function cstr(z:complex;len,dec : integer) : string;
  145. implementation
  146. operator := (r : real) z : complex;
  147. {$ifdef TEST_INLINE}
  148. inline;
  149. {$endif TEST_INLINE}
  150. begin
  151. z.re:=r;
  152. z.im:=0.0;
  153. end;
  154. { four base operations +, -, * , / }
  155. operator + (z1, z2 : complex) z : complex;
  156. {$ifdef TEST_INLINE}
  157. inline;
  158. {$endif TEST_INLINE}
  159. { addition : z := z1 + z2 }
  160. begin
  161. z.re := z1.re + z2.re;
  162. z.im := z1.im + z2.im;
  163. end;
  164. operator + (z1 : complex; r : real) z : complex;
  165. { addition : z := z1 + r }
  166. {$ifdef TEST_INLINE}
  167. inline;
  168. {$endif TEST_INLINE}
  169. begin
  170. z.re := z1.re + r;
  171. z.im := z1.im;
  172. end;
  173. operator + (r : real; z1 : complex) z : complex;
  174. { addition : z := r + z1 }
  175. {$ifdef TEST_INLINE}
  176. inline;
  177. {$endif TEST_INLINE}
  178. begin
  179. z.re := z1.re + r;
  180. z.im := z1.im;
  181. end;
  182. operator - (z1, z2 : complex) z : complex;
  183. {$ifdef TEST_INLINE}
  184. inline;
  185. {$endif TEST_INLINE}
  186. { substraction : z := z1 - z2 }
  187. begin
  188. z.re := z1.re - z2.re;
  189. z.im := z1.im - z2.im;
  190. end;
  191. operator - (z1 : complex; r : real) z : complex;
  192. {$ifdef TEST_INLINE}
  193. inline;
  194. {$endif TEST_INLINE}
  195. { substraction : z := z1 - r }
  196. begin
  197. z.re := z1.re - r;
  198. z.im := z1.im;
  199. end;
  200. operator - (z1 : complex) z : complex;
  201. {$ifdef TEST_INLINE}
  202. inline;
  203. {$endif TEST_INLINE}
  204. { substraction : z := - z1 }
  205. begin
  206. z.re := -z1.re;
  207. z.im := -z1.im;
  208. end;
  209. operator - (r : real; z1 : complex) z : complex;
  210. {$ifdef TEST_INLINE}
  211. inline;
  212. {$endif TEST_INLINE}
  213. { substraction : z := r - z1 }
  214. begin
  215. z.re := r - z1.re;
  216. z.im := - z1.im;
  217. end;
  218. operator * (z1, z2 : complex) z : complex;
  219. { multiplication : z := z1 * z2 }
  220. {$ifdef TEST_INLINE}
  221. inline;
  222. {$endif TEST_INLINE}
  223. begin
  224. z.re := (z1.re * z2.re) - (z1.im * z2.im);
  225. z.im := (z1.re * z2.im) + (z1.im * z2.re);
  226. end;
  227. operator * (z1 : complex; r : real) z : complex;
  228. {$ifdef TEST_INLINE}
  229. inline;
  230. {$endif TEST_INLINE}
  231. { multiplication : z := z1 * r }
  232. begin
  233. z.re := z1.re * r;
  234. z.im := z1.im * r;
  235. end;
  236. operator * (r : real; z1 : complex) z : complex;
  237. {$ifdef TEST_INLINE}
  238. inline;
  239. {$endif TEST_INLINE}
  240. { multiplication : z := r * z1 }
  241. begin
  242. z.re := z1.re * r;
  243. z.im := z1.im * r;
  244. end;
  245. operator / (znum, zden : complex) z : complex;
  246. {$ifdef TEST_INLINE}
  247. inline;
  248. {$endif TEST_INLINE}
  249. { division : z := znum / zden }
  250. var
  251. denom : real;
  252. begin
  253. with zden do denom := (re * re) + (im * im);
  254. { generates a fpu exception if denom=0 as for reals }
  255. z.re := ((znum.re * zden.re) + (znum.im * zden.im)) / denom;
  256. z.im := ((znum.im * zden.re) - (znum.re * zden.im)) / denom;
  257. end;
  258. operator / (znum : complex; r : real) z : complex;
  259. { division : z := znum / r }
  260. begin
  261. z.re := znum.re / r;
  262. z.im := znum.im / r;
  263. end;
  264. operator / (r : real; zden : complex) z : complex;
  265. { division : z := r / zden }
  266. var denom : real;
  267. begin
  268. with zden do denom := (re * re) + (im * im);
  269. { generates a fpu exception if denom=0 as for reals }
  270. z.re := (r * zden.re) / denom;
  271. z.im := - (r * zden.im) / denom;
  272. end;
  273. function cmod (z : complex): real;
  274. { module : r = |z| }
  275. begin
  276. with z do
  277. cmod := sqrt((re * re) + (im * im));
  278. end;
  279. function carg (z : complex): real;
  280. { argument : 0 / z = p ei0 }
  281. begin
  282. carg := arctan2(z.re, z.im);
  283. end;
  284. function cong (z : complex) : complex;
  285. { complex conjugee :
  286. if z := x + i.y
  287. then cong is x - i.y }
  288. begin
  289. cong.re := z.re;
  290. cong.im := - z.im;
  291. end;
  292. function cinv (z : complex) : complex;
  293. { inverse : r := 1 / z }
  294. var
  295. denom : real;
  296. begin
  297. with z do denom := (re * re) + (im * im);
  298. { generates a fpu exception if denom=0 as for reals }
  299. cinv.re:=z.re/denom;
  300. cinv.im:=-z.im/denom;
  301. end;
  302. operator = (z1, z2 : complex) b : boolean;
  303. { returns TRUE if z1 = z2 }
  304. begin
  305. b := (z1.re = z2.re) and (z1.im = z2.im);
  306. end;
  307. operator = (z1 : complex; r :real) b : boolean;
  308. { returns TRUE if z1 = r }
  309. begin
  310. b := (z1.re = r) and (z1.im = 0.0)
  311. end;
  312. operator = (r : real; z1 : complex) b : boolean;
  313. { returns TRUE if z1 = r }
  314. begin
  315. b := (z1.re = r) and (z1.im = 0.0)
  316. end;
  317. { fonctions elementaires }
  318. function cexp (z : complex) : complex;
  319. { exponantial : r := exp(z) }
  320. { exp(x + iy) = exp(x).exp(iy) = exp(x).[cos(y) + i sin(y)] }
  321. var expz : real;
  322. begin
  323. expz := exp(z.re);
  324. cexp.re := expz * cos(z.im);
  325. cexp.im := expz * sin(z.im);
  326. end;
  327. function cln (z : complex) : complex;
  328. { natural logarithm : r := ln(z) }
  329. { ln( p exp(i0)) = ln(p) + i0 + 2kpi }
  330. var modz : real;
  331. begin
  332. with z do
  333. modz := (re * re) + (im * im);
  334. cln.re := ln(modz);
  335. cln.im := arctan2(z.re, z.im);
  336. end;
  337. function csqrt (z : complex) : complex;
  338. { square root : r := sqrt(z) }
  339. var
  340. root, q : real;
  341. begin
  342. if (z.re<>0.0) or (z.im<>0.0) then
  343. begin
  344. root := sqrt(0.5 * (abs(z.re) + cmod(z)));
  345. q := z.im / (2.0 * root);
  346. if z.re >= 0.0 then
  347. begin
  348. csqrt.re := root;
  349. csqrt.im := q;
  350. end
  351. else if z.im < 0.0 then
  352. begin
  353. csqrt.re := - q;
  354. csqrt.im := - root
  355. end
  356. else
  357. begin
  358. csqrt.re := q;
  359. csqrt.im := root
  360. end
  361. end
  362. else csqrt := z;
  363. end;
  364. operator ** (z1, z2 : complex) z : complex;
  365. { exp : z := z1 ** z2 }
  366. begin
  367. z := cexp(z2*cln(z1));
  368. end;
  369. operator ** (z1 : complex; r : real) z : complex;
  370. { multiplication : z := z1 * r }
  371. begin
  372. z := cexp( r *cln(z1));
  373. end;
  374. operator ** (r : real; z1 : complex) z : complex;
  375. { multiplication : z := r + z1 }
  376. begin
  377. z := cexp(z1*ln(r));
  378. end;
  379. { direct trigonometric functions }
  380. function ccos (z : complex) : complex;
  381. { complex cosinus }
  382. { cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy) }
  383. { cos(ix) = cosh(x) et sin(ix) = i.sinh(x) }
  384. begin
  385. ccos.re := cos(z.re) * cosh(z.im);
  386. ccos.im := - sin(z.re) * sinh(z.im);
  387. end;
  388. function csin (z : complex) : complex;
  389. { sinus complex }
  390. { sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy) }
  391. { cos(ix) = cosh(x) et sin(ix) = i.sinh(x) }
  392. begin
  393. csin.re := sin(z.re) * cosh(z.im);
  394. csin.im := cos(z.re) * sinh(z.im);
  395. end;
  396. function ctg (z : complex) : complex;
  397. { tangente }
  398. var ccosz, temp : complex;
  399. begin
  400. ccosz := ccos(z);
  401. temp := csin(z);
  402. ctg := temp / ccosz;
  403. end;
  404. { fonctions trigonometriques inverses }
  405. function carc_cos (z : complex) : complex;
  406. { arc cosinus complex }
  407. { arccos(z) = -i.argch(z) }
  408. begin
  409. carc_cos := -i*carg_ch(z);
  410. end;
  411. function carc_sin (z : complex) : complex;
  412. { arc sinus complex }
  413. { arcsin(z) = -i.argsh(i.z) }
  414. begin
  415. carc_sin := -i*carg_sh(i*z);
  416. end;
  417. function carc_tg (z : complex) : complex;
  418. { arc tangente complex }
  419. { arctg(z) = -i.argth(i.z) }
  420. begin
  421. carc_tg := -i*carg_th(i*z);
  422. end;
  423. { hyberbolic complex functions }
  424. function cch (z : complex) : complex;
  425. { hyberbolic cosinus }
  426. { cosh(x+iy) = cosh(x).cosh(iy) + sinh(x).sinh(iy) }
  427. { cosh(iy) = cos(y) et sinh(iy) = i.sin(y) }
  428. begin
  429. cch.re := cosh(z.re) * cos(z.im);
  430. cch.im := sinh(z.re) * sin(z.im);
  431. end;
  432. function csh (z : complex) : complex;
  433. { hyberbolic sinus }
  434. { sinh(x+iy) = sinh(x).cosh(iy) + cosh(x).sinh(iy) }
  435. { cosh(iy) = cos(y) et sinh(iy) = i.sin(y) }
  436. begin
  437. csh.re := sinh(z.re) * cos(z.im);
  438. csh.im := cosh(z.re) * sin(z.im);
  439. end;
  440. function cth (z : complex) : complex;
  441. { hyberbolic complex tangent }
  442. { th(x) = sinh(x) / cosh(x) }
  443. { cosh(x) > 1 qq x }
  444. var temp : complex;
  445. begin
  446. temp := cch(z);
  447. z := csh(z);
  448. cth := z / temp;
  449. end;
  450. { inverse complex hyperbolic functions }
  451. function carg_ch (z : complex) : complex;
  452. { hyberbolic arg cosinus }
  453. { _________ }
  454. { argch(z) = -/+ ln(z + i.V 1 - z.z) }
  455. begin
  456. carg_ch:=-cln(z+i*csqrt(z*z-1.0));
  457. end;
  458. function carg_sh (z : complex) : complex;
  459. { hyperbolic arc sinus }
  460. { ________ }
  461. { argsh(z) = ln(z + V 1 + z.z) }
  462. begin
  463. carg_sh:=cln(z+csqrt(z*z+1.0));
  464. end;
  465. function carg_th (z : complex) : complex;
  466. { hyperbolic arc tangent }
  467. { argth(z) = 1/2 ln((z + 1) / (1 - z)) }
  468. begin
  469. carg_th:=cln((z+1.0)/(z-1.0))/2.0;
  470. end;
  471. { functions to write out a complex value }
  472. function cstr(z : complex) : string;
  473. var
  474. istr : string;
  475. begin
  476. str(z.im,istr);
  477. str(z.re,cstr);
  478. while istr[1]=' ' do
  479. delete(istr,1,1);
  480. if z.im<0 then
  481. cstr:=cstr+istr+'i'
  482. else if z.im>0 then
  483. cstr:=cstr+'+'+istr+'i';
  484. end;
  485. function cstr(z:complex;len : integer) : string;
  486. var
  487. istr : string;
  488. begin
  489. str(z.im:len,istr);
  490. while istr[1]=' ' do
  491. delete(istr,1,1);
  492. str(z.re:len,cstr);
  493. if z.im<0 then
  494. cstr:=cstr+istr+'i'
  495. else if z.im>0 then
  496. cstr:=cstr+'+'+istr+'i';
  497. end;
  498. function cstr(z:complex;len,dec : integer) : string;
  499. var
  500. istr : string;
  501. begin
  502. str(z.im:len:dec,istr);
  503. while istr[1]=' ' do
  504. delete(istr,1,1);
  505. str(z.re:len:dec,cstr);
  506. if z.im<0 then
  507. cstr:=cstr+istr+'i'
  508. else if z.im>0 then
  509. cstr:=cstr+'+'+istr+'i';
  510. end;
  511. end.