comparison armadillo-2.4.4/include/armadillo_bits/fn_eig.hpp @ 0:8b6102e2a9b0

Armadillo Library
author maxzanoni76 <max.zanoni@eecs.qmul.ac.uk>
date Wed, 11 Apr 2012 09:27:06 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:8b6102e2a9b0
1 // Copyright (C) 2008-2011 NICTA (www.nicta.com.au)
2 // Copyright (C) 2008-2011 Conrad Sanderson
3 // Copyright (C) 2009 Edmund Highcock
4 // Copyright (C) 2011 Stanislav Funiak
5 //
6 // This file is part of the Armadillo C++ library.
7 // It is provided without any warranty of fitness
8 // for any purpose. You can redistribute this file
9 // and/or modify it under the terms of the GNU
10 // Lesser General Public License (LGPL) as published
11 // by the Free Software Foundation, either version 3
12 // of the License or (at your option) any later version.
13 // (see http://www.opensource.org/licenses for more info)
14
15
16 //! \addtogroup fn_eig
17 //! @{
18
19
20 //
21 // symmetric/hermitian matrices
22 //
23
24
25 //! Eigenvalues of real/complex symmetric/hermitian matrix X
26 template<typename T1>
27 inline
28 bool
29 eig_sym
30 (
31 Col<typename T1::pod_type>& eigval,
32 const Base<typename T1::elem_type,T1>& X,
33 const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
34 )
35 {
36 arma_extra_debug_sigprint();
37 arma_ignore(junk);
38
39 // unwrap_check not used as T1::elem_type and T1::pod_type may not be the same.
40 // furthermore, it doesn't matter if X is an alias of eigval, as auxlib::eig_sym() makes a copy of X
41
42 const bool status = auxlib::eig_sym(eigval, X);
43
44 if(status == false)
45 {
46 eigval.reset();
47 arma_bad("eig_sym(): failed to converge", false);
48 }
49
50 return status;
51 }
52
53
54
55 //! Eigenvalues of real/complex symmetric/hermitian matrix X
56 template<typename T1>
57 inline
58 Col<typename T1::pod_type>
59 eig_sym
60 (
61 const Base<typename T1::elem_type,T1>& X,
62 const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
63 )
64 {
65 arma_extra_debug_sigprint();
66 arma_ignore(junk);
67
68 Col<typename T1::pod_type> out;
69 const bool status = auxlib::eig_sym(out, X);
70
71 if(status == false)
72 {
73 out.reset();
74 arma_bad("eig_sym(): failed to converge");
75 }
76
77 return out;
78 }
79
80
81
82 //! Eigenvalues and eigenvectors of real/complex symmetric/hermitian matrix X
83 template<typename T1>
84 inline
85 bool
86 eig_sym
87 (
88 Col<typename T1::pod_type>& eigval,
89 Mat<typename T1::elem_type>& eigvec,
90 const Base<typename T1::elem_type,T1>& X,
91 const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
92 )
93 {
94 arma_extra_debug_sigprint();
95 arma_ignore(junk);
96
97 arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_sym(): eigval is an alias of eigvec" );
98
99 const bool status = auxlib::eig_sym(eigval, eigvec, X);
100
101 if(status == false)
102 {
103 eigval.reset();
104 eigvec.reset();
105 arma_bad("eig_sym(): failed to converge", false);
106 }
107
108 return status;
109 }
110
111
112
113 //
114 // general matrices
115 //
116
117
118
119 //! Eigenvalues and eigenvectors (both left and right) of general real/complex square matrix X
120 template<typename T1>
121 inline
122 bool
123 eig_gen
124 (
125 Col< std::complex<typename T1::pod_type> >& eigval,
126 Mat<typename T1::elem_type>& l_eigvec,
127 Mat<typename T1::elem_type>& r_eigvec,
128 const Base<typename T1::elem_type,T1>& X,
129 const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
130 )
131 {
132 arma_extra_debug_sigprint();
133 arma_ignore(junk);
134
135 arma_debug_check
136 (
137 ((&l_eigvec) == (&r_eigvec)),
138 "eig_gen(): l_eigvec is an alias of r_eigvec"
139 );
140
141 arma_debug_check
142 (
143 (
144 (((void*)(&eigval)) == ((void*)(&l_eigvec)))
145 ||
146 (((void*)(&eigval)) == ((void*)(&r_eigvec)))
147 ),
148 "eig_gen(): eigval is an alias of l_eigvec or r_eigvec"
149 );
150
151 const bool status = auxlib::eig_gen(eigval, l_eigvec, r_eigvec, X, 'b');
152
153 if(status == false)
154 {
155 eigval.reset();
156 l_eigvec.reset();
157 r_eigvec.reset();
158 arma_bad("eig_gen(): failed to converge", false);
159 }
160
161 return status;
162 }
163
164
165
166 //! Eigenvalues and eigenvectors of general real square matrix X.
167 //! Optional argument 'side' specifies which eigenvectors should be computed:
168 //! 'r' for right (default) and 'l' for left.
169 template<typename eT, typename T1>
170 inline
171 bool
172 eig_gen
173 (
174 Col< std::complex<eT> >& eigval,
175 Mat< std::complex<eT> >& eigvec,
176 const Base<eT, T1>& X,
177 const char side = 'r',
178 const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
179 )
180 {
181 arma_extra_debug_sigprint();
182 arma_ignore(junk);
183
184 //std::cout << "real" << std::endl;
185
186 arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_gen(): eigval is an alias of eigvec" );
187
188 Mat<eT> dummy_eigvec;
189 Mat<eT> tmp_eigvec;
190
191 bool status;
192
193 switch(side)
194 {
195 case 'r':
196 status = auxlib::eig_gen(eigval, dummy_eigvec, tmp_eigvec, X, side);
197 break;
198
199 case 'l':
200 status = auxlib::eig_gen(eigval, tmp_eigvec, dummy_eigvec, X, side);
201 break;
202
203 default:
204 arma_stop("eig_gen(): parameter 'side' is invalid");
205 status = false;
206 }
207
208 if(status == false)
209 {
210 eigval.reset();
211 eigvec.reset();
212 arma_bad("eig_gen(): failed to converge", false);
213 }
214 else
215 {
216 const uword n = eigval.n_elem;
217
218 if(n > 0)
219 {
220 eigvec.set_size(n,n);
221
222 for(uword j=0; j<n; ++j)
223 {
224 if( (j < n-1) && (eigval[j] == std::conj(eigval[j+1])) )
225 {
226 // eigvec.col(j) = Mat< std::complex<eT> >( tmp_eigvec.col(j), tmp_eigvec.col(j+1) );
227 // eigvec.col(j+1) = Mat< std::complex<eT> >( tmp_eigvec.col(j), -tmp_eigvec.col(j+1) );
228
229 for(uword i=0; i<n; ++i)
230 {
231 eigvec.at(i,j) = std::complex<eT>( tmp_eigvec.at(i,j), tmp_eigvec.at(i,j+1) );
232 eigvec.at(i,j+1) = std::complex<eT>( tmp_eigvec.at(i,j), -tmp_eigvec.at(i,j+1) );
233 }
234
235 ++j;
236 }
237 else
238 {
239 // eigvec.col(i) = tmp_eigvec.col(i);
240
241 for(uword i=0; i<n; ++i)
242 {
243 eigvec.at(i,j) = std::complex<eT>(tmp_eigvec.at(i,j), eT(0));
244 }
245
246 }
247 }
248 }
249 }
250
251 return status;
252 }
253
254
255
256 //! Eigenvalues and eigenvectors of general complex square matrix X
257 //! Optional argument 'side' specifies which eigenvectors should be computed:
258 //! 'r' for right (default) and 'l' for left.
259 template<typename T, typename T1>
260 inline
261 bool
262 eig_gen
263 (
264 Col<std::complex<T> >& eigval,
265 Mat<std::complex<T> >& eigvec,
266 const Base<std::complex<T>, T1>& X,
267 const char side = 'r',
268 const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
269 )
270 {
271 arma_extra_debug_sigprint();
272 arma_ignore(junk);
273
274 //std::cout << "complex" << std::endl;
275
276 arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_gen(): eigval is an alias of eigvec" );
277
278 Mat< std::complex<T> > dummy_eigvec;
279
280 bool status;
281
282 switch(side)
283 {
284 case 'r':
285 status = auxlib::eig_gen(eigval, dummy_eigvec, eigvec, X, side);
286 break;
287
288 case 'l':
289 status = auxlib::eig_gen(eigval, eigvec, dummy_eigvec, X, side);
290 break;
291
292 default:
293 arma_stop("eig_gen(): parameter 'side' is invalid");
294 status = false;
295 }
296
297 if(status == false)
298 {
299 eigval.reset();
300 eigvec.reset();
301 arma_bad("eig_gen(): failed to converge", false);
302 }
303
304 return status;
305 }
306
307
308
309 //! @}
310