lax/tridiagonal/
rcond.rs

1use crate::*;
2use cauchy::*;
3use num_traits::Zero;
4
5pub struct RcondTridiagonalWork<T: Scalar> {
6    pub work: Vec<MaybeUninit<T>>,
7    pub iwork: Option<Vec<MaybeUninit<i32>>>,
8}
9
10pub trait RcondTridiagonalWorkImpl {
11    type Elem: Scalar;
12    fn new(layout: MatrixLayout) -> Self;
13    fn calc(
14        &mut self,
15        lu: &LUFactorizedTridiagonal<Self::Elem>,
16    ) -> Result<<Self::Elem as Scalar>::Real>;
17}
18
19macro_rules! impl_rcond_tridiagonal_work_c {
20    ($c:ty, $gtcon:path) => {
21        impl RcondTridiagonalWorkImpl for RcondTridiagonalWork<$c> {
22            type Elem = $c;
23
24            fn new(layout: MatrixLayout) -> Self {
25                let (n, _) = layout.size();
26                let work = vec_uninit(2 * n as usize);
27                RcondTridiagonalWork { work, iwork: None }
28            }
29
30            fn calc(
31                &mut self,
32                lu: &LUFactorizedTridiagonal<Self::Elem>,
33            ) -> Result<<Self::Elem as Scalar>::Real> {
34                let (n, _) = lu.a.l.size();
35                let ipiv = &lu.ipiv;
36                let mut rcond = <Self::Elem as Scalar>::Real::zero();
37                let mut info = 0;
38                unsafe {
39                    $gtcon(
40                        NormType::One.as_ptr(),
41                        &n,
42                        AsPtr::as_ptr(&lu.a.dl),
43                        AsPtr::as_ptr(&lu.a.d),
44                        AsPtr::as_ptr(&lu.a.du),
45                        AsPtr::as_ptr(&lu.du2),
46                        ipiv.as_ptr(),
47                        &lu.a_opnorm_one,
48                        &mut rcond,
49                        AsPtr::as_mut_ptr(&mut self.work),
50                        &mut info,
51                    );
52                }
53                info.as_lapack_result()?;
54                Ok(rcond)
55            }
56        }
57    };
58}
59
60impl_rcond_tridiagonal_work_c!(c64, lapack_sys::zgtcon_);
61impl_rcond_tridiagonal_work_c!(c32, lapack_sys::cgtcon_);
62
63macro_rules! impl_rcond_tridiagonal_work_r {
64    ($c:ty, $gtcon:path) => {
65        impl RcondTridiagonalWorkImpl for RcondTridiagonalWork<$c> {
66            type Elem = $c;
67
68            fn new(layout: MatrixLayout) -> Self {
69                let (n, _) = layout.size();
70                let work = vec_uninit(2 * n as usize);
71                let iwork = vec_uninit(n as usize);
72                RcondTridiagonalWork {
73                    work,
74                    iwork: Some(iwork),
75                }
76            }
77
78            fn calc(
79                &mut self,
80                lu: &LUFactorizedTridiagonal<Self::Elem>,
81            ) -> Result<<Self::Elem as Scalar>::Real> {
82                let (n, _) = lu.a.l.size();
83                let mut rcond = <Self::Elem as Scalar>::Real::zero();
84                let mut info = 0;
85                unsafe {
86                    $gtcon(
87                        NormType::One.as_ptr(),
88                        &n,
89                        AsPtr::as_ptr(&lu.a.dl),
90                        AsPtr::as_ptr(&lu.a.d),
91                        AsPtr::as_ptr(&lu.a.du),
92                        AsPtr::as_ptr(&lu.du2),
93                        AsPtr::as_ptr(&lu.ipiv),
94                        &lu.a_opnorm_one,
95                        &mut rcond,
96                        AsPtr::as_mut_ptr(&mut self.work),
97                        AsPtr::as_mut_ptr(self.iwork.as_mut().unwrap()),
98                        &mut info,
99                    );
100                }
101                info.as_lapack_result()?;
102                Ok(rcond)
103            }
104        }
105    };
106}
107
108impl_rcond_tridiagonal_work_r!(f64, lapack_sys::dgtcon_);
109impl_rcond_tridiagonal_work_r!(f32, lapack_sys::sgtcon_);