ucomplex.pp 16 KB

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