@@ -39,81 +39,166 @@ pub trait EighWorkImpl: Sized {
39
39
fn eval ( self , uplo : UPLO , a : & mut [ Self :: Elem ] ) -> Result < Vec < <Self :: Elem as Scalar >:: Real > > ;
40
40
}
41
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
- ) ;
42
+ macro_rules! impl_eigh_work_c {
43
+ ( $c: ty, $ev: path) => {
44
+ impl EighWorkImpl for EighWork <$c> {
45
+ type Elem = $c;
46
+
47
+ fn new( calc_eigenvectors: bool , layout: MatrixLayout ) -> Result <Self > {
48
+ assert_eq!( layout. len( ) , layout. lda( ) ) ;
49
+ let n = layout. len( ) ;
50
+ let jobz = if calc_eigenvectors {
51
+ JobEv :: All
52
+ } else {
53
+ JobEv :: None
54
+ } ;
55
+ let mut eigs = vec_uninit( n as usize ) ;
56
+ let mut rwork = vec_uninit( 3 * n as usize - 2 as usize ) ;
57
+ let mut info = 0 ;
58
+ let mut work_size = [ Self :: Elem :: zero( ) ] ;
59
+ unsafe {
60
+ $ev(
61
+ jobz. as_ptr( ) ,
62
+ UPLO :: Upper . as_ptr( ) , // dummy, working memory is not affected by UPLO
63
+ & n,
64
+ std:: ptr:: null_mut( ) ,
65
+ & n,
66
+ AsPtr :: as_mut_ptr( & mut eigs) ,
67
+ AsPtr :: as_mut_ptr( & mut work_size) ,
68
+ & ( -1 ) ,
69
+ AsPtr :: as_mut_ptr( & mut rwork) ,
70
+ & mut info,
71
+ ) ;
72
+ }
73
+ info. as_lapack_result( ) ?;
74
+ let lwork = work_size[ 0 ] . to_usize( ) . unwrap( ) ;
75
+ let work = vec_uninit( lwork) ;
76
+ Ok ( EighWork {
77
+ n,
78
+ eigs,
79
+ jobz,
80
+ work,
81
+ rwork: Some ( rwork) ,
82
+ } )
83
+ }
84
+
85
+ fn calc(
86
+ & mut self ,
87
+ uplo: UPLO ,
88
+ a: & mut [ Self :: Elem ] ,
89
+ ) -> Result <& [ <Self :: Elem as Scalar >:: Real ] > {
90
+ let lwork = self . work. len( ) . to_i32( ) . unwrap( ) ;
91
+ let mut info = 0 ;
92
+ unsafe {
93
+ $ev(
94
+ self . jobz. as_ptr( ) ,
95
+ uplo. as_ptr( ) ,
96
+ & self . n,
97
+ AsPtr :: as_mut_ptr( a) ,
98
+ & self . n,
99
+ AsPtr :: as_mut_ptr( & mut self . eigs) ,
100
+ AsPtr :: as_mut_ptr( & mut self . work) ,
101
+ & lwork,
102
+ AsPtr :: as_mut_ptr( self . rwork. as_mut( ) . unwrap( ) ) ,
103
+ & mut info,
104
+ ) ;
105
+ }
106
+ info. as_lapack_result( ) ?;
107
+ Ok ( unsafe { self . eigs. slice_assume_init_ref( ) } )
108
+ }
109
+
110
+ fn eval(
111
+ mut self ,
112
+ uplo: UPLO ,
113
+ a: & mut [ Self :: Elem ] ,
114
+ ) -> Result <Vec <<Self :: Elem as Scalar >:: Real >> {
115
+ let _eig = self . calc( uplo, a) ?;
116
+ Ok ( unsafe { self . eigs. assume_init( ) } )
117
+ }
103
118
}
104
- info. as_lapack_result ( ) ?;
105
- Ok ( unsafe { self . eigs . slice_assume_init_ref ( ) } )
106
- }
119
+ } ;
120
+ }
121
+ impl_eigh_work_c ! ( c64, lapack_sys:: zheev_) ;
122
+ impl_eigh_work_c ! ( c32, lapack_sys:: cheev_) ;
107
123
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
- }
124
+ macro_rules! impl_eigh_work_r {
125
+ ( $f: ty, $ev: path) => {
126
+ impl EighWorkImpl for EighWork <$f> {
127
+ type Elem = $f;
128
+
129
+ fn new( calc_eigenvectors: bool , layout: MatrixLayout ) -> Result <Self > {
130
+ assert_eq!( layout. len( ) , layout. lda( ) ) ;
131
+ let n = layout. len( ) ;
132
+ let jobz = if calc_eigenvectors {
133
+ JobEv :: All
134
+ } else {
135
+ JobEv :: None
136
+ } ;
137
+ let mut eigs = vec_uninit( n as usize ) ;
138
+ let mut info = 0 ;
139
+ let mut work_size = [ Self :: Elem :: zero( ) ] ;
140
+ unsafe {
141
+ $ev(
142
+ jobz. as_ptr( ) ,
143
+ UPLO :: Upper . as_ptr( ) , // dummy, working memory is not affected by UPLO
144
+ & n,
145
+ std:: ptr:: null_mut( ) ,
146
+ & n,
147
+ AsPtr :: as_mut_ptr( & mut eigs) ,
148
+ AsPtr :: as_mut_ptr( & mut work_size) ,
149
+ & ( -1 ) ,
150
+ & mut info,
151
+ ) ;
152
+ }
153
+ info. as_lapack_result( ) ?;
154
+ let lwork = work_size[ 0 ] . to_usize( ) . unwrap( ) ;
155
+ let work = vec_uninit( lwork) ;
156
+ Ok ( EighWork {
157
+ n,
158
+ eigs,
159
+ jobz,
160
+ work,
161
+ rwork: None ,
162
+ } )
163
+ }
164
+
165
+ fn calc(
166
+ & mut self ,
167
+ uplo: UPLO ,
168
+ a: & mut [ Self :: Elem ] ,
169
+ ) -> Result <& [ <Self :: Elem as Scalar >:: Real ] > {
170
+ let lwork = self . work. len( ) . to_i32( ) . unwrap( ) ;
171
+ let mut info = 0 ;
172
+ unsafe {
173
+ $ev(
174
+ self . jobz. as_ptr( ) ,
175
+ uplo. as_ptr( ) ,
176
+ & self . n,
177
+ AsPtr :: as_mut_ptr( a) ,
178
+ & self . n,
179
+ AsPtr :: as_mut_ptr( & mut self . eigs) ,
180
+ AsPtr :: as_mut_ptr( & mut self . work) ,
181
+ & lwork,
182
+ & mut info,
183
+ ) ;
184
+ }
185
+ info. as_lapack_result( ) ?;
186
+ Ok ( unsafe { self . eigs. slice_assume_init_ref( ) } )
187
+ }
188
+
189
+ fn eval(
190
+ mut self ,
191
+ uplo: UPLO ,
192
+ a: & mut [ Self :: Elem ] ,
193
+ ) -> Result <Vec <<Self :: Elem as Scalar >:: Real >> {
194
+ let _eig = self . calc( uplo, a) ?;
195
+ Ok ( unsafe { self . eigs. assume_init( ) } )
196
+ }
197
+ }
198
+ } ;
116
199
}
200
+ impl_eigh_work_r ! ( f64 , lapack_sys:: dsyev_) ;
201
+ impl_eigh_work_r ! ( f32 , lapack_sys:: ssyev_) ;
117
202
118
203
macro_rules! impl_eigh {
119
204
( @real, $scalar: ty, $ev: path) => {
0 commit comments