polrt.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* polrt.c
  2. *
  3. * Find roots of a polynomial
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * typedef struct
  10. * {
  11. * double r;
  12. * double i;
  13. * }cmplx;
  14. *
  15. * double xcof[], cof[];
  16. * int m;
  17. * cmplx root[];
  18. *
  19. * polrt( xcof, cof, m, root )
  20. *
  21. *
  22. *
  23. * DESCRIPTION:
  24. *
  25. * Iterative determination of the roots of a polynomial of
  26. * degree m whose coefficient vector is xcof[]. The
  27. * coefficients are arranged in ascending order; i.e., the
  28. * coefficient of x**m is xcof[m].
  29. *
  30. * The array cof[] is working storage the same size as xcof[].
  31. * root[] is the output array containing the complex roots.
  32. *
  33. *
  34. * ACCURACY:
  35. *
  36. * Termination depends on evaluation of the polynomial at
  37. * the trial values of the roots. The values of multiple roots
  38. * or of roots that are nearly equal may have poor relative
  39. * accuracy after the first root in the neighborhood has been
  40. * found.
  41. *
  42. */
  43. /* polrt */
  44. /* Complex roots of real polynomial */
  45. /* number of coefficients is m + 1 ( i.e., m is degree of polynomial) */
  46. #include <math.h>
  47. /*
  48. typedef struct
  49. {
  50. double r;
  51. double i;
  52. }cmplx;
  53. */
  54. #ifdef ANSIPROT
  55. extern double fabs ( double );
  56. #else
  57. double fabs();
  58. #endif
  59. int polrt( xcof, cof, m, root )
  60. double xcof[], cof[];
  61. int m;
  62. cmplx root[];
  63. {
  64. register double *p, *q;
  65. int i, j, nsav, n, n1, n2, nroot, iter, retry;
  66. int final;
  67. double mag, cofj;
  68. cmplx x0, x, xsav, dx, t, t1, u, ud;
  69. final = 0;
  70. n = m;
  71. if( n <= 0 )
  72. return(1);
  73. if( n > 36 )
  74. return(2);
  75. if( xcof[m] == 0.0 )
  76. return(4);
  77. n1 = n;
  78. n2 = n;
  79. nroot = 0;
  80. nsav = n;
  81. q = &xcof[0];
  82. p = &cof[n];
  83. for( j=0; j<=nsav; j++ )
  84. *p-- = *q++; /* cof[ n-j ] = xcof[j];*/
  85. xsav.r = 0.0;
  86. xsav.i = 0.0;
  87. nxtrut:
  88. x0.r = 0.00500101;
  89. x0.i = 0.01000101;
  90. retry = 0;
  91. tryagn:
  92. retry += 1;
  93. x.r = x0.r;
  94. x0.r = -10.0 * x0.i;
  95. x0.i = -10.0 * x.r;
  96. x.r = x0.r;
  97. x.i = x0.i;
  98. finitr:
  99. iter = 0;
  100. while( iter < 500 )
  101. {
  102. u.r = cof[n];
  103. if( u.r == 0.0 )
  104. { /* this root is zero */
  105. x.r = 0;
  106. n1 -= 1;
  107. n2 -= 1;
  108. goto zerrut;
  109. }
  110. u.i = 0;
  111. ud.r = 0;
  112. ud.i = 0;
  113. t.r = 1.0;
  114. t.i = 0;
  115. p = &cof[n-1];
  116. for( i=0; i<n; i++ )
  117. {
  118. t1.r = x.r * t.r - x.i * t.i;
  119. t1.i = x.r * t.i + x.i * t.r;
  120. cofj = *p--; /* evaluate polynomial */
  121. u.r += cofj * t1.r;
  122. u.i += cofj * t1.i;
  123. cofj = cofj * (i+1); /* derivative */
  124. ud.r += cofj * t.r;
  125. ud.i -= cofj * t.i;
  126. t.r = t1.r;
  127. t.i = t1.i;
  128. }
  129. mag = ud.r * ud.r + ud.i * ud.i;
  130. if( mag == 0.0 )
  131. {
  132. if( !final )
  133. goto tryagn;
  134. x.r = xsav.r;
  135. x.i = xsav.i;
  136. goto findon;
  137. }
  138. dx.r = (u.i * ud.i - u.r * ud.r)/mag;
  139. x.r += dx.r;
  140. dx.i = -(u.r * ud.i + u.i * ud.r)/mag;
  141. x.i += dx.i;
  142. if( (fabs(dx.i) + fabs(dx.r)) < 1.0e-6 )
  143. goto lupdon;
  144. iter += 1;
  145. } /* while iter < 500 */
  146. if( final )
  147. goto lupdon;
  148. if( retry < 5 )
  149. goto tryagn;
  150. return(3);
  151. lupdon:
  152. /* Swap original and reduced polynomials */
  153. q = &xcof[nsav];
  154. p = &cof[0];
  155. for( j=0; j<=n2; j++ )
  156. {
  157. cofj = *q;
  158. *q-- = *p;
  159. *p++ = cofj;
  160. }
  161. i = n;
  162. n = n1;
  163. n1 = i;
  164. if( !final )
  165. {
  166. final = 1;
  167. if( fabs(x.i/x.r) < 1.0e-4 )
  168. x.i = 0.0;
  169. xsav.r = x.r;
  170. xsav.i = x.i;
  171. goto finitr; /* do final iteration on original polynomial */
  172. }
  173. findon:
  174. final = 0;
  175. if( fabs(x.i/x.r) >= 1.0e-5 )
  176. {
  177. cofj = x.r + x.r;
  178. mag = x.r * x.r + x.i * x.i;
  179. n -= 2;
  180. }
  181. else
  182. { /* root is real */
  183. zerrut:
  184. x.i = 0;
  185. cofj = x.r;
  186. mag = 0;
  187. n -= 1;
  188. }
  189. /* divide working polynomial cof(z) by z - x */
  190. p = &cof[1];
  191. *p += cofj * *(p-1);
  192. for( j=1; j<n; j++ )
  193. {
  194. *(p+1) += cofj * *p - mag * *(p-1);
  195. p++;
  196. }
  197. setrut:
  198. root[nroot].r = x.r;
  199. root[nroot].i = x.i;
  200. nroot += 1;
  201. if( mag != 0.0 )
  202. {
  203. x.i = -x.i;
  204. mag = 0;
  205. goto setrut; /* fill in the complex conjugate root */
  206. }
  207. if( n > 0 )
  208. goto nxtrut;
  209. return(0);
  210. }