1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use crate::Scalar;
use lapacke::{Layout, ssyevx_work, dsyevx_work, zheevx_work, cheevx_work};
use num_complex::Complex32 as c32;
use num_complex::Complex64 as c64;

pub trait Theevx: Scalar
{
    /// Symmetric/Hermitian eigenvalue problem - Expert drivers with work arrays
    /// Binds to syevx for real scalars and to heevx for complex scalars
    /// rwork is not used for syevx and may refer to an empty array
    unsafe fn heevx(layout: Layout,
                    jobz: u8,
                    range: u8,
                    uplo: u8,
                    n: i32,
                    a: &mut [Self],
                    lda: i32,
                    vl: Self::Real,
                    vu: Self::Real,
                    il: i32,
                    iu: i32,
                    abstol: Self::Real,
                    m: &mut i32,
                    w: &mut [Self::Real],
                    z: &mut [Self],
                    ldz: i32,
                    work: &mut [Self],
                    lwork: i32,
                    rwork: &mut [Self::Real],
                    iwork: &mut [i32],
                    ifail: &mut [i32]) -> i32;

    fn rwork_const() -> isize;
}

macro_rules! impl_he_evx (
    ($N: ty, $heevx: path) => (
        impl Theevx for $N {
            #[inline]
            unsafe fn heevx(layout: Layout, jobz: u8, range: u8, uplo: u8, n: i32, a: &mut [Self], lda: i32,
                 vl: Self::Real, vu: Self::Real, il: i32, iu: i32,  abstol: Self::Real,
                 m: &mut i32, w: &mut [Self::Real], z: &mut [Self], ldz: i32,
                 work: &mut [Self], lwork: i32, rwork: &mut [Self::Real],  //Not used for real-symmetric routines
                 iwork: &mut [i32], ifail: &mut [i32]) -> i32 {
                    let info: i32 =
                                $heevx( layout,
                                        jobz, range, uplo, n, a, lda,
                                        vl, vu, il, iu, abstol,
                                        m, w, z, ldz,
                                        work, lwork, rwork, iwork, ifail)
                        ;
                    info
            }

            fn rwork_const() -> isize {
                7
            }
        }
    )
);

macro_rules! impl_sy_evx (
    ($N: ty, $syevx: path) => (
        impl Theevx for $N {
            #[inline]
            unsafe fn heevx(layout: Layout, jobz: u8, range: u8, uplo: u8, n: i32, a: &mut [Self], lda: i32,
                 vl: Self::Real, vu: Self::Real, il: i32, iu: i32,  abstol: Self::Real,
                 m: &mut i32, w: &mut [Self::Real], z: &mut [Self], ldz: i32,
                 work: &mut [Self], lwork: i32, _rwork: &mut [Self::Real],  //Not used for real-symmetric routines
                 iwork: &mut [i32], ifail: &mut [i32]) -> i32 {
                    let info: i32 =
                                $syevx( layout,
                                        jobz, range, uplo, n, a, lda,
                                        vl, vu, il, iu, abstol,
                                        m, w, z, ldz,
                                        work, lwork, iwork, ifail)
                        ;
                    info
            }
            fn rwork_const() -> isize {
                -1
            }
        }
    )
);

impl_sy_evx!(f32, ssyevx_work);
impl_sy_evx!(f64, dsyevx_work);
impl_he_evx!(c32, cheevx_work);
impl_he_evx!(c64, zheevx_work);