1 // find the roots of a polynomial numerically
9 #define ABS(z) sqrt((z).r * (z).r + (z).i * (z).i)
10 #define RANDOM (4.0 * (double) rand() / (double) RAND_MAX - 2.0)
14 } a
, b
, x
, y
, fa
, fb
, dx
, df
, c
[YMAX
];
27 if (p2
== symbol(NIL
))
36 stop("nroots: polynomial?");
42 // get the coefficients
48 stop("nroots: degree?");
50 // convert the coefficients to real and imaginary doubles
52 for (i
= 0; i
< n
; i
++) {
63 if (!isdouble(p1
) || !isdouble(p2
))
64 stop("nroots: coefficients?");
69 // pop the coefficients
73 // n is the number of coefficients, n = deg(p) + 1
77 for (k
= n
; k
> 1; k
--) {
79 if (fabs(a
.r
) < DELTA
)
81 if (fabs(a
.i
) < DELTA
)
91 // now make n equal to the number of roots
98 p1
->u
.tensor
->ndim
= 1;
99 p1
->u
.tensor
->dim
[0] = n
;
100 for (i
= 0; i
< n
; i
++)
101 p1
->u
.tensor
->elem
[i
] = stack
[h
+ i
];
107 // divide the polynomial by its leading coefficient
115 t
= y
.r
* y
.r
+ y
.i
* y
.i
;
116 for (k
= 0; k
< n
- 1; k
++) {
117 c
[k
].r
= (c
[k
].r
* y
.r
+ c
[k
].i
* y
.i
) / t
;
118 c
[k
].i
= (c
[k
].i
* y
.r
- c
[k
].r
* y
.i
) / t
;
124 // uses the secant method
132 if (ABS(c
[0]) < DELTA
) {
138 for (j
= 0; j
< 100; j
++) {
151 for (k
= 0; k
< 1000; k
++) {
155 if (ABS(fa
) < EPSILON
)
158 if (ABS(fa
) < ABS(fb
)) {
179 t
= df
.r
* df
.r
+ df
.i
* df
.i
;
184 y
.r
= (dx
.r
* df
.r
+ dx
.i
* df
.i
) / t
;
185 y
.i
= (dx
.i
* df
.r
- dx
.r
* df
.i
) / t
;
189 a
.r
= b
.r
- (y
.r
* fb
.r
- y
.i
* fb
.i
);
190 a
.i
= b
.i
- (y
.r
* fb
.i
+ y
.i
* fb
.r
);
194 stop("nroots: convergence error");
210 fa
.r
= c
[0].r
+ c
[1].r
* x
.r
- c
[1].i
* x
.i
;
211 fa
.i
= c
[0].i
+ c
[1].r
* x
.i
+ c
[1].i
* x
.r
;
213 for (k
= 2; k
< n
; k
++) {
217 t
= a
.r
* x
.r
- a
.i
* x
.i
;
218 x
.i
= a
.r
* x
.i
+ a
.i
* x
.r
;
223 fa
.r
+= c
[k
].r
* x
.r
- c
[k
].i
* x
.i
;
224 fa
.i
+= c
[k
].r
* x
.i
+ c
[k
].i
* x
.r
;
228 // divide the polynomial by x - a
234 for (k
= n
- 1; k
> 0; k
--) {
235 c
[k
- 1].r
+= c
[k
].r
* a
.r
- c
[k
].i
* a
.i
;
236 c
[k
- 1].i
+= c
[k
].i
* a
.r
+ c
[k
].r
* a
.i
;
238 if (ABS(c
[0]) > DELTA
)
239 stop("nroots: residual error");
240 for (k
= 0; k
< n
- 1; k
++) {
253 "nroots((1+i)*x^2+1)",
254 "(-0.17178-0.727673*i,0.17178+0.727673*i)",
256 "nroots(sqrt(2)*exp(i*pi/4)*x^2+1)",
257 "(-0.17178-0.727673*i,0.17178+0.727673*i)",
260 // "(-0.707107+0.707107*i,-0.707107-0.707107*i,0.707107+0.707107*i,0.707107-0.707107*i)",
266 test(__FILE__
, s
, sizeof s
/ sizeof (char *));