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_);