clogf.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. /* clogf.c
  2. *
  3. * Complex natural logarithm
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * void clogf();
  10. * cmplxf z, w;
  11. *
  12. * clogf( &z, &w );
  13. *
  14. *
  15. *
  16. * DESCRIPTION:
  17. *
  18. * Returns complex logarithm to the base e (2.718...) of
  19. * the complex argument x.
  20. *
  21. * If z = x + iy, r = sqrt( x**2 + y**2 ),
  22. * then
  23. * w = log(r) + i arctan(y/x).
  24. *
  25. * The arctangent ranges from -PI to +PI.
  26. *
  27. *
  28. * ACCURACY:
  29. *
  30. * Relative error:
  31. * arithmetic domain # trials peak rms
  32. * IEEE -10,+10 30000 1.9e-6 6.2e-8
  33. *
  34. * Larger relative error can be observed for z near 1 +i0.
  35. * In IEEE arithmetic the peak absolute error is 3.1e-7.
  36. *
  37. */
  38. #include <math.h>
  39. extern float MAXNUMF, MACHEPF, PIF, PIO2F;
  40. #ifdef ANSIC
  41. float cabsf(cmplxf *), sqrtf(float), logf(float), atan2f(float, float);
  42. float expf(float), sinf(float), cosf(float);
  43. float coshf(float), sinhf(float), asinf(float);
  44. float ctansf(cmplxf *), redupif(float);
  45. void cchshf( float, float *, float * );
  46. void caddf( cmplxf *, cmplxf *, cmplxf * );
  47. void csqrtf( cmplxf *, cmplxf * );
  48. #else
  49. float cabsf(), sqrtf(), logf(), atan2f();
  50. float expf(), sinf(), cosf();
  51. float coshf(), sinhf(), asinf();
  52. float ctansf(), redupif();
  53. void cchshf(), csqrtf(), caddf();
  54. #endif
  55. #define fabsf(x) ( (x) < 0 ? -(x) : (x) )
  56. void clogf( z, w )
  57. register cmplxf *z, *w;
  58. {
  59. float p, rr;
  60. /*rr = sqrtf( z->r * z->r + z->i * z->i );*/
  61. rr = cabsf(z);
  62. p = logf(rr);
  63. #if ANSIC
  64. rr = atan2f( z->i, z->r );
  65. #else
  66. rr = atan2f( z->r, z->i );
  67. if( rr > PIF )
  68. rr -= PIF + PIF;
  69. #endif
  70. w->i = rr;
  71. w->r = p;
  72. }
  73. /* cexpf()
  74. *
  75. * Complex exponential function
  76. *
  77. *
  78. *
  79. * SYNOPSIS:
  80. *
  81. * void cexpf();
  82. * cmplxf z, w;
  83. *
  84. * cexpf( &z, &w );
  85. *
  86. *
  87. *
  88. * DESCRIPTION:
  89. *
  90. * Returns the exponential of the complex argument z
  91. * into the complex result w.
  92. *
  93. * If
  94. * z = x + iy,
  95. * r = exp(x),
  96. *
  97. * then
  98. *
  99. * w = r cos y + i r sin y.
  100. *
  101. *
  102. * ACCURACY:
  103. *
  104. * Relative error:
  105. * arithmetic domain # trials peak rms
  106. * IEEE -10,+10 30000 1.4e-7 4.5e-8
  107. *
  108. */
  109. void cexpf( z, w )
  110. register cmplxf *z, *w;
  111. {
  112. float r;
  113. r = expf( z->r );
  114. w->r = r * cosf( z->i );
  115. w->i = r * sinf( z->i );
  116. }
  117. /* csinf()
  118. *
  119. * Complex circular sine
  120. *
  121. *
  122. *
  123. * SYNOPSIS:
  124. *
  125. * void csinf();
  126. * cmplxf z, w;
  127. *
  128. * csinf( &z, &w );
  129. *
  130. *
  131. *
  132. * DESCRIPTION:
  133. *
  134. * If
  135. * z = x + iy,
  136. *
  137. * then
  138. *
  139. * w = sin x cosh y + i cos x sinh y.
  140. *
  141. *
  142. *
  143. * ACCURACY:
  144. *
  145. * Relative error:
  146. * arithmetic domain # trials peak rms
  147. * IEEE -10,+10 30000 1.9e-7 5.5e-8
  148. *
  149. */
  150. void csinf( z, w )
  151. register cmplxf *z, *w;
  152. {
  153. float ch, sh;
  154. cchshf( z->i, &ch, &sh );
  155. w->r = sinf( z->r ) * ch;
  156. w->i = cosf( z->r ) * sh;
  157. }
  158. /* calculate cosh and sinh */
  159. void cchshf( float xx, float *c, float *s )
  160. {
  161. float x, e, ei;
  162. x = xx;
  163. if( fabsf(x) <= 0.5f )
  164. {
  165. *c = coshf(x);
  166. *s = sinhf(x);
  167. }
  168. else
  169. {
  170. e = expf(x);
  171. ei = 0.5f/e;
  172. e = 0.5f * e;
  173. *s = e - ei;
  174. *c = e + ei;
  175. }
  176. }
  177. /* ccosf()
  178. *
  179. * Complex circular cosine
  180. *
  181. *
  182. *
  183. * SYNOPSIS:
  184. *
  185. * void ccosf();
  186. * cmplxf z, w;
  187. *
  188. * ccosf( &z, &w );
  189. *
  190. *
  191. *
  192. * DESCRIPTION:
  193. *
  194. * If
  195. * z = x + iy,
  196. *
  197. * then
  198. *
  199. * w = cos x cosh y - i sin x sinh y.
  200. *
  201. *
  202. *
  203. * ACCURACY:
  204. *
  205. * Relative error:
  206. * arithmetic domain # trials peak rms
  207. * IEEE -10,+10 30000 1.8e-7 5.5e-8
  208. */
  209. void ccosf( z, w )
  210. register cmplxf *z, *w;
  211. {
  212. float ch, sh;
  213. cchshf( z->i, &ch, &sh );
  214. w->r = cosf( z->r ) * ch;
  215. w->i = -sinf( z->r ) * sh;
  216. }
  217. /* ctanf()
  218. *
  219. * Complex circular tangent
  220. *
  221. *
  222. *
  223. * SYNOPSIS:
  224. *
  225. * void ctanf();
  226. * cmplxf z, w;
  227. *
  228. * ctanf( &z, &w );
  229. *
  230. *
  231. *
  232. * DESCRIPTION:
  233. *
  234. * If
  235. * z = x + iy,
  236. *
  237. * then
  238. *
  239. * sin 2x + i sinh 2y
  240. * w = --------------------.
  241. * cos 2x + cosh 2y
  242. *
  243. * On the real axis the denominator is zero at odd multiples
  244. * of PI/2. The denominator is evaluated by its Taylor
  245. * series near these points.
  246. *
  247. *
  248. * ACCURACY:
  249. *
  250. * Relative error:
  251. * arithmetic domain # trials peak rms
  252. * IEEE -10,+10 30000 3.3e-7 5.1e-8
  253. */
  254. void ctanf( z, w )
  255. register cmplxf *z, *w;
  256. {
  257. float d;
  258. d = cosf( 2.0f * z->r ) + coshf( 2.0f * z->i );
  259. if( fabsf(d) < 0.25f )
  260. d = ctansf(z);
  261. if( d == 0.0f )
  262. {
  263. mtherr( "ctanf", OVERFLOW );
  264. w->r = MAXNUMF;
  265. w->i = MAXNUMF;
  266. return;
  267. }
  268. w->r = sinf( 2.0f * z->r ) / d;
  269. w->i = sinhf( 2.0f * z->i ) / d;
  270. }
  271. /* ccotf()
  272. *
  273. * Complex circular cotangent
  274. *
  275. *
  276. *
  277. * SYNOPSIS:
  278. *
  279. * void ccotf();
  280. * cmplxf z, w;
  281. *
  282. * ccotf( &z, &w );
  283. *
  284. *
  285. *
  286. * DESCRIPTION:
  287. *
  288. * If
  289. * z = x + iy,
  290. *
  291. * then
  292. *
  293. * sin 2x - i sinh 2y
  294. * w = --------------------.
  295. * cosh 2y - cos 2x
  296. *
  297. * On the real axis, the denominator has zeros at even
  298. * multiples of PI/2. Near these points it is evaluated
  299. * by a Taylor series.
  300. *
  301. *
  302. * ACCURACY:
  303. *
  304. * Relative error:
  305. * arithmetic domain # trials peak rms
  306. * IEEE -10,+10 30000 3.6e-7 5.7e-8
  307. * Also tested by ctan * ccot = 1 + i0.
  308. */
  309. void ccotf( z, w )
  310. register cmplxf *z, *w;
  311. {
  312. float d;
  313. d = coshf(2.0f * z->i) - cosf(2.0f * z->r);
  314. if( fabsf(d) < 0.25f )
  315. d = ctansf(z);
  316. if( d == 0.0f )
  317. {
  318. mtherr( "ccotf", OVERFLOW );
  319. w->r = MAXNUMF;
  320. w->i = MAXNUMF;
  321. return;
  322. }
  323. d = 1.0f/d;
  324. w->r = sinf( 2.0f * z->r ) * d;
  325. w->i = -sinhf( 2.0f * z->i ) * d;
  326. }
  327. /* Program to subtract nearest integer multiple of PI */
  328. /* extended precision value of PI: */
  329. static float DP1 = 3.140625;
  330. static float DP2 = 9.67502593994140625E-4;
  331. static float DP3 = 1.509957990978376432E-7;
  332. float redupif(float xx)
  333. {
  334. float x, t;
  335. long i;
  336. x = xx;
  337. t = x/PIF;
  338. if( t >= 0.0f )
  339. t += 0.5f;
  340. else
  341. t -= 0.5f;
  342. i = t; /* the multiple */
  343. t = i;
  344. t = ((x - t * DP1) - t * DP2) - t * DP3;
  345. return(t);
  346. }
  347. /* Taylor series expansion for cosh(2y) - cos(2x) */
  348. float ctansf(z)
  349. cmplxf *z;
  350. {
  351. float f, x, x2, y, y2, rn, t, d;
  352. x = fabsf( 2.0f * z->r );
  353. y = fabsf( 2.0f * z->i );
  354. x = redupif(x);
  355. x = x * x;
  356. y = y * y;
  357. x2 = 1.0f;
  358. y2 = 1.0f;
  359. f = 1.0f;
  360. rn = 0.0f;
  361. d = 0.0f;
  362. do
  363. {
  364. rn += 1.0f;
  365. f *= rn;
  366. rn += 1.0f;
  367. f *= rn;
  368. x2 *= x;
  369. y2 *= y;
  370. t = y2 + x2;
  371. t /= f;
  372. d += t;
  373. rn += 1.0f;
  374. f *= rn;
  375. rn += 1.0f;
  376. f *= rn;
  377. x2 *= x;
  378. y2 *= y;
  379. t = y2 - x2;
  380. t /= f;
  381. d += t;
  382. }
  383. while( fabsf(t/d) > MACHEPF );
  384. return(d);
  385. }
  386. /* casinf()
  387. *
  388. * Complex circular arc sine
  389. *
  390. *
  391. *
  392. * SYNOPSIS:
  393. *
  394. * void casinf();
  395. * cmplxf z, w;
  396. *
  397. * casinf( &z, &w );
  398. *
  399. *
  400. *
  401. * DESCRIPTION:
  402. *
  403. * Inverse complex sine:
  404. *
  405. * 2
  406. * w = -i clog( iz + csqrt( 1 - z ) ).
  407. *
  408. *
  409. * ACCURACY:
  410. *
  411. * Relative error:
  412. * arithmetic domain # trials peak rms
  413. * IEEE -10,+10 30000 1.1e-5 1.5e-6
  414. * Larger relative error can be observed for z near zero.
  415. *
  416. */
  417. void casinf( z, w )
  418. cmplxf *z, *w;
  419. {
  420. float x, y;
  421. static cmplxf ca, ct, zz, z2;
  422. /*
  423. float cn, n;
  424. static float a, b, s, t, u, v, y2;
  425. static cmplxf sum;
  426. */
  427. x = z->r;
  428. y = z->i;
  429. if( y == 0.0f )
  430. {
  431. if( fabsf(x) > 1.0f )
  432. {
  433. w->r = PIO2F;
  434. w->i = 0.0f;
  435. mtherr( "casinf", DOMAIN );
  436. }
  437. else
  438. {
  439. w->r = asinf(x);
  440. w->i = 0.0f;
  441. }
  442. return;
  443. }
  444. /* Power series expansion */
  445. /*
  446. b = cabsf(z);
  447. if( b < 0.125 )
  448. {
  449. z2.r = (x - y) * (x + y);
  450. z2.i = 2.0 * x * y;
  451. cn = 1.0;
  452. n = 1.0;
  453. ca.r = x;
  454. ca.i = y;
  455. sum.r = x;
  456. sum.i = y;
  457. do
  458. {
  459. ct.r = z2.r * ca.r - z2.i * ca.i;
  460. ct.i = z2.r * ca.i + z2.i * ca.r;
  461. ca.r = ct.r;
  462. ca.i = ct.i;
  463. cn *= n;
  464. n += 1.0;
  465. cn /= n;
  466. n += 1.0;
  467. b = cn/n;
  468. ct.r *= b;
  469. ct.i *= b;
  470. sum.r += ct.r;
  471. sum.i += ct.i;
  472. b = fabsf(ct.r) + fabsf(ct.i);
  473. }
  474. while( b > MACHEPF );
  475. w->r = sum.r;
  476. w->i = sum.i;
  477. return;
  478. }
  479. */
  480. ca.r = x;
  481. ca.i = y;
  482. ct.r = -ca.i; /* iz */
  483. ct.i = ca.r;
  484. /* sqrt( 1 - z*z) */
  485. /* cmul( &ca, &ca, &zz ) */
  486. zz.r = (ca.r - ca.i) * (ca.r + ca.i); /*x * x - y * y */
  487. zz.i = 2.0f * ca.r * ca.i;
  488. zz.r = 1.0f - zz.r;
  489. zz.i = -zz.i;
  490. csqrtf( &zz, &z2 );
  491. caddf( &z2, &ct, &zz );
  492. clogf( &zz, &zz );
  493. w->r = zz.i; /* mult by 1/i = -i */
  494. w->i = -zz.r;
  495. return;
  496. }
  497. /* cacosf()
  498. *
  499. * Complex circular arc cosine
  500. *
  501. *
  502. *
  503. * SYNOPSIS:
  504. *
  505. * void cacosf();
  506. * cmplxf z, w;
  507. *
  508. * cacosf( &z, &w );
  509. *
  510. *
  511. *
  512. * DESCRIPTION:
  513. *
  514. *
  515. * w = arccos z = PI/2 - arcsin z.
  516. *
  517. *
  518. *
  519. *
  520. * ACCURACY:
  521. *
  522. * Relative error:
  523. * arithmetic domain # trials peak rms
  524. * IEEE -10,+10 30000 9.2e-6 1.2e-6
  525. *
  526. */
  527. void cacosf( z, w )
  528. cmplxf *z, *w;
  529. {
  530. casinf( z, w );
  531. w->r = PIO2F - w->r;
  532. w->i = -w->i;
  533. }
  534. /* catan()
  535. *
  536. * Complex circular arc tangent
  537. *
  538. *
  539. *
  540. * SYNOPSIS:
  541. *
  542. * void catan();
  543. * cmplxf z, w;
  544. *
  545. * catan( &z, &w );
  546. *
  547. *
  548. *
  549. * DESCRIPTION:
  550. *
  551. * If
  552. * z = x + iy,
  553. *
  554. * then
  555. * 1 ( 2x )
  556. * Re w = - arctan(-----------) + k PI
  557. * 2 ( 2 2)
  558. * (1 - x - y )
  559. *
  560. * ( 2 2)
  561. * 1 (x + (y+1) )
  562. * Im w = - log(------------)
  563. * 4 ( 2 2)
  564. * (x + (y-1) )
  565. *
  566. * Where k is an arbitrary integer.
  567. *
  568. *
  569. *
  570. * ACCURACY:
  571. *
  572. * Relative error:
  573. * arithmetic domain # trials peak rms
  574. * IEEE -10,+10 30000 2.3e-6 5.2e-8
  575. *
  576. */
  577. void catanf( z, w )
  578. cmplxf *z, *w;
  579. {
  580. float a, t, x, x2, y;
  581. x = z->r;
  582. y = z->i;
  583. if( (x == 0.0f) && (y > 1.0f) )
  584. goto ovrf;
  585. x2 = x * x;
  586. a = 1.0f - x2 - (y * y);
  587. if( a == 0.0f )
  588. goto ovrf;
  589. #if ANSIC
  590. t = 0.5f * atan2f( 2.0f * x, a );
  591. #else
  592. t = 0.5f * atan2f( a, 2.0f * x );
  593. #endif
  594. w->r = redupif( t );
  595. t = y - 1.0f;
  596. a = x2 + (t * t);
  597. if( a == 0.0f )
  598. goto ovrf;
  599. t = y + 1.0f;
  600. a = (x2 + (t * t))/a;
  601. w->i = 0.25f*logf(a);
  602. return;
  603. ovrf:
  604. mtherr( "catanf", OVERFLOW );
  605. w->r = MAXNUMF;
  606. w->i = MAXNUMF;
  607. }