3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2006, 2007 Gerard Jungman, Patrick Alken
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 /* Author: G. Jungman, Modified: B. Gough. */
24 #include <gsl/gsl_math.h>
25 #include <gsl/gsl_eigen.h>
26 #include <gsl/gsl_complex.h>
27 #include <gsl/gsl_complex_math.h>
29 /* The eigen_sort below is not very good, but it is simple and
30 * self-contained. We can always implement an improved sort later. */
33 gsl_eigen_symmv_sort (gsl_vector * eval, gsl_matrix * evec,
34 gsl_eigen_sort_t sort_type)
36 if (evec->size1 != evec->size2)
38 GSL_ERROR ("eigenvector matrix must be square", GSL_ENOTSQR);
40 else if (eval->size != evec->size1)
42 GSL_ERROR ("eigenvalues must match eigenvector matrix", GSL_EBADLEN);
46 const size_t N = eval->size;
49 for (i = 0; i < N - 1; i++)
54 double ek = gsl_vector_get (eval, i);
56 /* search for something to swap */
57 for (j = i + 1; j < N; j++)
60 const double ej = gsl_vector_get (eval, j);
64 case GSL_EIGEN_SORT_VAL_ASC:
67 case GSL_EIGEN_SORT_VAL_DESC:
70 case GSL_EIGEN_SORT_ABS_ASC:
71 test = (fabs (ej) < fabs (ek));
73 case GSL_EIGEN_SORT_ABS_DESC:
74 test = (fabs (ej) > fabs (ek));
77 GSL_ERROR ("unrecognized sort type", GSL_EINVAL);
89 /* swap eigenvalues */
90 gsl_vector_swap_elements (eval, i, k);
92 /* swap eigenvectors */
93 gsl_matrix_swap_columns (evec, i, k);
103 gsl_eigen_hermv_sort (gsl_vector * eval, gsl_matrix_complex * evec,
104 gsl_eigen_sort_t sort_type)
106 if (evec->size1 != evec->size2)
108 GSL_ERROR ("eigenvector matrix must be square", GSL_ENOTSQR);
110 else if (eval->size != evec->size1)
112 GSL_ERROR ("eigenvalues must match eigenvector matrix", GSL_EBADLEN);
116 const size_t N = eval->size;
119 for (i = 0; i < N - 1; i++)
124 double ek = gsl_vector_get (eval, i);
126 /* search for something to swap */
127 for (j = i + 1; j < N; j++)
130 const double ej = gsl_vector_get (eval, j);
134 case GSL_EIGEN_SORT_VAL_ASC:
137 case GSL_EIGEN_SORT_VAL_DESC:
140 case GSL_EIGEN_SORT_ABS_ASC:
141 test = (fabs (ej) < fabs (ek));
143 case GSL_EIGEN_SORT_ABS_DESC:
144 test = (fabs (ej) > fabs (ek));
147 GSL_ERROR ("unrecognized sort type", GSL_EINVAL);
159 /* swap eigenvalues */
160 gsl_vector_swap_elements (eval, i, k);
162 /* swap eigenvectors */
163 gsl_matrix_complex_swap_columns (evec, i, k);
172 gsl_eigen_nonsymmv_sort (gsl_vector_complex * eval,
173 gsl_matrix_complex * evec,
174 gsl_eigen_sort_t sort_type)
176 if (evec && (evec->size1 != evec->size2))
178 GSL_ERROR ("eigenvector matrix must be square", GSL_ENOTSQR);
180 else if (evec && (eval->size != evec->size1))
182 GSL_ERROR ("eigenvalues must match eigenvector matrix", GSL_EBADLEN);
186 const size_t N = eval->size;
189 for (i = 0; i < N - 1; i++)
194 gsl_complex ek = gsl_vector_complex_get (eval, i);
196 /* search for something to swap */
197 for (j = i + 1; j < N; j++)
200 const gsl_complex ej = gsl_vector_complex_get (eval, j);
204 case GSL_EIGEN_SORT_ABS_ASC:
205 test = (gsl_complex_abs (ej) < gsl_complex_abs (ek));
207 case GSL_EIGEN_SORT_ABS_DESC:
208 test = (gsl_complex_abs (ej) > gsl_complex_abs (ek));
210 case GSL_EIGEN_SORT_VAL_ASC:
211 case GSL_EIGEN_SORT_VAL_DESC:
213 GSL_ERROR ("invalid sort type", GSL_EINVAL);
225 /* swap eigenvalues */
226 gsl_vector_complex_swap_elements (eval, i, k);
228 /* swap eigenvectors */
230 gsl_matrix_complex_swap_columns (evec, i, k);
239 gsl_eigen_gensymmv_sort (gsl_vector * eval, gsl_matrix * evec,
240 gsl_eigen_sort_t sort_type)
244 s = gsl_eigen_symmv_sort(eval, evec, sort_type);
250 gsl_eigen_genhermv_sort (gsl_vector * eval, gsl_matrix_complex * evec,
251 gsl_eigen_sort_t sort_type)
255 s = gsl_eigen_hermv_sort(eval, evec, sort_type);
261 gsl_eigen_genv_sort (gsl_vector_complex * alpha, gsl_vector * beta,
262 gsl_matrix_complex * evec, gsl_eigen_sort_t sort_type)
264 if (evec->size1 != evec->size2)
266 GSL_ERROR ("eigenvector matrix must be square", GSL_ENOTSQR);
268 else if (alpha->size != evec->size1 || beta->size != evec->size1)
270 GSL_ERROR ("eigenvalues must match eigenvector matrix", GSL_EBADLEN);
274 const size_t N = alpha->size;
277 for (i = 0; i < N - 1; i++)
282 gsl_complex ak = gsl_vector_complex_get (alpha, i);
283 double bk = gsl_vector_get(beta, i);
286 if (bk < GSL_DBL_EPSILON)
289 GSL_SIGN(GSL_REAL(ak)) ? GSL_POSINF : GSL_NEGINF,
290 GSL_SIGN(GSL_IMAG(ak)) ? GSL_POSINF : GSL_NEGINF);
293 ek = gsl_complex_div_real(ak, bk);
295 /* search for something to swap */
296 for (j = i + 1; j < N; j++)
299 const gsl_complex aj = gsl_vector_complex_get (alpha, j);
300 double bj = gsl_vector_get(beta, j);
303 if (bj < GSL_DBL_EPSILON)
306 GSL_SIGN(GSL_REAL(aj)) ? GSL_POSINF : GSL_NEGINF,
307 GSL_SIGN(GSL_IMAG(aj)) ? GSL_POSINF : GSL_NEGINF);
310 ej = gsl_complex_div_real(aj, bj);
314 case GSL_EIGEN_SORT_ABS_ASC:
315 test = (gsl_complex_abs (ej) < gsl_complex_abs (ek));
317 case GSL_EIGEN_SORT_ABS_DESC:
318 test = (gsl_complex_abs (ej) > gsl_complex_abs (ek));
320 case GSL_EIGEN_SORT_VAL_ASC:
321 case GSL_EIGEN_SORT_VAL_DESC:
323 GSL_ERROR ("invalid sort type", GSL_EINVAL);
335 /* swap eigenvalues */
336 gsl_vector_complex_swap_elements (alpha, i, k);
337 gsl_vector_swap_elements (beta, i, k);
339 /* swap eigenvectors */
340 gsl_matrix_complex_swap_columns (evec, i, k);