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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! Charactor flags, e.g. `'T'`, used in LAPACK API

/// Upper/Lower specification for seveal usages
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum UPLO {
    Upper = b'U',
    Lower = b'L',
}

impl UPLO {
    pub fn t(self) -> Self {
        match self {
            UPLO::Upper => UPLO::Lower,
            UPLO::Lower => UPLO::Upper,
        }
    }

    /// To use Fortran LAPACK API in lapack-sys crate
    pub fn as_ptr(&self) -> *const i8 {
        self as *const UPLO as *const i8
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum Transpose {
    No = b'N',
    Transpose = b'T',
    Hermite = b'C',
}

impl Transpose {
    /// To use Fortran LAPACK API in lapack-sys crate
    pub fn as_ptr(&self) -> *const i8 {
        self as *const Transpose as *const i8
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum NormType {
    One = b'O',
    Infinity = b'I',
    Frobenius = b'F',
}

impl NormType {
    pub fn transpose(self) -> Self {
        match self {
            NormType::One => NormType::Infinity,
            NormType::Infinity => NormType::One,
            NormType::Frobenius => NormType::Frobenius,
        }
    }

    /// To use Fortran LAPACK API in lapack-sys crate
    pub fn as_ptr(&self) -> *const i8 {
        self as *const NormType as *const i8
    }
}

/// Flag for calculating eigenvectors or not
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum JobEv {
    /// Calculate eigenvectors in addition to eigenvalues
    All = b'V',
    /// Do not calculate eigenvectors. Only calculate eigenvalues.
    None = b'N',
}

impl JobEv {
    pub fn is_calc(&self) -> bool {
        match self {
            JobEv::All => true,
            JobEv::None => false,
        }
    }

    pub fn then<T, F: FnOnce() -> T>(&self, f: F) -> Option<T> {
        if self.is_calc() {
            Some(f())
        } else {
            None
        }
    }

    /// To use Fortran LAPACK API in lapack-sys crate
    pub fn as_ptr(&self) -> *const i8 {
        self as *const JobEv as *const i8
    }
}

/// Specifies how many singular vectors are computed
///
/// For an input matrix $A$ of shape $m \times n$,
/// the following are computed on the singular value decomposition $A = U\Sigma V^T$:
#[cfg_attr(doc, katexit::katexit)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum JobSvd {
    /// All $m$ columns of $U$, and/or all $n$ rows of $V^T$.
    All = b'A',
    /// The first $\min(m, n)$ columns of $U$ and/or the first $\min(m, n)$ rows of $V^T$.
    Some = b'S',
    /// No columns of $U$ and/or rows of $V^T$.
    None = b'N',
}

impl JobSvd {
    pub fn from_bool(calc_uv: bool) -> Self {
        if calc_uv {
            JobSvd::All
        } else {
            JobSvd::None
        }
    }

    pub fn as_ptr(&self) -> *const i8 {
        self as *const JobSvd as *const i8
    }
}

/// Specify whether input triangular matrix is unit or not
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum Diag {
    /// Unit triangular matrix, i.e. all diagonal elements of the matrix are `1`
    Unit = b'U',
    /// Non-unit triangular matrix. Its diagonal elements may be different from `1`
    NonUnit = b'N',
}

impl Diag {
    pub fn as_ptr(&self) -> *const i8 {
        self as *const Diag as *const i8
    }
}