@@ -223,59 +223,67 @@ macro_rules! impl_eig_real {
223
223
. map( |( & re, & im) | Self :: complex( re, im) )
224
224
. collect( ) ;
225
225
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( ) ) )
271
231
}
272
- let eigvecs = unsafe { eigvecs. assume_init( ) } ;
273
-
274
- Ok ( ( eigs, eigvecs) )
275
232
}
276
233
}
277
234
} ;
278
235
}
279
236
280
237
impl_eig_real ! ( f64 , lapack_sys:: dgeev_) ;
281
238
impl_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