@@ -429,59 +429,71 @@ macro_rules! impl_eig_real {
429
429
. map( |( & re, & im) | Self :: complex( re, im) )
430
430
. collect( ) ;
431
431
432
- if !calc_v {
433
- return Ok ( ( eigs, Vec :: new( ) ) ) ;
434
- }
435
-
436
- // Reconstruct eigenvectors into complex-array
437
- // --------------------------------------------
438
- //
439
- // From LAPACK API https://software.intel.com/en-us/node/469230
440
- //
441
- // - If the j-th eigenvalue is real,
442
- // - v(j) = VR(:,j), the j-th column of VR.
443
- //
444
- // - If the j-th and (j+1)-st eigenvalues form a complex conjugate pair,
445
- // - v(j) = VR(:,j) + i*VR(:,j+1)
446
- // - v(j+1) = VR(:,j) - i*VR(:,j+1).
447
- //
448
- // In the C-layout case, we need the conjugates of the left
449
- // eigenvectors, so the signs should be reversed.
450
-
451
- let n = n as usize ;
452
- let v = vr. or( vl) . unwrap( ) ;
453
- let mut eigvecs: Vec <MaybeUninit <Self :: Complex >> = vec_uninit( n * n) ;
454
- let mut col = 0 ;
455
- while col < n {
456
- if eig_im[ col] == 0. {
457
- // The corresponding eigenvalue is real.
458
- for row in 0 ..n {
459
- let re = v[ row + col * n] ;
460
- eigvecs[ row + col * n] . write( Self :: complex( re, 0. ) ) ;
461
- }
462
- col += 1 ;
463
- } else {
464
- // This is a complex conjugate pair.
465
- assert!( col + 1 < n) ;
466
- for row in 0 ..n {
467
- let re = v[ row + col * n] ;
468
- let mut im = v[ row + ( col + 1 ) * n] ;
469
- if jobvl. is_calc( ) {
470
- im = -im;
471
- }
472
- eigvecs[ row + col * n] . write( Self :: complex( re, im) ) ;
473
- eigvecs[ row + ( col + 1 ) * n] . write( Self :: complex( re, -im) ) ;
474
- }
475
- col += 2 ;
476
- }
432
+ if calc_v {
433
+ let mut eigvecs = vec_uninit( ( n * n) as usize ) ;
434
+ reconstruct_eigenvectors(
435
+ jobvl. is_calc( ) ,
436
+ & eig_im,
437
+ & vr. or( vl) . unwrap( ) ,
438
+ & mut eigvecs,
439
+ ) ;
440
+ Ok ( ( eigs, unsafe { eigvecs. assume_init( ) } ) )
441
+ } else {
442
+ Ok ( ( eigs, Vec :: new( ) ) )
477
443
}
478
- let eigvecs = unsafe { eigvecs. assume_init( ) } ;
479
-
480
- Ok ( ( eigs, eigvecs) )
481
444
}
482
445
}
483
446
} ;
484
447
}
485
448
486
449
impl_eig_real ! ( f64 , lapack_sys:: dgeev_) ;
487
450
impl_eig_real ! ( f32 , lapack_sys:: sgeev_) ;
451
+
452
+ /// Reconstruct eigenvectors into complex-array
453
+ ///
454
+ /// From LAPACK API https://software.intel.com/en-us/node/469230
455
+ ///
456
+ /// - If the j-th eigenvalue is real,
457
+ /// - v(j) = VR(:,j), the j-th column of VR.
458
+ ///
459
+ /// - If the j-th and (j+1)-st eigenvalues form a complex conjugate pair,
460
+ /// - v(j) = VR(:,j) + i*VR(:,j+1)
461
+ /// - v(j+1) = VR(:,j) - i*VR(:,j+1).
462
+ ///
463
+ /// In the C-layout case, we need the conjugates of the left
464
+ /// eigenvectors, so the signs should be reversed.
465
+ fn reconstruct_eigenvectors < T : Scalar > (
466
+ take_hermite_conjugate : bool ,
467
+ eig_im : & [ T ] ,
468
+ vr : & [ T ] ,
469
+ vc : & mut [ MaybeUninit < T :: Complex > ] ,
470
+ ) {
471
+ let n = eig_im. len ( ) ;
472
+ assert_eq ! ( vr. len( ) , n * n) ;
473
+ assert_eq ! ( vc. len( ) , n * n) ;
474
+
475
+ let mut col = 0 ;
476
+ while col < n {
477
+ if eig_im[ col] . is_zero ( ) {
478
+ // The corresponding eigenvalue is real.
479
+ for row in 0 ..n {
480
+ let re = vr[ row + col * n] ;
481
+ vc[ row + col * n] . write ( T :: complex ( re, T :: zero ( ) ) ) ;
482
+ }
483
+ col += 1 ;
484
+ } else {
485
+ // This is a complex conjugate pair.
486
+ assert ! ( col + 1 < n) ;
487
+ for row in 0 ..n {
488
+ let re = vr[ row + col * n] ;
489
+ let mut im = vr[ row + ( col + 1 ) * n] ;
490
+ if take_hermite_conjugate {
491
+ im = -im;
492
+ }
493
+ vc[ row + col * n] . write ( T :: complex ( re, im) ) ;
494
+ vc[ row + ( col + 1 ) * n] . write ( T :: complex ( re, -im) ) ;
495
+ }
496
+ col += 2 ;
497
+ }
498
+ }
499
+ }
0 commit comments