PageRenderTime 34ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/R-2.15.1/src/appl/cpoly.c

#
C | 715 lines | 421 code | 121 blank | 173 comment | 85 complexity | f65f6c5bb76a8c9fa54127897a9f97bc MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, CC-BY-SA-4.0, BSD-3-Clause, AGPL-3.0, GPL-2.0, GPL-3.0, LGPL-2.0
  1. /*
  2. * R : A Computer Language for Statistical Data Analysis
  3. * Copyright (C) 1997-1998 Ross Ihaka
  4. * Copyright (C) 1999-2001 R Core Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, a copy is available at
  18. * http://www.r-project.org/Licenses/
  19. *
  20. * cpoly finds the zeros of a complex polynomial.
  21. *
  22. * On Entry
  23. *
  24. * opr, opi - double precision vectors of real and
  25. * imaginary parts of the coefficients in
  26. * order of decreasing powers.
  27. *
  28. * degree - int degree of polynomial.
  29. *
  30. *
  31. * On Return
  32. *
  33. * zeror, zeroi - output double precision vectors of
  34. * real and imaginary parts of the zeros.
  35. *
  36. * fail - output int parameter, true only if
  37. * leading coefficient is zero or if cpoly
  38. * has found fewer than degree zeros.
  39. *
  40. * The program has been written to reduce the chance of overflow
  41. * occurring. If it does occur, there is still a possibility that
  42. * the zerofinder will work provided the overflowed quantity is
  43. * replaced by a large number.
  44. *
  45. * This is a C translation of the following.
  46. *
  47. * TOMS Algorithm 419
  48. * Jenkins and Traub.
  49. * Comm. ACM 15 (1972) 97-99.
  50. *
  51. * Ross Ihaka
  52. * February 1997
  53. */
  54. #ifdef HAVE_CONFIG_H
  55. #include <config.h>
  56. #endif
  57. #include <R_ext/Arith.h> /* for declaration of hypot */
  58. #include <R_ext/Memory.h> /* for declaration of R_alloc */
  59. #include <float.h> /* for FLT_RADIX */
  60. #include <Rmath.h> /* for R_pow_di */
  61. #include <R_ext/Applic.h>
  62. #ifdef HAVE_VISIBILITY_ATTRIBUTE
  63. # define attribute_hidden __attribute__ ((visibility ("hidden")))
  64. #else
  65. # define attribute_hidden
  66. #endif
  67. static void calct(Rboolean *);
  68. static Rboolean fxshft(int, double *, double *);
  69. static Rboolean vrshft(int, double *, double *);
  70. static void nexth(Rboolean);
  71. static void noshft(int);
  72. /* Consider exporting these (via Applic.h): */
  73. static void polyev(int, double, double,
  74. double *, double *, double *, double *, double *, double *);
  75. static double errev(int, double *, double *, double, double, double, double);
  76. static double cpoly_cauchy(int, double *, double *);
  77. static double cpoly_scale(int, double *, double, double, double, double);
  78. static void cdivid(double, double, double, double, double *, double *);
  79. /* Global Variables (too many!) */
  80. static int nn;
  81. #if 0
  82. #define NMAX 50
  83. static double pr[NMAX];
  84. static double pi[NMAX];
  85. static double hr[NMAX];
  86. static double hi[NMAX];
  87. static double qpr[NMAX];
  88. static double qpi[NMAX];
  89. static double qhr[NMAX];
  90. static double qhi[NMAX];
  91. static double shr[NMAX];
  92. static double shi[NMAX];
  93. #else
  94. static double *pr, *pi, *hr, *hi, *qpr, *qpi, *qhr, *qhi, *shr, *shi;
  95. #endif
  96. static double sr, si;
  97. static double tr, ti;
  98. static double pvr, pvi;
  99. static const double eta = DBL_EPSILON;
  100. static const double are = /* eta = */DBL_EPSILON;
  101. static const double mre = 2. * M_SQRT2 * /* eta, i.e. */DBL_EPSILON;
  102. static const double infin = DBL_MAX;
  103. attribute_hidden
  104. void R_cpolyroot(double *opr, double *opi, int *degree,
  105. double *zeror, double *zeroi, Rboolean *fail)
  106. {
  107. static const double smalno = DBL_MIN;
  108. static const double base = (double)FLT_RADIX;
  109. static int d_n, i, i1, i2;
  110. static double zi, zr, xx, yy;
  111. static double bnd, xxx;
  112. Rboolean conv;
  113. int d1;
  114. double *tmp;
  115. static const double cosr =/* cos 94 */ -0.06975647374412529990;
  116. static const double sinr =/* sin 94 */ 0.99756405025982424767;
  117. xx = M_SQRT1_2;/* 1/sqrt(2) = 0.707.... */
  118. yy = -xx;
  119. *fail = FALSE;
  120. nn = *degree;
  121. d1 = nn - 1;
  122. /* algorithm fails if the leading coefficient is zero. */
  123. if (opr[0] == 0. && opi[0] == 0.) {
  124. *fail = TRUE;
  125. return;
  126. }
  127. /* remove the zeros at the origin if any. */
  128. while (opr[nn] == 0. && opi[nn] == 0.) {
  129. d_n = d1-nn+1;
  130. zeror[d_n] = 0.;
  131. zeroi[d_n] = 0.;
  132. nn--;
  133. }
  134. nn++;
  135. /*-- Now, global var. nn := #{coefficients} = (relevant degree)+1 */
  136. if (nn == 1) return;
  137. /* Use a single allocation as these as small */
  138. tmp = (double *) R_alloc((size_t) (10*nn), sizeof(double));
  139. pr = tmp; pi = tmp + nn; hr = tmp + 2*nn; hi = tmp + 3*nn;
  140. qpr = tmp + 4*nn; qpi = tmp + 5*nn; qhr = tmp + 6*nn; qhi = tmp + 7*nn;
  141. shr = tmp + 8*nn; shi = tmp + 9*nn;
  142. /* make a copy of the coefficients and shr[] = | p[] | */
  143. for (i = 0; i < nn; i++) {
  144. pr[i] = opr[i];
  145. pi[i] = opi[i];
  146. shr[i] = hypot(pr[i], pi[i]);
  147. }
  148. /* scale the polynomial with factor 'bnd'. */
  149. bnd = cpoly_scale(nn, shr, eta, infin, smalno, base);
  150. if (bnd != 1.) {
  151. for (i=0; i < nn; i++) {
  152. pr[i] *= bnd;
  153. pi[i] *= bnd;
  154. }
  155. }
  156. /* start the algorithm for one zero */
  157. while (nn > 2) {
  158. /* calculate bnd, a lower bound on the modulus of the zeros. */
  159. for (i=0 ; i < nn ; i++)
  160. shr[i] = hypot(pr[i], pi[i]);
  161. bnd = cpoly_cauchy(nn, shr, shi);
  162. /* outer loop to control 2 major passes */
  163. /* with different sequences of shifts */
  164. for (i1 = 1; i1 <= 2; i1++) {
  165. /* first stage calculation, no shift */
  166. noshft(5);
  167. /* inner loop to select a shift */
  168. for (i2 = 1; i2 <= 9; i2++) {
  169. /* shift is chosen with modulus bnd */
  170. /* and amplitude rotated by 94 degrees */
  171. /* from the previous shift */
  172. xxx= cosr * xx - sinr * yy;
  173. yy = sinr * xx + cosr * yy;
  174. xx = xxx;
  175. sr = bnd * xx;
  176. si = bnd * yy;
  177. /* second stage calculation, fixed shift */
  178. conv = fxshft(i2 * 10, &zr, &zi);
  179. if (conv)
  180. goto L10;
  181. }
  182. }
  183. /* the zerofinder has failed on two major passes */
  184. /* return empty handed */
  185. *fail = TRUE;
  186. return;
  187. /* the second stage jumps directly to the third stage iteration.
  188. * if successful, the zero is stored and the polynomial deflated.
  189. */
  190. L10:
  191. d_n = d1+2 - nn;
  192. zeror[d_n] = zr;
  193. zeroi[d_n] = zi;
  194. --nn;
  195. for (i=0; i < nn ; i++) {
  196. pr[i] = qpr[i];
  197. pi[i] = qpi[i];
  198. }
  199. }/*while*/
  200. /* calculate the final zero and return */
  201. cdivid(-pr[1], -pi[1], pr[0], pi[0], &zeror[d1], &zeroi[d1]);
  202. return;
  203. }
  204. /* Computes the derivative polynomial as the initial
  205. * polynomial and computes l1 no-shift h polynomials. */
  206. static void noshft(int l1)
  207. {
  208. int i, j, jj, n = nn - 1, nm1 = n - 1;
  209. double t1, t2, xni;
  210. for (i=0; i < n; i++) {
  211. xni = (double)(nn - i - 1);
  212. hr[i] = xni * pr[i] / n;
  213. hi[i] = xni * pi[i] / n;
  214. }
  215. for (jj = 1; jj <= l1; jj++) {
  216. if (hypot(hr[n-1], hi[n-1]) <=
  217. eta * 10.0 * hypot(pr[n-1], pi[n-1])) {
  218. /* If the constant term is essentially zero, */
  219. /* shift h coefficients. */
  220. for (i = 1; i <= nm1; i++) {
  221. j = nn - i;
  222. hr[j-1] = hr[j-2];
  223. hi[j-1] = hi[j-2];
  224. }
  225. hr[0] = 0.;
  226. hi[0] = 0.;
  227. }
  228. else {
  229. cdivid(-pr[nn-1], -pi[nn-1], hr[n-1], hi[n-1], &tr, &ti);
  230. for (i = 1; i <= nm1; i++) {
  231. j = nn - i;
  232. t1 = hr[j-2];
  233. t2 = hi[j-2];
  234. hr[j-1] = tr * t1 - ti * t2 + pr[j-1];
  235. hi[j-1] = tr * t2 + ti * t1 + pi[j-1];
  236. }
  237. hr[0] = pr[0];
  238. hi[0] = pi[0];
  239. }
  240. }
  241. }
  242. /* Computes l2 fixed-shift h polynomials and tests for convergence.
  243. * initiates a variable-shift iteration and returns with the
  244. * approximate zero if successful.
  245. */
  246. static Rboolean fxshft(int l2, double *zr, double *zi)
  247. {
  248. /* l2 - limit of fixed shift steps
  249. * zr,zi - approximate zero if convergence (result TRUE)
  250. *
  251. * Return value indicates convergence of stage 3 iteration
  252. *
  253. * Uses global (sr,si), nn, pr[], pi[], .. (all args of polyev() !)
  254. */
  255. Rboolean pasd, bool, test;
  256. static double svsi, svsr;
  257. static int i, j, n;
  258. static double oti, otr;
  259. n = nn - 1;
  260. /* evaluate p at s. */
  261. polyev(nn, sr, si, pr, pi, qpr, qpi, &pvr, &pvi);
  262. test = TRUE;
  263. pasd = FALSE;
  264. /* calculate first t = -p(s)/h(s). */
  265. calct(&bool);
  266. /* main loop for one second stage step. */
  267. for (j=1; j<=l2; j++) {
  268. otr = tr;
  269. oti = ti;
  270. /* compute next h polynomial and new t. */
  271. nexth(bool);
  272. calct(&bool);
  273. *zr = sr + tr;
  274. *zi = si + ti;
  275. /* test for convergence unless stage 3 has */
  276. /* failed once or this is the last h polynomial. */
  277. if (!bool && test && j != l2) {
  278. if (hypot(tr - otr, ti - oti) >= hypot(*zr, *zi) * 0.5) {
  279. pasd = FALSE;
  280. }
  281. else if (! pasd) {
  282. pasd = TRUE;
  283. }
  284. else {
  285. /* the weak convergence test has been */
  286. /* passed twice, start the third stage */
  287. /* iteration, after saving the current */
  288. /* h polynomial and shift. */
  289. for (i = 0; i < n; i++) {
  290. shr[i] = hr[i];
  291. shi[i] = hi[i];
  292. }
  293. svsr = sr;
  294. svsi = si;
  295. if (vrshft(10, zr, zi)) {
  296. return TRUE;
  297. }
  298. /* the iteration failed to converge. */
  299. /* turn off testing and restore */
  300. /* h, s, pv and t. */
  301. test = FALSE;
  302. for (i=1 ; i<=n ; i++) {
  303. hr[i-1] = shr[i-1];
  304. hi[i-1] = shi[i-1];
  305. }
  306. sr = svsr;
  307. si = svsi;
  308. polyev(nn, sr, si, pr, pi, qpr, qpi, &pvr, &pvi);
  309. calct(&bool);
  310. }
  311. }
  312. }
  313. /* attempt an iteration with final h polynomial */
  314. /* from second stage. */
  315. return(vrshft(10, zr, zi));
  316. }
  317. /* carries out the third stage iteration.
  318. */
  319. static Rboolean vrshft(int l3, double *zr, double *zi)
  320. {
  321. /* l3 - limit of steps in stage 3.
  322. * zr,zi - on entry contains the initial iterate;
  323. * if the iteration converges it contains
  324. * the final iterate on exit.
  325. * Returns TRUE if iteration converges
  326. *
  327. * Assign and uses GLOBAL sr, si
  328. */
  329. Rboolean bool, b;
  330. static int i, j;
  331. static double r1, r2, mp, ms, tp, relstp;
  332. static double omp;
  333. b = FALSE;
  334. sr = *zr;
  335. si = *zi;
  336. /* main loop for stage three */
  337. for (i = 1; i <= l3; i++) {
  338. /* evaluate p at s and test for convergence. */
  339. polyev(nn, sr, si, pr, pi, qpr, qpi, &pvr, &pvi);
  340. mp = hypot(pvr, pvi);
  341. ms = hypot(sr, si);
  342. if (mp <= 20. * errev(nn, qpr, qpi, ms, mp, /*are=*/eta, mre)) {
  343. goto L_conv;
  344. }
  345. /* polynomial value is smaller in value than */
  346. /* a bound on the error in evaluating p, */
  347. /* terminate the iteration. */
  348. if (i != 1) {
  349. if (!b && mp >= omp && relstp < .05) {
  350. /* iteration has stalled. probably a */
  351. /* cluster of zeros. do 5 fixed shift */
  352. /* steps into the cluster to force */
  353. /* one zero to dominate. */
  354. tp = relstp;
  355. b = TRUE;
  356. if (relstp < eta)
  357. tp = eta;
  358. r1 = sqrt(tp);
  359. r2 = sr * (r1 + 1.) - si * r1;
  360. si = sr * r1 + si * (r1 + 1.);
  361. sr = r2;
  362. polyev(nn, sr, si, pr, pi, qpr, qpi, &pvr, &pvi);
  363. for (j = 1; j <= 5; ++j) {
  364. calct(&bool);
  365. nexth(bool);
  366. }
  367. omp = infin;
  368. goto L10;
  369. }
  370. else {
  371. /* exit if polynomial value */
  372. /* increases significantly. */
  373. if (mp * .1 > omp)
  374. return FALSE;
  375. }
  376. }
  377. omp = mp;
  378. /* calculate next iterate. */
  379. L10:
  380. calct(&bool);
  381. nexth(bool);
  382. calct(&bool);
  383. if (!bool) {
  384. relstp = hypot(tr, ti) / hypot(sr, si);
  385. sr += tr;
  386. si += ti;
  387. }
  388. }
  389. return FALSE;
  390. L_conv:
  391. *zr = sr;
  392. *zi = si;
  393. return TRUE;
  394. }
  395. static void calct(Rboolean *bool)
  396. {
  397. /* computes t = -p(s)/h(s).
  398. * bool - logical, set true if h(s) is essentially zero. */
  399. int n = nn - 1;
  400. double hvi, hvr;
  401. /* evaluate h(s). */
  402. polyev(n, sr, si, hr, hi,
  403. qhr, qhi, &hvr, &hvi);
  404. *bool = hypot(hvr, hvi) <= are * 10. * hypot(hr[n-1], hi[n-1]);
  405. if (!*bool) {
  406. cdivid(-pvr, -pvi, hvr, hvi, &tr, &ti);
  407. }
  408. else {
  409. tr = 0.;
  410. ti = 0.;
  411. }
  412. }
  413. static void nexth(Rboolean bool)
  414. {
  415. /* calculates the next shifted h polynomial.
  416. * bool : if TRUE h(s) is essentially zero
  417. */
  418. int j, n = nn - 1;
  419. double t1, t2;
  420. if (!bool) {
  421. for (j=1; j < n; j++) {
  422. t1 = qhr[j - 1];
  423. t2 = qhi[j - 1];
  424. hr[j] = tr * t1 - ti * t2 + qpr[j];
  425. hi[j] = tr * t2 + ti * t1 + qpi[j];
  426. }
  427. hr[0] = qpr[0];
  428. hi[0] = qpi[0];
  429. }
  430. else {
  431. /* if h(s) is zero replace h with qh. */
  432. for (j=1; j < n; j++) {
  433. hr[j] = qhr[j-1];
  434. hi[j] = qhi[j-1];
  435. }
  436. hr[0] = 0.;
  437. hi[0] = 0.;
  438. }
  439. }
  440. /*--------------------- Independent Complex Polynomial Utilities ----------*/
  441. static
  442. void polyev(int n,
  443. double s_r, double s_i,
  444. double *p_r, double *p_i,
  445. double *q_r, double *q_i,
  446. double *v_r, double *v_i)
  447. {
  448. /* evaluates a polynomial p at s by the horner recurrence
  449. * placing the partial sums in q and the computed value in v_.
  450. */
  451. int i;
  452. double t;
  453. q_r[0] = p_r[0];
  454. q_i[0] = p_i[0];
  455. *v_r = q_r[0];
  456. *v_i = q_i[0];
  457. for (i = 1; i < n; i++) {
  458. t = *v_r * s_r - *v_i * s_i + p_r[i];
  459. q_i[i] = *v_i = *v_r * s_i + *v_i * s_r + p_i[i];
  460. q_r[i] = *v_r = t;
  461. }
  462. }
  463. static
  464. double errev(int n, double *qr, double *qi,
  465. double ms, double mp, double a_re, double m_re)
  466. {
  467. /* bounds the error in evaluating the polynomial by the horner
  468. * recurrence.
  469. *
  470. * qr,qi - the partial sum vectors
  471. * ms - modulus of the point
  472. * mp - modulus of polynomial value
  473. * a_re,m_re - error bounds on complex addition and multiplication
  474. */
  475. double e;
  476. int i;
  477. e = hypot(qr[0], qi[0]) * m_re / (a_re + m_re);
  478. for (i=0; i < n; i++)
  479. e = e*ms + hypot(qr[i], qi[i]);
  480. return e * (a_re + m_re) - mp * m_re;
  481. }
  482. static
  483. double cpoly_cauchy(int n, double *pot, double *q)
  484. {
  485. /* Computes a lower bound on the moduli of the zeros of a polynomial
  486. * pot[1:nn] is the modulus of the coefficients.
  487. */
  488. double f, x, delf, dx, xm;
  489. int i, n1 = n - 1;
  490. pot[n1] = -pot[n1];
  491. /* compute upper estimate of bound. */
  492. x = exp((log(-pot[n1]) - log(pot[0])) / (double) n1);
  493. /* if newton step at the origin is better, use it. */
  494. if (pot[n1-1] != 0.) {
  495. xm = -pot[n1] / pot[n1-1];
  496. if (xm < x)
  497. x = xm;
  498. }
  499. /* chop the interval (0,x) unitl f le 0. */
  500. for(;;) {
  501. xm = x * 0.1;
  502. f = pot[0];
  503. for (i = 1; i < n; i++)
  504. f = f * xm + pot[i];
  505. if (f <= 0.0) {
  506. break;
  507. }
  508. x = xm;
  509. }
  510. dx = x;
  511. /* do Newton iteration until x converges to two decimal places. */
  512. while (fabs(dx / x) > 0.005) {
  513. q[0] = pot[0];
  514. for(i = 1; i < n; i++)
  515. q[i] = q[i-1] * x + pot[i];
  516. f = q[n1];
  517. delf = q[0];
  518. for(i = 1; i < n1; i++)
  519. delf = delf * x + q[i];
  520. dx = f / delf;
  521. x -= dx;
  522. }
  523. return x;
  524. }
  525. static
  526. double cpoly_scale(int n, double *pot,
  527. double eps, double BIG, double small, double base)
  528. {
  529. /* Returns a scale factor to multiply the coefficients of the polynomial.
  530. * The scaling is done to avoid overflow and to avoid
  531. * undetected underflow interfering with the convergence criterion.
  532. * The factor is a power of the base.
  533. * pot[1:n] : modulus of coefficients of p
  534. * eps,BIG,
  535. * small,base - constants describing the floating point arithmetic.
  536. */
  537. int i, ell;
  538. double x, high, sc, lo, min_, max_;
  539. /* find largest and smallest moduli of coefficients. */
  540. high = sqrt(BIG);
  541. lo = small / eps;
  542. max_ = 0.;
  543. min_ = BIG;
  544. for (i = 0; i < n; i++) {
  545. x = pot[i];
  546. if (x > max_) max_ = x;
  547. if (x != 0. && x < min_)
  548. min_ = x;
  549. }
  550. /* scale only if there are very large or very small components. */
  551. if (min_ < lo || max_ > high) {
  552. x = lo / min_;
  553. if (x <= 1.)
  554. sc = 1. / (sqrt(max_) * sqrt(min_));
  555. else {
  556. sc = x;
  557. if (BIG / sc > max_)
  558. sc = 1.0;
  559. }
  560. ell = (int) (log(sc) / log(base) + 0.5);
  561. return R_pow_di(base, ell);
  562. }
  563. else return 1.0;
  564. }
  565. static
  566. void cdivid(double ar, double ai, double br, double bi,
  567. double *cr, double *ci)
  568. {
  569. /* complex division c = a/b, i.e., (cr +i*ci) = (ar +i*ai) / (br +i*bi),
  570. avoiding overflow. */
  571. double d, r;
  572. if (br == 0. && bi == 0.) {
  573. /* division by zero, c = infinity. */
  574. *cr = *ci = R_PosInf;
  575. }
  576. else if (fabs(br) >= fabs(bi)) {
  577. r = bi / br;
  578. d = br + r * bi;
  579. *cr = (ar + ai * r) / d;
  580. *ci = (ai - ar * r) / d;
  581. }
  582. else {
  583. r = br / bi;
  584. d = bi + r * br;
  585. *cr = (ar * r + ai) / d;
  586. *ci = (ai * r - ar) / d;
  587. }
  588. }
  589. /* static double cpoly_cmod(double *r, double *i)
  590. * --> replaced by hypot() everywhere
  591. */