@@ -18,6 +18,116 @@ pub trait QR_: Sized {
1818 fn qr ( l : MatrixLayout , a : & mut [ Self ] ) -> Result < Vec < Self > > ;
1919}
2020
21+ pub struct HouseholderWork < T : Scalar > {
22+ pub m : i32 ,
23+ pub n : i32 ,
24+ pub layout : MatrixLayout ,
25+ pub tau : Vec < MaybeUninit < T > > ,
26+ pub work : Vec < MaybeUninit < T > > ,
27+ }
28+
29+ pub trait HouseholderWorkImpl : Sized {
30+ type Elem : Scalar ;
31+ fn new ( l : MatrixLayout ) -> Result < Self > ;
32+ fn calc ( & mut self , a : & mut [ Self :: Elem ] ) -> Result < & [ Self :: Elem ] > ;
33+ fn eval ( self , a : & mut [ Self :: Elem ] ) -> Result < Vec < Self :: Elem > > ;
34+ }
35+
36+ macro_rules! impl_householder_work {
37+ ( $s: ty, $qrf: path, $lqf: path) => {
38+ impl HouseholderWorkImpl for HouseholderWork <$s> {
39+ type Elem = $s;
40+
41+ fn new( layout: MatrixLayout ) -> Result <Self > {
42+ let m = layout. lda( ) ;
43+ let n = layout. len( ) ;
44+ let k = m. min( n) ;
45+ let mut tau = vec_uninit( k as usize ) ;
46+ let mut info = 0 ;
47+ let mut work_size = [ Self :: Elem :: zero( ) ] ;
48+ match layout {
49+ MatrixLayout :: F { .. } => unsafe {
50+ $qrf(
51+ & m,
52+ & n,
53+ std:: ptr:: null_mut( ) ,
54+ & m,
55+ AsPtr :: as_mut_ptr( & mut tau) ,
56+ AsPtr :: as_mut_ptr( & mut work_size) ,
57+ & ( -1 ) ,
58+ & mut info,
59+ )
60+ } ,
61+ MatrixLayout :: C { .. } => unsafe {
62+ $lqf(
63+ & m,
64+ & n,
65+ std:: ptr:: null_mut( ) ,
66+ & m,
67+ AsPtr :: as_mut_ptr( & mut tau) ,
68+ AsPtr :: as_mut_ptr( & mut work_size) ,
69+ & ( -1 ) ,
70+ & mut info,
71+ )
72+ } ,
73+ }
74+ info. as_lapack_result( ) ?;
75+ let lwork = work_size[ 0 ] . to_usize( ) . unwrap( ) ;
76+ let work = vec_uninit( lwork) ;
77+ Ok ( HouseholderWork {
78+ n,
79+ m,
80+ layout,
81+ tau,
82+ work,
83+ } )
84+ }
85+
86+ fn calc( & mut self , a: & mut [ Self :: Elem ] ) -> Result <& [ Self :: Elem ] > {
87+ let lwork = self . work. len( ) . to_i32( ) . unwrap( ) ;
88+ let mut info = 0 ;
89+ match self . layout {
90+ MatrixLayout :: F { .. } => unsafe {
91+ $qrf(
92+ & self . m,
93+ & self . n,
94+ AsPtr :: as_mut_ptr( a) ,
95+ & self . m,
96+ AsPtr :: as_mut_ptr( & mut self . tau) ,
97+ AsPtr :: as_mut_ptr( & mut self . work) ,
98+ & lwork,
99+ & mut info,
100+ ) ;
101+ } ,
102+ MatrixLayout :: C { .. } => unsafe {
103+ $lqf(
104+ & self . m,
105+ & self . n,
106+ AsPtr :: as_mut_ptr( a) ,
107+ & self . m,
108+ AsPtr :: as_mut_ptr( & mut self . tau) ,
109+ AsPtr :: as_mut_ptr( & mut self . work) ,
110+ & lwork,
111+ & mut info,
112+ ) ;
113+ } ,
114+ }
115+ info. as_lapack_result( ) ?;
116+ Ok ( unsafe { self . tau. slice_assume_init_ref( ) } )
117+ }
118+
119+ fn eval( mut self , a: & mut [ Self :: Elem ] ) -> Result <Vec <Self :: Elem >> {
120+ let _eig = self . calc( a) ?;
121+ Ok ( unsafe { self . tau. assume_init( ) } )
122+ }
123+ }
124+ } ;
125+ }
126+ impl_householder_work ! ( c64, lapack_sys:: zgeqrf_, lapack_sys:: zgelqf_) ;
127+ impl_householder_work ! ( c32, lapack_sys:: cgeqrf_, lapack_sys:: cgelqf_) ;
128+ impl_householder_work ! ( f64 , lapack_sys:: dgeqrf_, lapack_sys:: dgelqf_) ;
129+ impl_householder_work ! ( f32 , lapack_sys:: sgeqrf_, lapack_sys:: sgelqf_) ;
130+
21131macro_rules! impl_qr {
22132 ( $scalar: ty, $qrf: path, $lqf: path, $gqr: path, $glq: path) => {
23133 impl QR_ for $scalar {
0 commit comments