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