ucomplex.pp 16 KB

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