1
- //! Eigenvalue decomposition for Hermite matrices
1
+ //! Eigenvalue decomposition for Symmetric/ Hermite matrices
2
2
3
3
use super :: * ;
4
4
use crate :: { error:: * , layout:: MatrixLayout } ;
5
5
use cauchy:: * ;
6
6
use num_traits:: Zero ;
7
7
8
- /// Wraps `*syev` for real and `*heev` for complex
9
8
pub trait Eigh_ : Scalar {
10
- unsafe fn eigh (
9
+ /// Wraps `*syev` for real and `*heev` for complex
10
+ fn eigh (
11
11
calc_eigenvec : bool ,
12
- l : MatrixLayout ,
12
+ layout : MatrixLayout ,
13
13
uplo : UPLO ,
14
14
a : & mut [ Self ] ,
15
15
) -> Result < Vec < Self :: Real > > ;
16
- unsafe fn eigh_generalized (
16
+
17
+ /// Wraps `*syegv` for real and `*heegv` for complex
18
+ fn eigh_generalized (
17
19
calc_eigenvec : bool ,
18
- l : MatrixLayout ,
20
+ layout : MatrixLayout ,
19
21
uplo : UPLO ,
20
22
a : & mut [ Self ] ,
21
23
b : & mut [ Self ] ,
@@ -25,50 +27,152 @@ pub trait Eigh_: Scalar {
25
27
macro_rules! impl_eigh {
26
28
( $scalar: ty, $ev: path, $evg: path) => {
27
29
impl Eigh_ for $scalar {
28
- unsafe fn eigh(
30
+ fn eigh(
31
+ calc_v: bool ,
32
+ layout: MatrixLayout ,
33
+ uplo: UPLO ,
34
+ mut a: & mut [ Self ] ,
35
+ ) -> Result <Vec <Self :: Real >> {
36
+ assert_eq!( layout. len( ) , layout. lda( ) ) ;
37
+ let n = layout. len( ) ;
38
+ let jobz = if calc_v { b'V' } else { b'N' } ;
39
+ let mut eigs = vec![ Self :: Real :: zero( ) ; n as usize ] ;
40
+ let mut work = vec![ Self :: zero( ) ; 3 * n as usize ] ;
41
+ let n = n as i32 ;
42
+ let mut info = 0 ;
43
+ unsafe {
44
+ $ev(
45
+ jobz,
46
+ uplo as u8 ,
47
+ n,
48
+ & mut a,
49
+ n,
50
+ & mut eigs,
51
+ & mut work,
52
+ 3 * n - 1 ,
53
+ & mut info,
54
+ ) ;
55
+ }
56
+ info. as_lapack_result( ) ?;
57
+ Ok ( eigs)
58
+ }
59
+
60
+ fn eigh_generalized(
61
+ calc_v: bool ,
62
+ layout: MatrixLayout ,
63
+ uplo: UPLO ,
64
+ mut a: & mut [ Self ] ,
65
+ mut b: & mut [ Self ] ,
66
+ ) -> Result <Vec <Self :: Real >> {
67
+ assert_eq!( layout. len( ) , layout. lda( ) ) ;
68
+ let n = layout. len( ) ;
69
+ let jobz = if calc_v { b'V' } else { b'N' } ;
70
+ let mut eigs = vec![ Self :: Real :: zero( ) ; n as usize ] ;
71
+ let mut work = vec![ Self :: zero( ) ; 3 * n as usize - 1 ] ;
72
+ let n = n as i32 ;
73
+ let mut info = 0 ;
74
+ unsafe {
75
+ $evg(
76
+ & [ 1 ] ,
77
+ jobz,
78
+ uplo as u8 ,
79
+ n,
80
+ & mut a,
81
+ n,
82
+ & mut b,
83
+ n,
84
+ & mut eigs,
85
+ & mut work,
86
+ 3 * n - 1 ,
87
+ & mut info,
88
+ ) ;
89
+ }
90
+ info. as_lapack_result( ) ?;
91
+ Ok ( eigs)
92
+ }
93
+ }
94
+ } ;
95
+ } // impl_eigh!
96
+
97
+ impl_eigh ! ( f64 , lapack:: dsyev, lapack:: dsygv) ;
98
+ impl_eigh ! ( f32 , lapack:: ssyev, lapack:: ssygv) ;
99
+
100
+ // splitted for RWORK
101
+ macro_rules! impl_eighc {
102
+ ( $scalar: ty, $ev: path, $evg: path) => {
103
+ impl Eigh_ for $scalar {
104
+ fn eigh(
29
105
calc_v: bool ,
30
- l : MatrixLayout ,
106
+ layout : MatrixLayout ,
31
107
uplo: UPLO ,
32
108
mut a: & mut [ Self ] ,
33
109
) -> Result <Vec <Self :: Real >> {
34
- let ( n, _) = l. size( ) ;
110
+ assert_eq!( layout. len( ) , layout. lda( ) ) ;
111
+ let n = layout. len( ) ;
35
112
let jobz = if calc_v { b'V' } else { b'N' } ;
36
- let mut w = vec![ Self :: Real :: zero( ) ; n as usize ] ;
37
- $ev( l. lapacke_layout( ) , jobz, uplo as u8 , n, & mut a, n, & mut w)
38
- . as_lapack_result( ) ?;
39
- Ok ( w)
113
+ let mut eigs = vec![ Self :: Real :: zero( ) ; n as usize ] ;
114
+ let mut work = vec![ Self :: zero( ) ; 2 * n as usize - 1 ] ;
115
+ let mut rwork = vec![ Self :: Real :: zero( ) ; 3 * n as usize - 2 ] ;
116
+ let mut info = 0 ;
117
+ let n = n as i32 ;
118
+
119
+ unsafe {
120
+ $ev(
121
+ jobz,
122
+ uplo as u8 ,
123
+ n,
124
+ & mut a,
125
+ n,
126
+ & mut eigs,
127
+ & mut work,
128
+ 2 * n - 1 ,
129
+ & mut rwork,
130
+ & mut info,
131
+ )
132
+ } ;
133
+ info. as_lapack_result( ) ?;
134
+ Ok ( eigs)
40
135
}
41
136
42
- unsafe fn eigh_generalized(
137
+ fn eigh_generalized(
43
138
calc_v: bool ,
44
- l : MatrixLayout ,
139
+ layout : MatrixLayout ,
45
140
uplo: UPLO ,
46
141
mut a: & mut [ Self ] ,
47
142
mut b: & mut [ Self ] ,
48
143
) -> Result <Vec <Self :: Real >> {
49
- let ( n, _) = l. size( ) ;
144
+ assert_eq!( layout. len( ) , layout. lda( ) ) ;
145
+ let n = layout. len( ) ;
50
146
let jobz = if calc_v { b'V' } else { b'N' } ;
51
- let mut w = vec![ Self :: Real :: zero( ) ; n as usize ] ;
52
- $evg(
53
- l. lapacke_layout( ) ,
54
- 1 ,
55
- jobz,
56
- uplo as u8 ,
57
- n,
58
- & mut a,
59
- n,
60
- & mut b,
61
- n,
62
- & mut w,
63
- )
64
- . as_lapack_result( ) ?;
65
- Ok ( w)
147
+ let mut eigs = vec![ Self :: Real :: zero( ) ; n as usize ] ;
148
+ let mut work = vec![ Self :: zero( ) ; 2 * n as usize - 1 ] ;
149
+ let mut rwork = vec![ Self :: Real :: zero( ) ; 3 * n as usize - 2 ] ;
150
+ let n = n as i32 ;
151
+ let mut info = 0 ;
152
+
153
+ unsafe {
154
+ $evg(
155
+ & [ 1 ] ,
156
+ jobz,
157
+ uplo as u8 ,
158
+ n,
159
+ & mut a,
160
+ n,
161
+ & mut b,
162
+ n,
163
+ & mut eigs,
164
+ & mut work,
165
+ 2 * n - 1 ,
166
+ & mut rwork,
167
+ & mut info,
168
+ )
169
+ } ;
170
+ info. as_lapack_result( ) ?;
171
+ Ok ( eigs)
66
172
}
67
173
}
68
174
} ;
69
175
} // impl_eigh!
70
176
71
- impl_eigh ! ( f64 , lapacke:: dsyev, lapacke:: dsygv) ;
72
- impl_eigh ! ( f32 , lapacke:: ssyev, lapacke:: ssygv) ;
73
- impl_eigh ! ( c64, lapacke:: zheev, lapacke:: zhegv) ;
74
- impl_eigh ! ( c32, lapacke:: cheev, lapacke:: chegv) ;
177
+ impl_eighc ! ( c64, lapack:: zheev, lapack:: zhegv) ;
178
+ impl_eighc ! ( c32, lapack:: cheev, lapack:: chegv) ;
0 commit comments