43 #define MAT(m, i, j, n) ((m)[(i) * (n) + (j)])
46 #define FMAT(m, i, j, n) ((m)[((i)-1) * (n) + ((j)-1)])
48 #define GSL_DBL_EPSILON 2.2204460492503131e-16
51 #define RADIX2 (RADIX * RADIX)
54 #define GSL_FAILURE -1
58 #define GSL_SET_COMPLEX_PACKED(zp, n, x, y) \
60 *((zp) + 2 * (n)) = (x); \
61 *((zp) + (2 * (n) + 1)) = (y); \
77 static void set_companion_matrix(
const double *a,
size_t n,
double *m);
81 static void balance_companion_matrix(
double *m,
size_t n);
83 static int gsl_poly_complex_solve(
const double *a,
97 assert(roots.
nrows() == a - 1);
98 assert(roots.
ncols() == 2);
99 assert(coeffs[a - 1] != 0);
105 c = (
double *)malloc(a *
sizeof(
double));
106 for (
Index i = 0; i < a; i++) c[i] = (
double)coeffs[i];
108 s = (
double *)malloc((a - 1) * 2 *
sizeof(double));
113 int status = gsl_poly_complex_solve(c, a,
w, s);
117 for (
Index i = 0; i < a - 1; i++) {
118 roots(i, 0) = (
Numeric)s[i * 2];
119 roots(i, 1) = (
Numeric)s[i * 2 + 1];
127 gsl_poly_complex_workspace_free(
w);
138 cerr <<
"matrix size n must be positive integer" << endl;
146 cerr <<
"failed to allocate space for struct" << endl;
155 w->matrix = (
double *)malloc(nc * nc *
sizeof(
double));
157 if (
w->matrix == 0) {
160 cerr <<
"failed to allocate space for workspace matrix" << endl;
173 static void balance_companion_matrix(
double *m,
size_t nc) {
174 int not_converged = 1;
179 while (not_converged) {
185 for (i = 0; i < nc; i++) {
189 col_norm = fabs(
MAT(m, i + 1, i, nc));
193 for (j = 0; j < nc - 1; j++) {
194 col_norm += fabs(
MAT(m, j, nc - 1, nc));
201 row_norm = fabs(
MAT(m, 0, nc - 1, nc));
202 }
else if (i == nc - 1) {
203 row_norm = fabs(
MAT(m, i, i - 1, nc));
205 row_norm = (fabs(
MAT(m, i, i - 1, nc)) + fabs(
MAT(m, i, nc - 1, nc)));
208 if (col_norm == 0 || row_norm == 0) {
212 g = row_norm /
RADIX;
214 s = col_norm + row_norm;
216 while (col_norm < g) {
221 g = row_norm *
RADIX;
223 while (col_norm > g) {
228 if ((row_norm + col_norm) < 0.95 * s * f) {
234 MAT(m, 0, nc - 1, nc) *= g;
236 MAT(m, i, i - 1, nc) *= g;
237 MAT(m, i, nc - 1, nc) *= g;
241 for (j = 0; j < nc; j++) {
242 MAT(m, j, i, nc) *= f;
245 MAT(m, i + 1, i, nc) *= f;
255 size_t iterations, e, i, j, k, m;
257 double w,
x,
y, s, z;
259 double p = 0,
q = 0, r = 0;
278 for (e = n; e >= 2; e--) {
279 double a1 = fabs(
FMAT(h, e, e - 1, nc));
280 double a2 = fabs(
FMAT(h, e - 1, e - 1, nc));
281 double a3 = fabs(
FMAT(h, e, e, nc));
286 x =
FMAT(h, n, n, nc);
295 y =
FMAT(h, n - 1, n - 1, nc);
296 w =
FMAT(h, n - 1, n, nc) *
FMAT(h, n, n - 1, nc);
324 if (iterations == 60)
331 if (iterations % 10 == 0 && iterations > 0) {
335 for (i = 1; i <= n; i++) {
336 FMAT(h, i, i, nc) -=
x;
339 s = fabs(
FMAT(h, n, n - 1, nc)) + fabs(
FMAT(h, n - 1, n - 2, nc));
347 for (m = n - 2; m >= e; m--) {
350 z =
FMAT(h, m, m, nc);
353 p =
FMAT(h, m, m + 1, nc) + (r * s -
w) /
FMAT(h, m + 1, m, nc);
354 q =
FMAT(h, m + 1, m + 1, nc) - z - r - s;
355 r =
FMAT(h, m + 2, m + 1, nc);
356 s = fabs(p) + fabs(
q) + fabs(r);
363 a1 = fabs(
FMAT(h, m, m - 1, nc));
364 a2 = fabs(
FMAT(h, m - 1, m - 1, nc));
365 a3 = fabs(
FMAT(h, m + 1, m + 1, nc));
371 for (i = m + 2; i <= n; i++) {
372 FMAT(h, i, i - 2, nc) = 0;
375 for (i = m + 3; i <= n; i++) {
376 FMAT(h, i, i - 3, nc) = 0;
381 for (k = m; k <= n - 1; k++) {
382 notlast = (k != n - 1);
385 p =
FMAT(h, k, k - 1, nc);
386 q =
FMAT(h, k + 1, k - 1, nc);
387 r = notlast ?
FMAT(h, k + 2, k - 1, nc) : 0.0;
389 x = fabs(p) + fabs(
q) + fabs(r);
391 if (
x == 0)
continue;
398 s =
sqrt(p * p +
q *
q + r * r);
403 FMAT(h, k, k - 1, nc) = -s *
x;
405 FMAT(h, k, k - 1, nc) *= -1;
417 for (j = k; j <= n; j++) {
418 p =
FMAT(h, k, j, nc) +
q *
FMAT(h, k + 1, j, nc);
421 p += r *
FMAT(h, k + 2, j, nc);
422 FMAT(h, k + 2, j, nc) -= p * z;
425 FMAT(h, k + 1, j, nc) -= p *
y;
426 FMAT(h, k, j, nc) -= p *
x;
429 j = (k + 3 < n) ? (k + 3) : n;
433 for (i = e; i <= j; i++) {
434 p =
x *
FMAT(h, i, k, nc) +
y *
FMAT(h, i, k + 1, nc);
437 p += z *
FMAT(h, i, k + 2, nc);
438 FMAT(h, i, k + 2, nc) -= p * r;
440 FMAT(h, i, k + 1, nc) -= p *
q;
441 FMAT(h, i, k, nc) -= p;
448 static void set_companion_matrix(
const double *a,
size_t nc,
double *m) {
451 for (i = 0; i < nc; i++)
452 for (j = 0; j < nc; j++)
MAT(m, i, j, nc) = 0.0;
454 for (i = 1; i < nc; i++)
MAT(m, i, i - 1, nc) = 1.0;
456 for (i = 0; i < nc; i++)
MAT(m, i, nc - 1, nc) = -a[i] / a[nc];
459 static int gsl_poly_complex_solve(
const double *a,
467 cerr <<
"number of terms must be a positive integer" << endl;
473 cerr <<
"cannot solve for only one term" << endl;
479 cerr <<
"leading term of polynomial must be non-zero" << endl;
484 if (
w->nc != n - 1) {
485 cerr <<
"size of workspace does not match polynomial" << endl;
492 set_companion_matrix(a, n - 1, m);
494 balance_companion_matrix(m, n - 1);
496 status = qr_companion(m, n - 1, z);