1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17 
18 
19 //! \addtogroup fn_eigs_gen
20 //! @{
21 
22 
23 //! eigenvalues of general sparse matrix X
24 template<typename T1>
25 arma_warn_unused
26 inline
27 typename enable_if2< is_real<typename T1::pod_type>::value, Col< std::complex<typename T1::pod_type> > >::result
eigs_gen(const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const char * form="lm",const eigs_opts opts=eigs_opts ())28 eigs_gen
29   (
30   const SpBase<typename T1::elem_type, T1>& X,
31   const uword                               n_eigvals,
32   const char*                               form = "lm",
33   const eigs_opts                           opts = eigs_opts()
34   )
35   {
36   arma_extra_debug_sigprint();
37 
38   typedef typename T1::pod_type T;
39 
40   Mat< std::complex<T> > eigvec;
41   Col< std::complex<T> > eigval;
42 
43   sp_auxlib::form_type form_val = sp_auxlib::interpret_form_str(form);
44 
45   const bool status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, form_val, opts);
46 
47   if(status == false)
48     {
49     eigval.soft_reset();
50     arma_stop_runtime_error("eigs_gen(): decomposition failed");
51     }
52 
53   return eigval;
54   }
55 
56 
57 
58 //! this form is deprecated; use eigs_gen(X, n_eigvals, form, opts) instead
59 template<typename T1>
60 arma_deprecated
61 inline
62 typename enable_if2< is_real<typename T1::pod_type>::value, Col< std::complex<typename T1::pod_type> > >::result
eigs_gen(const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const char * form,const typename T1::pod_type tol)63 eigs_gen
64   (
65   const SpBase<typename T1::elem_type, T1>& X,
66   const uword                               n_eigvals,
67   const char*                               form,
68   const typename T1::pod_type               tol
69   )
70   {
71   arma_extra_debug_sigprint();
72 
73   eigs_opts opts;
74   opts.tol = tol;
75 
76   return eigs_gen(X, n_eigvals, form, opts);
77   }
78 
79 
80 
81 template<typename T1>
82 arma_warn_unused
83 inline
84 typename enable_if2< is_real<typename T1::pod_type>::value, Col< std::complex<typename T1::pod_type> > >::result
eigs_gen(const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const std::complex<typename T1::pod_type> sigma,const eigs_opts opts=eigs_opts ())85 eigs_gen
86   (
87   const SpBase<typename T1::elem_type, T1>& X,
88   const uword                               n_eigvals,
89   const std::complex<typename T1::pod_type> sigma,
90   const eigs_opts                           opts = eigs_opts()
91   )
92   {
93   arma_extra_debug_sigprint();
94 
95   typedef typename T1::pod_type T;
96 
97   Mat< std::complex<T> > eigvec;
98   Col< std::complex<T> > eigval;
99 
100   bool status = false;
101 
102   // If X is real and sigma is truly complex, treat X as complex.
103   // The reason is that we are still not able to apply truly complex shifts to real matrices
104   if( (is_real<typename T1::elem_type>::yes) && (std::imag(sigma) != T(0)) )
105     {
106     status = sp_auxlib::eigs_gen(eigval, eigvec, conv_to< SpMat< std::complex<T> > >::from(X), n_eigvals, sigma, opts);
107     }
108   else
109     {
110     status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, sigma, opts);
111     }
112 
113   if(status == false)
114     {
115     eigval.soft_reset();
116     arma_stop_runtime_error("eigs_gen(): decomposition failed");
117     }
118 
119   return eigval;
120   }
121 
122 
123 
124 template<typename T1>
125 arma_warn_unused
126 inline
127 typename enable_if2< is_real<typename T1::pod_type>::value, Col< std::complex<typename T1::pod_type> > >::result
eigs_gen(const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const double sigma,const eigs_opts opts=eigs_opts ())128 eigs_gen
129   (
130   const SpBase<typename T1::elem_type, T1>& X,
131   const uword                               n_eigvals,
132   const double                              sigma,
133   const eigs_opts                           opts = eigs_opts()
134   )
135   {
136   arma_extra_debug_sigprint();
137 
138   typedef typename T1::pod_type T;
139 
140   Mat< std::complex<T> > eigvec;
141   Col< std::complex<T> > eigval;
142 
143   const bool status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, std::complex<T>(T(sigma)), opts);
144 
145   if(status == false)
146     {
147     eigval.soft_reset();
148     arma_stop_runtime_error("eigs_gen(): decomposition failed");
149     }
150 
151   return eigval;
152   }
153 
154 
155 
156 //! eigenvalues of general sparse matrix X
157 template<typename T1>
158 inline
159 typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result
eigs_gen(Col<std::complex<typename T1::pod_type>> & eigval,const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const char * form="lm",const eigs_opts opts=eigs_opts ())160 eigs_gen
161   (
162            Col< std::complex<typename T1::pod_type> >& eigval,
163   const SpBase<typename T1::elem_type, T1>&            X,
164   const uword                                          n_eigvals,
165   const char*                                          form = "lm",
166   const eigs_opts                                      opts = eigs_opts()
167   )
168   {
169   arma_extra_debug_sigprint();
170 
171   typedef typename T1::pod_type T;
172 
173   Mat< std::complex<T> > eigvec;
174 
175   sp_auxlib::form_type form_val = sp_auxlib::interpret_form_str(form);
176 
177   const bool status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, form_val, opts);
178 
179   if(status == false)
180     {
181     eigval.soft_reset();
182     arma_debug_warn_level(3, "eigs_gen(): decomposition failed");
183     }
184 
185   return status;
186   }
187 
188 
189 
190 //! this form is deprecated; use eigs_gen(eigval, X, n_eigvals, form, opts) instead
191 template<typename T1>
192 arma_deprecated
193 inline
194 typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result
eigs_gen(Col<std::complex<typename T1::pod_type>> & eigval,const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const char * form,const typename T1::pod_type tol)195 eigs_gen
196   (
197            Col< std::complex<typename T1::pod_type> >& eigval,
198   const SpBase<typename T1::elem_type, T1>&            X,
199   const uword                                          n_eigvals,
200   const char*                                          form,
201   const typename T1::pod_type                          tol
202   )
203   {
204   arma_extra_debug_sigprint();
205 
206   eigs_opts opts;
207   opts.tol = tol;
208 
209   return eigs_gen(eigval, X, n_eigvals, form, opts);
210   }
211 
212 
213 
214 template<typename T1>
215 inline
216 typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result
eigs_gen(Col<std::complex<typename T1::pod_type>> & eigval,const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const std::complex<typename T1::pod_type> sigma,const eigs_opts opts=eigs_opts ())217 eigs_gen
218   (
219            Col< std::complex<typename T1::pod_type> >& eigval,
220   const SpBase<typename T1::elem_type, T1>&            X,
221   const uword                                          n_eigvals,
222   const std::complex<typename T1::pod_type>            sigma,
223   const eigs_opts                                      opts = eigs_opts()
224   )
225   {
226   arma_extra_debug_sigprint();
227 
228   typedef typename T1::pod_type T;
229 
230   Mat< std::complex<T> > eigvec;
231 
232   bool status = false;
233 
234   // If X is real and sigma is truly complex, treat X as complex.
235   // The reason is that we are still not able to apply truly complex shifts to real matrices
236   if( (is_real<typename T1::elem_type>::yes) && (std::imag(sigma) != T(0)) )
237     {
238     status = sp_auxlib::eigs_gen(eigval, eigvec, conv_to< SpMat< std::complex<T> > >::from(X), n_eigvals, sigma, opts);
239     }
240   else
241     {
242     status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, sigma, opts);
243     }
244 
245   if(status == false)
246     {
247     eigval.soft_reset();
248     arma_debug_warn_level(3, "eigs_gen(): decomposition failed");
249     }
250 
251   return status;
252   }
253 
254 
255 
256 template<typename T1>
257 inline
258 typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result
eigs_gen(Col<std::complex<typename T1::pod_type>> & eigval,const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const double sigma,const eigs_opts opts=eigs_opts ())259 eigs_gen
260   (
261            Col< std::complex<typename T1::pod_type> >& eigval,
262   const SpBase<typename T1::elem_type, T1>&            X,
263   const uword                                          n_eigvals,
264   const double                                         sigma,
265   const eigs_opts                                      opts = eigs_opts()
266   )
267   {
268   arma_extra_debug_sigprint();
269 
270   typedef typename T1::pod_type T;
271 
272   Mat< std::complex<T> > eigvec;
273 
274   const bool status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, std::complex<T>(T(sigma)), opts);
275 
276   if(status == false)
277     {
278     eigval.soft_reset();
279     arma_debug_warn_level(3, "eigs_gen(): decomposition failed");
280     }
281 
282   return status;
283   }
284 
285 
286 
287 //! eigenvalues and eigenvectors of general sparse matrix X
288 template<typename T1>
289 inline
290 typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result
eigs_gen(Col<std::complex<typename T1::pod_type>> & eigval,Mat<std::complex<typename T1::pod_type>> & eigvec,const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const char * form="lm",const eigs_opts opts=eigs_opts ())291 eigs_gen
292   (
293          Col< std::complex<typename T1::pod_type> >& eigval,
294          Mat< std::complex<typename T1::pod_type> >& eigvec,
295   const SpBase<typename T1::elem_type, T1>&          X,
296   const uword                                        n_eigvals,
297   const char*                                        form = "lm",
298   const eigs_opts                                    opts = eigs_opts()
299   )
300   {
301   arma_extra_debug_sigprint();
302 
303   // typedef typename T1::pod_type T;
304 
305   arma_debug_check( void_ptr(&eigval) == void_ptr(&eigvec), "eigs_gen(): parameter 'eigval' is an alias of parameter 'eigvec'" );
306 
307   sp_auxlib::form_type form_val = sp_auxlib::interpret_form_str(form);
308 
309   const bool status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, form_val, opts);
310 
311   if(status == false)
312     {
313     eigval.soft_reset();
314     eigvec.soft_reset();
315     arma_debug_warn_level(3, "eigs_gen(): decomposition failed");
316     }
317 
318   return status;
319   }
320 
321 
322 
323 //! this form is deprecated; use eigs_gen(eigval, eigvec, X, n_eigvals, form, opts) instead
324 template<typename T1>
325 arma_deprecated
326 inline
327 typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result
eigs_gen(Col<std::complex<typename T1::pod_type>> & eigval,Mat<std::complex<typename T1::pod_type>> & eigvec,const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const char * form,const typename T1::pod_type tol)328 eigs_gen
329   (
330          Col< std::complex<typename T1::pod_type> >& eigval,
331          Mat< std::complex<typename T1::pod_type> >& eigvec,
332   const SpBase<typename T1::elem_type, T1>&          X,
333   const uword                                        n_eigvals,
334   const char*                                        form,
335   const typename T1::pod_type                        tol
336   )
337   {
338   arma_extra_debug_sigprint();
339 
340   eigs_opts opts;
341   opts.tol = tol;
342 
343   return eigs_gen(eigval, eigvec, X, n_eigvals, form, opts);
344   }
345 
346 
347 
348 template<typename T1>
349 inline
350 typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result
eigs_gen(Col<std::complex<typename T1::pod_type>> & eigval,Mat<std::complex<typename T1::pod_type>> & eigvec,const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const std::complex<typename T1::pod_type> sigma,const eigs_opts opts=eigs_opts ())351 eigs_gen
352   (
353          Col< std::complex<typename T1::pod_type> >& eigval,
354          Mat< std::complex<typename T1::pod_type> >& eigvec,
355   const SpBase<typename T1::elem_type, T1>&          X,
356   const uword                                        n_eigvals,
357   const std::complex<typename T1::pod_type>          sigma,
358   const eigs_opts                                    opts = eigs_opts()
359   )
360   {
361   arma_extra_debug_sigprint();
362 
363   typedef typename T1::pod_type T;
364 
365   arma_debug_check( void_ptr(&eigval) == void_ptr(&eigvec), "eigs_gen(): parameter 'eigval' is an alias of parameter 'eigvec'" );
366 
367   bool status = false;
368 
369   // If X is real and sigma is truly complex, treat X as complex.
370   // The reason is that we are still not able to apply truly complex shifts to real matrices
371   if( (is_real<typename T1::elem_type>::yes) && (std::imag(sigma) != T(0)) )
372     {
373     status = sp_auxlib::eigs_gen(eigval, eigvec, conv_to< SpMat< std::complex<T> > >::from(X), n_eigvals, sigma, opts);
374     }
375   else
376     {
377     status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, sigma, opts);
378     }
379 
380   if(status == false)
381     {
382     eigval.soft_reset();
383     eigvec.soft_reset();
384     arma_debug_warn_level(3, "eigs_gen(): decomposition failed");
385     }
386 
387   return status;
388   }
389 
390 
391 
392 template<typename T1>
393 inline
394 typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result
eigs_gen(Col<std::complex<typename T1::pod_type>> & eigval,Mat<std::complex<typename T1::pod_type>> & eigvec,const SpBase<typename T1::elem_type,T1> & X,const uword n_eigvals,const double sigma,const eigs_opts opts=eigs_opts ())395 eigs_gen
396   (
397          Col< std::complex<typename T1::pod_type> >& eigval,
398          Mat< std::complex<typename T1::pod_type> >& eigvec,
399   const SpBase<typename T1::elem_type, T1>&          X,
400   const uword                                        n_eigvals,
401   const double                                       sigma,
402   const eigs_opts                                    opts = eigs_opts()
403   )
404   {
405   arma_extra_debug_sigprint();
406 
407   typedef typename T1::pod_type T;
408 
409   arma_debug_check( void_ptr(&eigval) == void_ptr(&eigvec), "eigs_gen(): parameter 'eigval' is an alias of parameter 'eigvec'" );
410 
411   const bool status = sp_auxlib::eigs_gen(eigval, eigvec, X, n_eigvals, std::complex<T>(T(sigma)), opts);
412 
413   if(status == false)
414     {
415     eigval.soft_reset();
416     eigvec.soft_reset();
417     arma_debug_warn_level(3, "eigs_gen(): decomposition failed");
418     }
419 
420   return status;
421   }
422 
423 
424 
425 //! @}
426