@@ -40,11 +40,11 @@ pub struct EigWork<T: Scalar> {
40
40
pub jobvl : JobEv ,
41
41
42
42
/// Eigenvalues used in complex routines
43
- pub eigs : Option < Vec < MaybeUninit < T > > > ,
43
+ pub eigs : Option < Vec < MaybeUninit < T :: Complex > > > ,
44
44
/// Real part of eigenvalues used in real routines
45
- pub eigs_re : Option < Vec < MaybeUninit < T > > > ,
45
+ pub eigs_re : Option < Vec < MaybeUninit < T :: Real > > > ,
46
46
/// Imaginary part of eigenvalues used in real routines
47
- pub eigs_im : Option < Vec < MaybeUninit < T > > > ,
47
+ pub eigs_im : Option < Vec < MaybeUninit < T :: Real > > > ,
48
48
49
49
/// Left eigenvectors
50
50
pub vl : Option < Vec < MaybeUninit < T > > > ,
@@ -71,6 +71,26 @@ pub struct EigRef<'work, T: Scalar> {
71
71
pub vl : Option < & ' work [ T :: Complex ] > ,
72
72
}
73
73
74
+ impl < T : Scalar > EigWork < T > {
75
+ /// Create complex eigenvalues from real and imaginary parts.
76
+ unsafe fn reconstruct_eigs ( & mut self ) {
77
+ let n = self . n as usize ;
78
+ if self . eigs . is_none ( ) {
79
+ self . eigs = Some ( vec_uninit ( n) ) ;
80
+ }
81
+ let eigs = self . eigs . as_mut ( ) . unwrap ( ) ;
82
+ if let ( Some ( re) , Some ( im) ) = ( self . eigs_re . as_ref ( ) , self . eigs_im . as_ref ( ) ) {
83
+ assert_eq ! ( re. len( ) , n) ;
84
+ assert_eq ! ( im. len( ) , n) ;
85
+ for i in 0 ..n {
86
+ eigs[ i] . write ( T :: complex ( re[ i] . assume_init ( ) , im[ i] . assume_init ( ) ) ) ;
87
+ }
88
+ } else {
89
+ panic ! ( "Called without constructing eigs_re and eigs_im" ) ;
90
+ }
91
+ }
92
+ }
93
+
74
94
pub trait EigWorkImpl : Sized {
75
95
type Elem : Scalar ;
76
96
/// Create new working memory for eigenvalues compution.
@@ -227,6 +247,109 @@ impl EigWorkImpl for EigWork<c64> {
227
247
}
228
248
}
229
249
250
+ impl EigWorkImpl for EigWork < f64 > {
251
+ type Elem = f64 ;
252
+
253
+ fn new ( calc_v : bool , l : MatrixLayout ) -> Result < Self > {
254
+ let ( n, _) = l. size ( ) ;
255
+ let ( jobvl, jobvr) = if calc_v {
256
+ match l {
257
+ MatrixLayout :: C { .. } => ( JobEv :: All , JobEv :: None ) ,
258
+ MatrixLayout :: F { .. } => ( JobEv :: None , JobEv :: All ) ,
259
+ }
260
+ } else {
261
+ ( JobEv :: None , JobEv :: None )
262
+ } ;
263
+ let mut eigs_re: Vec < MaybeUninit < f64 > > = vec_uninit ( n as usize ) ;
264
+ let mut eigs_im: Vec < MaybeUninit < f64 > > = vec_uninit ( n as usize ) ;
265
+
266
+ let mut vl: Option < Vec < MaybeUninit < f64 > > > = jobvl. then ( || vec_uninit ( ( n * n) as usize ) ) ;
267
+ let mut vr: Option < Vec < MaybeUninit < f64 > > > = jobvr. then ( || vec_uninit ( ( n * n) as usize ) ) ;
268
+
269
+ // calc work size
270
+ let mut info = 0 ;
271
+ let mut work_size: [ f64 ; 1 ] = [ 0.0 ] ;
272
+ unsafe {
273
+ lapack_sys:: dgeev_ (
274
+ jobvl. as_ptr ( ) ,
275
+ jobvr. as_ptr ( ) ,
276
+ & n,
277
+ std:: ptr:: null_mut ( ) ,
278
+ & n,
279
+ AsPtr :: as_mut_ptr ( & mut eigs_re) ,
280
+ AsPtr :: as_mut_ptr ( & mut eigs_im) ,
281
+ AsPtr :: as_mut_ptr ( vl. as_deref_mut ( ) . unwrap_or ( & mut [ ] ) ) ,
282
+ & n,
283
+ AsPtr :: as_mut_ptr ( vr. as_deref_mut ( ) . unwrap_or ( & mut [ ] ) ) ,
284
+ & n,
285
+ AsPtr :: as_mut_ptr ( & mut work_size) ,
286
+ & ( -1 ) ,
287
+ & mut info,
288
+ )
289
+ } ;
290
+ info. as_lapack_result ( ) ?;
291
+
292
+ // actual ev
293
+ let lwork = work_size[ 0 ] . to_usize ( ) . unwrap ( ) ;
294
+ let work: Vec < MaybeUninit < f64 > > = vec_uninit ( lwork) ;
295
+
296
+ Ok ( Self {
297
+ n,
298
+ jobvr,
299
+ jobvl,
300
+ eigs : None ,
301
+ eigs_re : Some ( eigs_re) ,
302
+ eigs_im : Some ( eigs_im) ,
303
+ rwork : None ,
304
+ vl,
305
+ vr,
306
+ work,
307
+ } )
308
+ }
309
+
310
+ fn calc < ' work > ( & ' work mut self , _a : & mut [ f64 ] ) -> Result < EigRef < ' work , f64 > > {
311
+ todo ! ( )
312
+ }
313
+
314
+ fn eval ( mut self , a : & mut [ f64 ] ) -> Result < Eig < f64 > > {
315
+ let lwork = self . work . len ( ) . to_i32 ( ) . unwrap ( ) ;
316
+ let mut info = 0 ;
317
+ unsafe {
318
+ lapack_sys:: dgeev_ (
319
+ self . jobvl . as_ptr ( ) ,
320
+ self . jobvr . as_ptr ( ) ,
321
+ & self . n ,
322
+ AsPtr :: as_mut_ptr ( a) ,
323
+ & self . n ,
324
+ AsPtr :: as_mut_ptr ( self . eigs_re . as_mut ( ) . unwrap ( ) ) ,
325
+ AsPtr :: as_mut_ptr ( self . eigs_im . as_mut ( ) . unwrap ( ) ) ,
326
+ AsPtr :: as_mut_ptr ( self . vl . as_deref_mut ( ) . unwrap_or ( & mut [ ] ) ) ,
327
+ & self . n ,
328
+ AsPtr :: as_mut_ptr ( self . vr . as_deref_mut ( ) . unwrap_or ( & mut [ ] ) ) ,
329
+ & self . n ,
330
+ AsPtr :: as_mut_ptr ( & mut self . work ) ,
331
+ & lwork,
332
+ & mut info,
333
+ )
334
+ } ;
335
+ info. as_lapack_result ( ) ?;
336
+
337
+ let eig_re = unsafe { self . eigs_re . unwrap ( ) . assume_init ( ) } ;
338
+ let eig_im = unsafe { self . eigs_im . unwrap ( ) . assume_init ( ) } ;
339
+ let vl = unsafe { self . vl . map ( |v| v. assume_init ( ) ) } ;
340
+ let vr = unsafe { self . vr . map ( |v| v. assume_init ( ) ) } ;
341
+
342
+ // reconstruct eigenvalues
343
+ let eigs: Vec < c64 > = eig_re
344
+ . iter ( )
345
+ . zip ( eig_im. iter ( ) )
346
+ . map ( |( & re, & im) | c64:: new ( re, im) )
347
+ . collect ( ) ;
348
+
349
+ Ok ( Eig { eigs, vl, vr } )
350
+ }
351
+ }
352
+
230
353
macro_rules! impl_eig_complex {
231
354
( $scalar: ty, $ev: path) => {
232
355
impl Eig_ for $scalar {
0 commit comments