clogl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. /* clogl.c
  2. *
  3. * Complex natural logarithm
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * void clogl();
  10. * cmplxl z, w;
  11. *
  12. * clogl( &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. * DEC -10,+10 7000 8.5e-17 1.9e-17
  33. * IEEE -10,+10 30000 5.0e-15 1.1e-16
  34. *
  35. * Larger relative error can be observed for z near 1 +i0.
  36. * In IEEE arithmetic the peak absolute error is 5.2e-16, rms
  37. * absolute error 1.0e-16.
  38. */
  39. #include <math.h>
  40. #ifdef ANSIPROT
  41. static void cchshl ( long double x, long double *c, long double *s );
  42. static long double redupil ( long double x );
  43. static long double ctansl ( cmplxl *z );
  44. long double cabsl ( cmplxl *x );
  45. void csqrtl ( cmplxl *x, cmplxl *y );
  46. void caddl ( cmplxl *x, cmplxl *y, cmplxl *z );
  47. extern long double fabsl ( long double );
  48. extern long double sqrtl ( long double );
  49. extern long double logl ( long double );
  50. extern long double expl ( long double );
  51. extern long double atan2l ( long double, long double );
  52. extern long double coshl ( long double );
  53. extern long double sinhl ( long double );
  54. extern long double asinl ( long double );
  55. extern long double sinl ( long double );
  56. extern long double cosl ( long double );
  57. void clogl ( cmplxl *, cmplxl *);
  58. void casinl ( cmplxl *, cmplxl *);
  59. #else
  60. static void cchshl();
  61. static long double redupil();
  62. static long double ctansl();
  63. long double cabsl(), fabsl(), sqrtl();
  64. lnog double logl(), expl(), atan2l(), coshl(), sinhl();
  65. long double asinl(), sinl(), cosl();
  66. void caddl(), csqrtl(), clogl(), casinl();
  67. #endif
  68. extern long double MAXNUML, MACHEPL, PIL, PIO2L;
  69. void clogl( z, w )
  70. register cmplxl *z, *w;
  71. {
  72. long double p, rr;
  73. /*rr = sqrt( z->r * z->r + z->i * z->i );*/
  74. rr = cabsl(z);
  75. p = logl(rr);
  76. #if ANSIC
  77. rr = atan2l( z->i, z->r );
  78. #else
  79. rr = atan2l( z->r, z->i );
  80. if( rr > PIL )
  81. rr -= PIL + PIL;
  82. #endif
  83. w->i = rr;
  84. w->r = p;
  85. }
  86. /* cexpl()
  87. *
  88. * Complex exponential function
  89. *
  90. *
  91. *
  92. * SYNOPSIS:
  93. *
  94. * void cexpl();
  95. * cmplxl z, w;
  96. *
  97. * cexpl( &z, &w );
  98. *
  99. *
  100. *
  101. * DESCRIPTION:
  102. *
  103. * Returns the exponential of the complex argument z
  104. * into the complex result w.
  105. *
  106. * If
  107. * z = x + iy,
  108. * r = exp(x),
  109. *
  110. * then
  111. *
  112. * w = r cos y + i r sin y.
  113. *
  114. *
  115. * ACCURACY:
  116. *
  117. * Relative error:
  118. * arithmetic domain # trials peak rms
  119. * DEC -10,+10 8700 3.7e-17 1.1e-17
  120. * IEEE -10,+10 30000 3.0e-16 8.7e-17
  121. *
  122. */
  123. void cexpl( z, w )
  124. register cmplxl *z, *w;
  125. {
  126. long double r;
  127. r = expl( z->r );
  128. w->r = r * cosl( z->i );
  129. w->i = r * sinl( z->i );
  130. }
  131. /* csinl()
  132. *
  133. * Complex circular sine
  134. *
  135. *
  136. *
  137. * SYNOPSIS:
  138. *
  139. * void csinl();
  140. * cmplxl z, w;
  141. *
  142. * csinl( &z, &w );
  143. *
  144. *
  145. *
  146. * DESCRIPTION:
  147. *
  148. * If
  149. * z = x + iy,
  150. *
  151. * then
  152. *
  153. * w = sin x cosh y + i cos x sinh y.
  154. *
  155. *
  156. *
  157. * ACCURACY:
  158. *
  159. * Relative error:
  160. * arithmetic domain # trials peak rms
  161. * DEC -10,+10 8400 5.3e-17 1.3e-17
  162. * IEEE -10,+10 30000 3.8e-16 1.0e-16
  163. * Also tested by csin(casin(z)) = z.
  164. *
  165. */
  166. void csinl( z, w )
  167. register cmplxl *z, *w;
  168. {
  169. long double ch, sh;
  170. cchshl( z->i, &ch, &sh );
  171. w->r = sinl( z->r ) * ch;
  172. w->i = cosl( z->r ) * sh;
  173. }
  174. /* calculate cosh and sinh */
  175. static void cchshl( x, c, s )
  176. long double x, *c, *s;
  177. {
  178. long double e, ei;
  179. if( fabsl(x) <= 0.5L )
  180. {
  181. *c = coshl(x);
  182. *s = sinhl(x);
  183. }
  184. else
  185. {
  186. e = expl(x);
  187. ei = 0.5L/e;
  188. e = 0.5L * e;
  189. *s = e - ei;
  190. *c = e + ei;
  191. }
  192. }
  193. /* ccosl()
  194. *
  195. * Complex circular cosine
  196. *
  197. *
  198. *
  199. * SYNOPSIS:
  200. *
  201. * void ccosl();
  202. * cmplxl z, w;
  203. *
  204. * ccosl( &z, &w );
  205. *
  206. *
  207. *
  208. * DESCRIPTION:
  209. *
  210. * If
  211. * z = x + iy,
  212. *
  213. * then
  214. *
  215. * w = cos x cosh y - i sin x sinh y.
  216. *
  217. *
  218. *
  219. * ACCURACY:
  220. *
  221. * Relative error:
  222. * arithmetic domain # trials peak rms
  223. * DEC -10,+10 8400 4.5e-17 1.3e-17
  224. * IEEE -10,+10 30000 3.8e-16 1.0e-16
  225. */
  226. void ccosl( z, w )
  227. register cmplxl *z, *w;
  228. {
  229. long double ch, sh;
  230. cchshl( z->i, &ch, &sh );
  231. w->r = cosl( z->r ) * ch;
  232. w->i = -sinl( z->r ) * sh;
  233. }
  234. /* ctanl()
  235. *
  236. * Complex circular tangent
  237. *
  238. *
  239. *
  240. * SYNOPSIS:
  241. *
  242. * void ctanl();
  243. * cmplxl z, w;
  244. *
  245. * ctanl( &z, &w );
  246. *
  247. *
  248. *
  249. * DESCRIPTION:
  250. *
  251. * If
  252. * z = x + iy,
  253. *
  254. * then
  255. *
  256. * sin 2x + i sinh 2y
  257. * w = --------------------.
  258. * cos 2x + cosh 2y
  259. *
  260. * On the real axis the denominator is zero at odd multiples
  261. * of PI/2. The denominator is evaluated by its Taylor
  262. * series near these points.
  263. *
  264. *
  265. * ACCURACY:
  266. *
  267. * Relative error:
  268. * arithmetic domain # trials peak rms
  269. * DEC -10,+10 5200 7.1e-17 1.6e-17
  270. * IEEE -10,+10 30000 7.2e-16 1.2e-16
  271. * Also tested by ctan * ccot = 1 and catan(ctan(z)) = z.
  272. */
  273. void ctanl( z, w )
  274. register cmplxl *z, *w;
  275. {
  276. long double d;
  277. d = cosl( 2.0L * z->r ) + coshl( 2.0L * z->i );
  278. if( fabsl(d) < 0.25L )
  279. d = ctansl(z);
  280. if( d == 0.0L )
  281. {
  282. mtherr( "ctan", OVERFLOW );
  283. w->r = MAXNUML;
  284. w->i = MAXNUML;
  285. return;
  286. }
  287. w->r = sinl( 2.0L * z->r ) / d;
  288. w->i = sinhl( 2.0L * z->i ) / d;
  289. }
  290. /* ccotl()
  291. *
  292. * Complex circular cotangent
  293. *
  294. *
  295. *
  296. * SYNOPSIS:
  297. *
  298. * void ccotl();
  299. * cmplxl z, w;
  300. *
  301. * ccotl( &z, &w );
  302. *
  303. *
  304. *
  305. * DESCRIPTION:
  306. *
  307. * If
  308. * z = x + iy,
  309. *
  310. * then
  311. *
  312. * sin 2x - i sinh 2y
  313. * w = --------------------.
  314. * cosh 2y - cos 2x
  315. *
  316. * On the real axis, the denominator has zeros at even
  317. * multiples of PI/2. Near these points it is evaluated
  318. * by a Taylor series.
  319. *
  320. *
  321. * ACCURACY:
  322. *
  323. * Relative error:
  324. * arithmetic domain # trials peak rms
  325. * DEC -10,+10 3000 6.5e-17 1.6e-17
  326. * IEEE -10,+10 30000 9.2e-16 1.2e-16
  327. * Also tested by ctan * ccot = 1 + i0.
  328. */
  329. void ccotl( z, w )
  330. register cmplxl *z, *w;
  331. {
  332. long double d;
  333. d = coshl(2.0L * z->i) - cosl(2.0L * z->r);
  334. if( fabsl(d) < 0.25L )
  335. d = ctansl(z);
  336. if( d == 0.0L )
  337. {
  338. mtherr( "ccot", OVERFLOW );
  339. w->r = MAXNUML;
  340. w->i = MAXNUML;
  341. return;
  342. }
  343. w->r = sinl( 2.0L * z->r ) / d;
  344. w->i = -sinhl( 2.0L * z->i ) / d;
  345. }
  346. /* Program to subtract nearest integer multiple of PI */
  347. /* extended precision value of PI: */
  348. #ifdef UNK
  349. static double DP1 = 3.14159265160560607910E0;
  350. static double DP2 = 1.98418714791870343106E-9;
  351. static double DP3 = 1.14423774522196636802E-17;
  352. #endif
  353. #ifdef DEC
  354. static unsigned short P1[] = {0040511,0007732,0120000,0000000,};
  355. static unsigned short P2[] = {0031010,0055060,0100000,0000000,};
  356. static unsigned short P3[] = {0022123,0011431,0105056,0001560,};
  357. #define DP1 *(double *)P1
  358. #define DP2 *(double *)P2
  359. #define DP3 *(double *)P3
  360. #endif
  361. #ifdef IBMPC
  362. static unsigned short P1[] = {0x0000,0x5400,0x21fb,0x4009};
  363. static unsigned short P2[] = {0x0000,0x1000,0x0b46,0x3e21};
  364. static unsigned short P3[] = {0xc06e,0x3145,0x6263,0x3c6a};
  365. #define DP1 *(double *)P1
  366. #define DP2 *(double *)P2
  367. #define DP3 *(double *)P3
  368. #endif
  369. #ifdef MIEEE
  370. static unsigned short P1[] = {
  371. 0x4009,0x21fb,0x5400,0x0000
  372. };
  373. static unsigned short P2[] = {
  374. 0x3e21,0x0b46,0x1000,0x0000
  375. };
  376. static unsigned short P3[] = {
  377. 0x3c6a,0x6263,0x3145,0xc06e
  378. };
  379. #define DP1 *(double *)P1
  380. #define DP2 *(double *)P2
  381. #define DP3 *(double *)P3
  382. #endif
  383. static long double redupil(x)
  384. long double x;
  385. {
  386. long double t;
  387. long i;
  388. t = x/PIL;
  389. if( t >= 0.0L )
  390. t += 0.5L;
  391. else
  392. t -= 0.5L;
  393. i = t; /* the multiple */
  394. t = i;
  395. t = ((x - t * DP1) - t * DP2) - t * DP3;
  396. return(t);
  397. }
  398. /* Taylor series expansion for cosh(2y) - cos(2x) */
  399. static long double ctansl(z)
  400. cmplxl *z;
  401. {
  402. long double f, x, x2, y, y2, rn, t;
  403. long double d;
  404. x = fabsl( 2.0L * z->r );
  405. y = fabsl( 2.0L * z->i );
  406. x = redupil(x);
  407. x = x * x;
  408. y = y * y;
  409. x2 = 1.0L;
  410. y2 = 1.0L;
  411. f = 1.0L;
  412. rn = 0.0;
  413. d = 0.0;
  414. do
  415. {
  416. rn += 1.0L;
  417. f *= rn;
  418. rn += 1.0L;
  419. f *= rn;
  420. x2 *= x;
  421. y2 *= y;
  422. t = y2 + x2;
  423. t /= f;
  424. d += t;
  425. rn += 1.0L;
  426. f *= rn;
  427. rn += 1.0L;
  428. f *= rn;
  429. x2 *= x;
  430. y2 *= y;
  431. t = y2 - x2;
  432. t /= f;
  433. d += t;
  434. }
  435. while( fabsl(t/d) > MACHEPL );
  436. return(d);
  437. }
  438. /* casinl()
  439. *
  440. * Complex circular arc sine
  441. *
  442. *
  443. *
  444. * SYNOPSIS:
  445. *
  446. * void casinl();
  447. * cmplxl z, w;
  448. *
  449. * casinl( &z, &w );
  450. *
  451. *
  452. *
  453. * DESCRIPTION:
  454. *
  455. * Inverse complex sine:
  456. *
  457. * 2
  458. * w = -i clog( iz + csqrt( 1 - z ) ).
  459. *
  460. *
  461. * ACCURACY:
  462. *
  463. * Relative error:
  464. * arithmetic domain # trials peak rms
  465. * DEC -10,+10 10100 2.1e-15 3.4e-16
  466. * IEEE -10,+10 30000 2.2e-14 2.7e-15
  467. * Larger relative error can be observed for z near zero.
  468. * Also tested by csin(casin(z)) = z.
  469. */
  470. void casinl( z, w )
  471. cmplxl *z, *w;
  472. {
  473. static cmplxl ca, ct, zz, z2;
  474. long double x, y;
  475. x = z->r;
  476. y = z->i;
  477. if( y == 0.0L )
  478. {
  479. if( fabsl(x) > 1.0L )
  480. {
  481. w->r = PIO2L;
  482. w->i = 0.0L;
  483. mtherr( "casinl", DOMAIN );
  484. }
  485. else
  486. {
  487. w->r = asinl(x);
  488. w->i = 0.0L;
  489. }
  490. return;
  491. }
  492. /* Power series expansion */
  493. /*
  494. b = cabsl(z);
  495. if( b < 0.125L )
  496. {
  497. z2.r = (x - y) * (x + y);
  498. z2.i = 2.0L * x * y;
  499. cn = 1.0L;
  500. n = 1.0L;
  501. ca.r = x;
  502. ca.i = y;
  503. sum.r = x;
  504. sum.i = y;
  505. do
  506. {
  507. ct.r = z2.r * ca.r - z2.i * ca.i;
  508. ct.i = z2.r * ca.i + z2.i * ca.r;
  509. ca.r = ct.r;
  510. ca.i = ct.i;
  511. cn *= n;
  512. n += 1.0L;
  513. cn /= n;
  514. n += 1.0L;
  515. b = cn/n;
  516. ct.r *= b;
  517. ct.i *= b;
  518. sum.r += ct.r;
  519. sum.i += ct.i;
  520. b = fabsl(ct.r) + fabs(ct.i);
  521. }
  522. while( b > MACHEPL );
  523. w->r = sum.r;
  524. w->i = sum.i;
  525. return;
  526. }
  527. */
  528. ca.r = x;
  529. ca.i = y;
  530. ct.r = -ca.i; /* iz */
  531. ct.i = ca.r;
  532. /* sqrt( 1 - z*z) */
  533. /* cmul( &ca, &ca, &zz ) */
  534. zz.r = (ca.r - ca.i) * (ca.r + ca.i); /*x * x - y * y */
  535. zz.i = 2.0L * ca.r * ca.i;
  536. zz.r = 1.0L - zz.r;
  537. zz.i = -zz.i;
  538. csqrtl( &zz, &z2 );
  539. caddl( &z2, &ct, &zz );
  540. clogl( &zz, &zz );
  541. w->r = zz.i; /* mult by 1/i = -i */
  542. w->i = -zz.r;
  543. return;
  544. }
  545. /* cacosl()
  546. *
  547. * Complex circular arc cosine
  548. *
  549. *
  550. *
  551. * SYNOPSIS:
  552. *
  553. * void cacosl();
  554. * cmplxl z, w;
  555. *
  556. * cacosl( &z, &w );
  557. *
  558. *
  559. *
  560. * DESCRIPTION:
  561. *
  562. *
  563. * w = arccos z = PI/2 - arcsin z.
  564. *
  565. *
  566. *
  567. *
  568. * ACCURACY:
  569. *
  570. * Relative error:
  571. * arithmetic domain # trials peak rms
  572. * DEC -10,+10 5200 1.6e-15 2.8e-16
  573. * IEEE -10,+10 30000 1.8e-14 2.2e-15
  574. */
  575. void cacosl( z, w )
  576. cmplxl *z, *w;
  577. {
  578. casinl( z, w );
  579. w->r = PIO2L - w->r;
  580. w->i = -w->i;
  581. }
  582. /* catanl()
  583. *
  584. * Complex circular arc tangent
  585. *
  586. *
  587. *
  588. * SYNOPSIS:
  589. *
  590. * void catanl();
  591. * cmplxl z, w;
  592. *
  593. * catanl( &z, &w );
  594. *
  595. *
  596. *
  597. * DESCRIPTION:
  598. *
  599. * If
  600. * z = x + iy,
  601. *
  602. * then
  603. * 1 ( 2x )
  604. * Re w = - arctan(-----------) + k PI
  605. * 2 ( 2 2)
  606. * (1 - x - y )
  607. *
  608. * ( 2 2)
  609. * 1 (x + (y+1) )
  610. * Im w = - log(------------)
  611. * 4 ( 2 2)
  612. * (x + (y-1) )
  613. *
  614. * Where k is an arbitrary integer.
  615. *
  616. *
  617. *
  618. * ACCURACY:
  619. *
  620. * Relative error:
  621. * arithmetic domain # trials peak rms
  622. * DEC -10,+10 5900 1.3e-16 7.8e-18
  623. * IEEE -10,+10 30000 2.3e-15 8.5e-17
  624. * The check catan( ctan(z) ) = z, with |x| and |y| < PI/2,
  625. * had peak relative error 1.5e-16, rms relative error
  626. * 2.9e-17. See also clog().
  627. */
  628. void catanl( z, w )
  629. cmplxl *z, *w;
  630. {
  631. long double a, t, x, x2, y;
  632. x = z->r;
  633. y = z->i;
  634. if( (x == 0.0L) && (y > 1.0L) )
  635. goto ovrf;
  636. x2 = x * x;
  637. a = 1.0L - x2 - (y * y);
  638. if( a == 0.0L )
  639. goto ovrf;
  640. #if ANSIC
  641. t = atan2l( 2.0L * x, a ) * 0.5L;
  642. #else
  643. t = atan2l( a, 2.0 * x ) * 0.5L;
  644. #endif
  645. w->r = redupil( t );
  646. t = y - 1.0L;
  647. a = x2 + (t * t);
  648. if( a == 0.0L )
  649. goto ovrf;
  650. t = y + 1.0L;
  651. a = (x2 + (t * t))/a;
  652. w->i = logl(a)/4.0;
  653. return;
  654. ovrf:
  655. mtherr( "catanl", OVERFLOW );
  656. w->r = MAXNUML;
  657. w->i = MAXNUML;
  658. }