00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022 #include "sinfo_solve_poly_root.h"
00023
00024
00025 #define RADIX 2
00026 #define RADIX2 (RADIX*RADIX)
00027
00042 void
00043 sinfo_balance_companion_matrix (double *m, size_t nc)
00044 {
00045 int not_converged = 1;
00046
00047 double row_norm = 0;
00048 double col_norm = 0;
00049
00050 while (not_converged)
00051 {
00052 size_t i, j;
00053 double g, f, s;
00054
00055 not_converged = 0;
00056
00057 for (i = 0; i < nc; i++)
00058 {
00059
00060
00061 if (i != nc - 1)
00062 {
00063 col_norm = fabs (MAT (m, i + 1, i, nc));
00064 }
00065 else
00066 {
00067 col_norm = 0;
00068
00069 for (j = 0; j < nc - 1; j++)
00070 {
00071 col_norm += fabs (MAT (m, j, nc - 1, nc));
00072 }
00073 }
00074
00075
00076
00077 if (i == 0)
00078 {
00079 row_norm = fabs (MAT (m, 0, nc - 1, nc));
00080 }
00081 else if (i == nc - 1)
00082 {
00083 row_norm = fabs (MAT (m, i, i - 1, nc));
00084 }
00085 else
00086 {
00087 row_norm = (fabs (MAT (m, i, i - 1, nc))
00088 + fabs (MAT (m, i, nc - 1, nc)));
00089 }
00090
00091 if (col_norm == 0 || row_norm == 0)
00092 {
00093 continue;
00094 }
00095
00096 g = row_norm / RADIX;
00097 f = 1;
00098 s = col_norm + row_norm;
00099
00100 while (col_norm < g)
00101 {
00102 f *= RADIX;
00103 col_norm *= RADIX2;
00104 }
00105
00106 g = row_norm * RADIX;
00107
00108 while (col_norm > g)
00109 {
00110 f /= RADIX;
00111 col_norm /= RADIX2;
00112 }
00113
00114 if ((row_norm + col_norm) < 0.95 * s * f)
00115 {
00116 not_converged = 1;
00117
00118 g = 1 / f;
00119
00120 if (i == 0)
00121 {
00122 MAT (m, 0, nc - 1, nc) *= g;
00123 }
00124 else
00125 {
00126 MAT (m, i, i - 1, nc) *= g;
00127 MAT (m, i, nc - 1, nc) *= g;
00128 }
00129
00130 if (i == nc - 1)
00131 {
00132 for (j = 0; j < nc; j++)
00133 {
00134 MAT (m, j, i, nc) *= f;
00135 }
00136 }
00137 else
00138 {
00139 MAT (m, i + 1, i, nc) *= f;
00140 }
00141 }
00142 }
00143 }
00144 }