@@ -23,6 +23,98 @@ pub trait Eigh_: Scalar {
23
23
) -> Result < Vec < Self :: Real > > ;
24
24
}
25
25
26
+ pub struct EighWork < T : Scalar > {
27
+ pub n : i32 ,
28
+ pub jobz : JobEv ,
29
+ pub eigs : Vec < MaybeUninit < T :: Real > > ,
30
+ pub work : Vec < MaybeUninit < T > > ,
31
+ pub rwork : Option < Vec < MaybeUninit < T :: Real > > > ,
32
+ }
33
+
34
+ pub trait EighWorkImpl : Sized {
35
+ type Elem : Scalar ;
36
+ fn new ( calc_eigenvectors : bool , layout : MatrixLayout ) -> Result < Self > ;
37
+ fn calc ( & mut self , uplo : UPLO , a : & mut [ Self :: Elem ] )
38
+ -> Result < & [ <Self :: Elem as Scalar >:: Real ] > ;
39
+ fn eval ( self , uplo : UPLO , a : & mut [ Self :: Elem ] ) -> Result < Vec < <Self :: Elem as Scalar >:: Real > > ;
40
+ }
41
+
42
+ impl EighWorkImpl for EighWork < c64 > {
43
+ type Elem = c64 ;
44
+
45
+ fn new ( calc_eigenvectors : bool , layout : MatrixLayout ) -> Result < Self > {
46
+ assert_eq ! ( layout. len( ) , layout. lda( ) ) ;
47
+ let n = layout. len ( ) ;
48
+ let jobz = if calc_eigenvectors {
49
+ JobEv :: All
50
+ } else {
51
+ JobEv :: None
52
+ } ;
53
+ let mut eigs = vec_uninit ( n as usize ) ;
54
+ let mut rwork = vec_uninit ( 3 * n as usize - 2 as usize ) ;
55
+ let mut info = 0 ;
56
+ let mut work_size = [ c64:: zero ( ) ] ;
57
+ unsafe {
58
+ lapack_sys:: zheev_ (
59
+ jobz. as_ptr ( ) ,
60
+ UPLO :: Upper . as_ptr ( ) , // dummy, working memory is not affected by UPLO
61
+ & n,
62
+ std:: ptr:: null_mut ( ) ,
63
+ & n,
64
+ AsPtr :: as_mut_ptr ( & mut eigs) ,
65
+ AsPtr :: as_mut_ptr ( & mut work_size) ,
66
+ & ( -1 ) ,
67
+ AsPtr :: as_mut_ptr ( & mut rwork) ,
68
+ & mut info,
69
+ ) ;
70
+ }
71
+ info. as_lapack_result ( ) ?;
72
+ let lwork = work_size[ 0 ] . to_usize ( ) . unwrap ( ) ;
73
+ let work = vec_uninit ( lwork) ;
74
+ Ok ( EighWork {
75
+ n,
76
+ eigs,
77
+ jobz,
78
+ work,
79
+ rwork : Some ( rwork) ,
80
+ } )
81
+ }
82
+
83
+ fn calc (
84
+ & mut self ,
85
+ uplo : UPLO ,
86
+ a : & mut [ Self :: Elem ] ,
87
+ ) -> Result < & [ <Self :: Elem as Scalar >:: Real ] > {
88
+ let lwork = self . work . len ( ) . to_i32 ( ) . unwrap ( ) ;
89
+ let mut info = 0 ;
90
+ unsafe {
91
+ lapack_sys:: zheev_ (
92
+ self . jobz . as_ptr ( ) ,
93
+ uplo. as_ptr ( ) ,
94
+ & self . n ,
95
+ AsPtr :: as_mut_ptr ( a) ,
96
+ & self . n ,
97
+ AsPtr :: as_mut_ptr ( & mut self . eigs ) ,
98
+ AsPtr :: as_mut_ptr ( & mut self . work ) ,
99
+ & lwork,
100
+ AsPtr :: as_mut_ptr ( self . rwork . as_mut ( ) . unwrap ( ) ) ,
101
+ & mut info,
102
+ ) ;
103
+ }
104
+ info. as_lapack_result ( ) ?;
105
+ Ok ( unsafe { self . eigs . slice_assume_init_ref ( ) } )
106
+ }
107
+
108
+ fn eval (
109
+ mut self ,
110
+ uplo : UPLO ,
111
+ a : & mut [ Self :: Elem ] ,
112
+ ) -> Result < Vec < <Self :: Elem as Scalar >:: Real > > {
113
+ let _eig = self . calc ( uplo, a) ?;
114
+ Ok ( unsafe { self . eigs . assume_init ( ) } )
115
+ }
116
+ }
117
+
26
118
macro_rules! impl_eigh {
27
119
( @real, $scalar: ty, $ev: path) => {
28
120
impl_eigh!( @body, $scalar, $ev, ) ;
0 commit comments