@@ -128,6 +128,107 @@ impl_householder_work!(c32, lapack_sys::cgeqrf_, lapack_sys::cgelqf_);
128128impl_householder_work ! ( f64 , lapack_sys:: dgeqrf_, lapack_sys:: dgelqf_) ;
129129impl_householder_work ! ( f32 , lapack_sys:: sgeqrf_, lapack_sys:: sgelqf_) ;
130130
131+ pub struct QWork < T : Scalar > {
132+ pub layout : MatrixLayout ,
133+ pub work : Vec < MaybeUninit < T > > ,
134+ }
135+
136+ pub trait QWorkImpl : Sized {
137+ type Elem : Scalar ;
138+ fn new ( layout : MatrixLayout ) -> Result < Self > ;
139+ fn calc ( & mut self , a : & mut [ Self :: Elem ] , tau : & mut [ Self :: Elem ] ) -> Result < ( ) > ;
140+ }
141+
142+ macro_rules! impl_q_work {
143+ ( $s: ty, $gqr: path, $glq: path) => {
144+ impl QWorkImpl for QWork <$s> {
145+ type Elem = $s;
146+
147+ fn new( layout: MatrixLayout ) -> Result <Self > {
148+ let m = layout. lda( ) ;
149+ let n = layout. len( ) ;
150+ let k = m. min( n) ;
151+ let mut info = 0 ;
152+ let mut work_size = [ Self :: Elem :: zero( ) ] ;
153+ match layout {
154+ MatrixLayout :: F { .. } => unsafe {
155+ $gqr(
156+ & m,
157+ & k,
158+ & k,
159+ std:: ptr:: null_mut( ) ,
160+ & m,
161+ std:: ptr:: null_mut( ) ,
162+ AsPtr :: as_mut_ptr( & mut work_size) ,
163+ & ( -1 ) ,
164+ & mut info,
165+ )
166+ } ,
167+ MatrixLayout :: C { .. } => unsafe {
168+ $glq(
169+ & k,
170+ & n,
171+ & k,
172+ std:: ptr:: null_mut( ) ,
173+ & m,
174+ std:: ptr:: null_mut( ) ,
175+ AsPtr :: as_mut_ptr( & mut work_size) ,
176+ & ( -1 ) ,
177+ & mut info,
178+ )
179+ } ,
180+ }
181+ let lwork = work_size[ 0 ] . to_usize( ) . unwrap( ) ;
182+ let work = vec_uninit( lwork) ;
183+ Ok ( QWork { layout, work } )
184+ }
185+
186+ fn calc( & mut self , a: & mut [ Self :: Elem ] , tau: & mut [ Self :: Elem ] ) -> Result <( ) > {
187+ let m = self . layout. lda( ) ;
188+ let n = self . layout. len( ) ;
189+ let k = m. min( n) ;
190+ let lwork = self . work. len( ) . to_i32( ) . unwrap( ) ;
191+ let mut info = 0 ;
192+ match self . layout {
193+ MatrixLayout :: F { .. } => unsafe {
194+ $gqr(
195+ & m,
196+ & k,
197+ & k,
198+ AsPtr :: as_mut_ptr( a) ,
199+ & m,
200+ AsPtr :: as_ptr( & tau) ,
201+ AsPtr :: as_mut_ptr( & mut self . work) ,
202+ & lwork,
203+ & mut info,
204+ )
205+ } ,
206+ MatrixLayout :: C { .. } => unsafe {
207+ $glq(
208+ & k,
209+ & n,
210+ & k,
211+ AsPtr :: as_mut_ptr( a) ,
212+ & m,
213+ AsPtr :: as_ptr( & tau) ,
214+ AsPtr :: as_mut_ptr( & mut self . work) ,
215+ & lwork,
216+ & mut info,
217+ )
218+ } ,
219+ }
220+ info. as_lapack_result( ) ?;
221+ Ok ( ( ) )
222+ }
223+ }
224+ } ;
225+ }
226+
227+ impl_q_work ! ( c64, lapack_sys:: zungqr_, lapack_sys:: zunglq_) ;
228+ impl_q_work ! ( c32, lapack_sys:: cungqr_, lapack_sys:: cunglq_) ;
229+ impl_q_work ! ( f64 , lapack_sys:: dorgqr_, lapack_sys:: dorglq_) ;
230+ impl_q_work ! ( f32 , lapack_sys:: sorgqr_, lapack_sys:: sorglq_) ;
231+
131232macro_rules! impl_qr {
132233 ( $scalar: ty, $qrf: path, $lqf: path, $gqr: path, $glq: path) => {
133234 impl QR_ for $scalar {
0 commit comments