@@ -223,59 +223,67 @@ macro_rules! impl_eig_real {
223223 . map( |( & re, & im) | Self :: complex( re, im) )
224224 . collect( ) ;
225225
226- if !calc_v {
227- return Ok ( ( eigs, Vec :: new( ) ) ) ;
228- }
229-
230- // Reconstruct eigenvectors into complex-array
231- // --------------------------------------------
232- //
233- // From LAPACK API https://software.intel.com/en-us/node/469230
234- //
235- // - If the j-th eigenvalue is real,
236- // - v(j) = VR(:,j), the j-th column of VR.
237- //
238- // - If the j-th and (j+1)-st eigenvalues form a complex conjugate pair,
239- // - v(j) = VR(:,j) + i*VR(:,j+1)
240- // - v(j+1) = VR(:,j) - i*VR(:,j+1).
241- //
242- // In the C-layout case, we need the conjugates of the left
243- // eigenvectors, so the signs should be reversed.
244-
245- let n = n as usize ;
246- let v = vr. or( vl) . unwrap( ) ;
247- let mut eigvecs: Vec <MaybeUninit <Self :: Complex >> = vec_uninit( n * n) ;
248- let mut col = 0 ;
249- while col < n {
250- if eig_im[ col] == 0. {
251- // The corresponding eigenvalue is real.
252- for row in 0 ..n {
253- let re = v[ row + col * n] ;
254- eigvecs[ row + col * n] . write( Self :: complex( re, 0. ) ) ;
255- }
256- col += 1 ;
257- } else {
258- // This is a complex conjugate pair.
259- assert!( col + 1 < n) ;
260- for row in 0 ..n {
261- let re = v[ row + col * n] ;
262- let mut im = v[ row + ( col + 1 ) * n] ;
263- if jobvl. is_calc( ) {
264- im = -im;
265- }
266- eigvecs[ row + col * n] . write( Self :: complex( re, im) ) ;
267- eigvecs[ row + ( col + 1 ) * n] . write( Self :: complex( re, -im) ) ;
268- }
269- col += 2 ;
270- }
226+ if calc_v {
227+ let eigvecs = reconstruct_eigenvectors( jobvl, n, & eig_im, vr, vl) ;
228+ Ok ( ( eigs, eigvecs) )
229+ } else {
230+ Ok ( ( eigs, Vec :: new( ) ) )
271231 }
272- let eigvecs = unsafe { eigvecs. assume_init( ) } ;
273-
274- Ok ( ( eigs, eigvecs) )
275232 }
276233 }
277234 } ;
278235}
279236
280237impl_eig_real ! ( f64 , lapack_sys:: dgeev_) ;
281238impl_eig_real ! ( f32 , lapack_sys:: sgeev_) ;
239+
240+ /// Reconstruct eigenvectors into complex-array
241+ /// --------------------------------------------
242+ ///
243+ /// From LAPACK API https://software.intel.com/en-us/node/469230
244+ ///
245+ /// - If the j-th eigenvalue is real,
246+ /// - v(j) = VR(:,j), the j-th column of VR.
247+ ///
248+ /// - If the j-th and (j+1)-st eigenvalues form a complex conjugate pair,
249+ /// - v(j) = VR(:,j) + i*VR(:,j+1)
250+ /// - v(j+1) = VR(:,j) - i*VR(:,j+1).
251+ ///
252+ /// In the C-layout case, we need the conjugates of the left
253+ /// eigenvectors, so the signs should be reversed.
254+ fn reconstruct_eigenvectors < T : Scalar > (
255+ jobvl : JobEv ,
256+ n : i32 ,
257+ eig_im : & [ T ] ,
258+ vr : Option < Vec < T > > ,
259+ vl : Option < Vec < T > > ,
260+ ) -> Vec < T :: Complex > {
261+ let n = n as usize ;
262+ let v = vr. or ( vl) . unwrap ( ) ;
263+ let mut eigvecs: Vec < MaybeUninit < T :: Complex > > = vec_uninit ( n * n) ;
264+ let mut col = 0 ;
265+ while col < n {
266+ if eig_im[ col] . is_zero ( ) {
267+ // The corresponding eigenvalue is real.
268+ for row in 0 ..n {
269+ let re = v[ row + col * n] ;
270+ eigvecs[ row + col * n] . write ( T :: complex ( re, T :: zero ( ) ) ) ;
271+ }
272+ col += 1 ;
273+ } else {
274+ // This is a complex conjugate pair.
275+ assert ! ( col + 1 < n) ;
276+ for row in 0 ..n {
277+ let re = v[ row + col * n] ;
278+ let mut im = v[ row + ( col + 1 ) * n] ;
279+ if jobvl. is_calc ( ) {
280+ im = -im;
281+ }
282+ eigvecs[ row + col * n] . write ( T :: complex ( re, im) ) ;
283+ eigvecs[ row + ( col + 1 ) * n] . write ( T :: complex ( re, -im) ) ;
284+ }
285+ col += 2 ;
286+ }
287+ }
288+ unsafe { eigvecs. assume_init ( ) }
289+ }
0 commit comments