LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
zgelss.f
Go to the documentation of this file.
1*> \brief <b> ZGELSS solves overdetermined or underdetermined systems for GE matrices</b>
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download ZGELSS + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zgelss.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zgelss.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgelss.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE ZGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
20* WORK, LWORK, RWORK, INFO )
21*
22* .. Scalar Arguments ..
23* INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
24* DOUBLE PRECISION RCOND
25* ..
26* .. Array Arguments ..
27* DOUBLE PRECISION RWORK( * ), S( * )
28* COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
29* ..
30*
31*
32*> \par Purpose:
33* =============
34*>
35*> \verbatim
36*>
37*> ZGELSS computes the minimum norm solution to a complex linear
38*> least squares problem:
39*>
40*> Minimize 2-norm(| b - A*x |).
41*>
42*> using the singular value decomposition (SVD) of A. A is an M-by-N
43*> matrix which may be rank-deficient.
44*>
45*> Several right hand side vectors b and solution vectors x can be
46*> handled in a single call; they are stored as the columns of the
47*> M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix
48*> X.
49*>
50*> The effective rank of A is determined by treating as zero those
51*> singular values which are less than RCOND times the largest singular
52*> value.
53*> \endverbatim
54*
55* Arguments:
56* ==========
57*
58*> \param[in] M
59*> \verbatim
60*> M is INTEGER
61*> The number of rows of the matrix A. M >= 0.
62*> \endverbatim
63*>
64*> \param[in] N
65*> \verbatim
66*> N is INTEGER
67*> The number of columns of the matrix A. N >= 0.
68*> \endverbatim
69*>
70*> \param[in] NRHS
71*> \verbatim
72*> NRHS is INTEGER
73*> The number of right hand sides, i.e., the number of columns
74*> of the matrices B and X. NRHS >= 0.
75*> \endverbatim
76*>
77*> \param[in,out] A
78*> \verbatim
79*> A is COMPLEX*16 array, dimension (LDA,N)
80*> On entry, the M-by-N matrix A.
81*> On exit, the first min(m,n) rows of A are overwritten with
82*> its right singular vectors, stored rowwise.
83*> \endverbatim
84*>
85*> \param[in] LDA
86*> \verbatim
87*> LDA is INTEGER
88*> The leading dimension of the array A. LDA >= max(1,M).
89*> \endverbatim
90*>
91*> \param[in,out] B
92*> \verbatim
93*> B is COMPLEX*16 array, dimension (LDB,NRHS)
94*> On entry, the M-by-NRHS right hand side matrix B.
95*> On exit, B is overwritten by the N-by-NRHS solution matrix X.
96*> If m >= n and RANK = n, the residual sum-of-squares for
97*> the solution in the i-th column is given by the sum of
98*> squares of the modulus of elements n+1:m in that column.
99*> \endverbatim
100*>
101*> \param[in] LDB
102*> \verbatim
103*> LDB is INTEGER
104*> The leading dimension of the array B. LDB >= max(1,M,N).
105*> \endverbatim
106*>
107*> \param[out] S
108*> \verbatim
109*> S is DOUBLE PRECISION array, dimension (min(M,N))
110*> The singular values of A in decreasing order.
111*> The condition number of A in the 2-norm = S(1)/S(min(m,n)).
112*> \endverbatim
113*>
114*> \param[in] RCOND
115*> \verbatim
116*> RCOND is DOUBLE PRECISION
117*> RCOND is used to determine the effective rank of A.
118*> Singular values S(i) <= RCOND*S(1) are treated as zero.
119*> If RCOND < 0, machine precision is used instead.
120*> \endverbatim
121*>
122*> \param[out] RANK
123*> \verbatim
124*> RANK is INTEGER
125*> The effective rank of A, i.e., the number of singular values
126*> which are greater than RCOND*S(1).
127*> \endverbatim
128*>
129*> \param[out] WORK
130*> \verbatim
131*> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
132*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
133*> \endverbatim
134*>
135*> \param[in] LWORK
136*> \verbatim
137*> LWORK is INTEGER
138*> The dimension of the array WORK. LWORK >= 1, and also:
139*> LWORK >= 2*min(M,N) + max(M,N,NRHS)
140*> For good performance, LWORK should generally be larger.
141*>
142*> If LWORK = -1, then a workspace query is assumed; the routine
143*> only calculates the optimal size of the WORK array, returns
144*> this value as the first entry of the WORK array, and no error
145*> message related to LWORK is issued by XERBLA.
146*> \endverbatim
147*>
148*> \param[out] RWORK
149*> \verbatim
150*> RWORK is DOUBLE PRECISION array, dimension (5*min(M,N))
151*> \endverbatim
152*>
153*> \param[out] INFO
154*> \verbatim
155*> INFO is INTEGER
156*> = 0: successful exit
157*> < 0: if INFO = -i, the i-th argument had an illegal value.
158*> > 0: the algorithm for computing the SVD failed to converge;
159*> if INFO = i, i off-diagonal elements of an intermediate
160*> bidiagonal form did not converge to zero.
161*> \endverbatim
162*
163* Authors:
164* ========
165*
166*> \author Univ. of Tennessee
167*> \author Univ. of California Berkeley
168*> \author Univ. of Colorado Denver
169*> \author NAG Ltd.
170*
171*> \ingroup gelss
172*
173* =====================================================================
174 SUBROUTINE zgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
175 $ WORK, LWORK, RWORK, INFO )
176*
177* -- LAPACK driver routine --
178* -- LAPACK is a software package provided by Univ. of Tennessee, --
179* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
180*
181* .. Scalar Arguments ..
182 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
183 DOUBLE PRECISION RCOND
184* ..
185* .. Array Arguments ..
186 DOUBLE PRECISION RWORK( * ), S( * )
187 COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
188* ..
189*
190* =====================================================================
191*
192* .. Parameters ..
193 DOUBLE PRECISION ZERO, ONE
194 parameter( zero = 0.0d+0, one = 1.0d+0 )
195 COMPLEX*16 CZERO, CONE
196 parameter( czero = ( 0.0d+0, 0.0d+0 ),
197 $ cone = ( 1.0d+0, 0.0d+0 ) )
198* ..
199* .. Local Scalars ..
200 LOGICAL LQUERY
201 INTEGER BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
202 $ itau, itaup, itauq, iwork, ldwork, maxmn,
203 $ maxwrk, minmn, minwrk, mm, mnthr
204 INTEGER LWORK_ZGEQRF, LWORK_ZUNMQR, LWORK_ZGEBRD,
205 $ lwork_zunmbr, lwork_zungbr, lwork_zunmlq,
206 $ lwork_zgelqf
207 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
208* ..
209* .. Local Arrays ..
210 COMPLEX*16 DUM( 1 )
211* ..
212* .. External Subroutines ..
213 EXTERNAL dlascl, dlaset, xerbla, zbdsqr, zcopy,
214 $ zdrscl,
217* ..
218* .. External Functions ..
219 INTEGER ILAENV
220 DOUBLE PRECISION DLAMCH, ZLANGE
221 EXTERNAL ilaenv, dlamch, zlange
222* ..
223* .. Intrinsic Functions ..
224 INTRINSIC max, min
225* ..
226* .. Executable Statements ..
227*
228* Test the input arguments
229*
230 info = 0
231 minmn = min( m, n )
232 maxmn = max( m, n )
233 lquery = ( lwork.EQ.-1 )
234 IF( m.LT.0 ) THEN
235 info = -1
236 ELSE IF( n.LT.0 ) THEN
237 info = -2
238 ELSE IF( nrhs.LT.0 ) THEN
239 info = -3
240 ELSE IF( lda.LT.max( 1, m ) ) THEN
241 info = -5
242 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
243 info = -7
244 END IF
245*
246* Compute workspace
247* (Note: Comments in the code beginning "Workspace:" describe the
248* minimal amount of workspace needed at that point in the code,
249* as well as the preferred amount for good performance.
250* CWorkspace refers to complex workspace, and RWorkspace refers
251* to real workspace. NB refers to the optimal block size for the
252* immediately following subroutine, as returned by ILAENV.)
253*
254 IF( info.EQ.0 ) THEN
255 minwrk = 1
256 maxwrk = 1
257 IF( minmn.GT.0 ) THEN
258 mm = m
259 mnthr = ilaenv( 6, 'ZGELSS', ' ', m, n, nrhs, -1 )
260 IF( m.GE.n .AND. m.GE.mnthr ) THEN
261*
262* Path 1a - overdetermined, with many more rows than
263* columns
264*
265* Compute space needed for ZGEQRF
266 CALL zgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
267 lwork_zgeqrf = int( dum(1) )
268* Compute space needed for ZUNMQR
269 CALL zunmqr( 'L', 'C', m, nrhs, n, a, lda, dum(1), b,
270 $ ldb, dum(1), -1, info )
271 lwork_zunmqr = int( dum(1) )
272 mm = n
273 maxwrk = max( maxwrk, n + n*ilaenv( 1, 'ZGEQRF', ' ',
274 $ m,
275 $ n, -1, -1 ) )
276 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1, 'ZUNMQR',
277 $ 'LC',
278 $ m, nrhs, n, -1 ) )
279 END IF
280 IF( m.GE.n ) THEN
281*
282* Path 1 - overdetermined or exactly determined
283*
284* Compute space needed for ZGEBRD
285 CALL zgebrd( mm, n, a, lda, s, s, dum(1), dum(1),
286 $ dum(1),
287 $ -1, info )
288 lwork_zgebrd = int( dum(1) )
289* Compute space needed for ZUNMBR
290 CALL zunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda,
291 $ dum(1),
292 $ b, ldb, dum(1), -1, info )
293 lwork_zunmbr = int( dum(1) )
294* Compute space needed for ZUNGBR
295 CALL zungbr( 'P', n, n, n, a, lda, dum(1),
296 $ dum(1), -1, info )
297 lwork_zungbr = int( dum(1) )
298* Compute total workspace needed
299 maxwrk = max( maxwrk, 2*n + lwork_zgebrd )
300 maxwrk = max( maxwrk, 2*n + lwork_zunmbr )
301 maxwrk = max( maxwrk, 2*n + lwork_zungbr )
302 maxwrk = max( maxwrk, n*nrhs )
303 minwrk = 2*n + max( nrhs, m )
304 END IF
305 IF( n.GT.m ) THEN
306 minwrk = 2*m + max( nrhs, n )
307 IF( n.GE.mnthr ) THEN
308*
309* Path 2a - underdetermined, with many more columns
310* than rows
311*
312* Compute space needed for ZGELQF
313 CALL zgelqf( m, n, a, lda, dum(1), dum(1),
314 $ -1, info )
315 lwork_zgelqf = int( dum(1) )
316* Compute space needed for ZGEBRD
317 CALL zgebrd( m, m, a, lda, s, s, dum(1), dum(1),
318 $ dum(1), -1, info )
319 lwork_zgebrd = int( dum(1) )
320* Compute space needed for ZUNMBR
321 CALL zunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda,
322 $ dum(1), b, ldb, dum(1), -1, info )
323 lwork_zunmbr = int( dum(1) )
324* Compute space needed for ZUNGBR
325 CALL zungbr( 'P', m, m, m, a, lda, dum(1),
326 $ dum(1), -1, info )
327 lwork_zungbr = int( dum(1) )
328* Compute space needed for ZUNMLQ
329 CALL zunmlq( 'L', 'C', n, nrhs, m, a, lda, dum(1),
330 $ b, ldb, dum(1), -1, info )
331 lwork_zunmlq = int( dum(1) )
332* Compute total workspace needed
333 maxwrk = m + lwork_zgelqf
334 maxwrk = max( maxwrk, 3*m + m*m + lwork_zgebrd )
335 maxwrk = max( maxwrk, 3*m + m*m + lwork_zunmbr )
336 maxwrk = max( maxwrk, 3*m + m*m + lwork_zungbr )
337 IF( nrhs.GT.1 ) THEN
338 maxwrk = max( maxwrk, m*m + m + m*nrhs )
339 ELSE
340 maxwrk = max( maxwrk, m*m + 2*m )
341 END IF
342 maxwrk = max( maxwrk, m + lwork_zunmlq )
343 ELSE
344*
345* Path 2 - underdetermined
346*
347* Compute space needed for ZGEBRD
348 CALL zgebrd( m, n, a, lda, s, s, dum(1), dum(1),
349 $ dum(1), -1, info )
350 lwork_zgebrd = int( dum(1) )
351* Compute space needed for ZUNMBR
352 CALL zunmbr( 'Q', 'L', 'C', m, nrhs, m, a, lda,
353 $ dum(1), b, ldb, dum(1), -1, info )
354 lwork_zunmbr = int( dum(1) )
355* Compute space needed for ZUNGBR
356 CALL zungbr( 'P', m, n, m, a, lda, dum(1),
357 $ dum(1), -1, info )
358 lwork_zungbr = int( dum(1) )
359 maxwrk = 2*m + lwork_zgebrd
360 maxwrk = max( maxwrk, 2*m + lwork_zunmbr )
361 maxwrk = max( maxwrk, 2*m + lwork_zungbr )
362 maxwrk = max( maxwrk, n*nrhs )
363 END IF
364 END IF
365 maxwrk = max( minwrk, maxwrk )
366 END IF
367 work( 1 ) = maxwrk
368*
369 IF( lwork.LT.minwrk .AND. .NOT.lquery )
370 $ info = -12
371 END IF
372*
373 IF( info.NE.0 ) THEN
374 CALL xerbla( 'ZGELSS', -info )
375 RETURN
376 ELSE IF( lquery ) THEN
377 RETURN
378 END IF
379*
380* Quick return if possible
381*
382 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
383 rank = 0
384 RETURN
385 END IF
386*
387* Get machine parameters
388*
389 eps = dlamch( 'P' )
390 sfmin = dlamch( 'S' )
391 smlnum = sfmin / eps
392 bignum = one / smlnum
393*
394* Scale A if max element outside range [SMLNUM,BIGNUM]
395*
396 anrm = zlange( 'M', m, n, a, lda, rwork )
397 iascl = 0
398 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
399*
400* Scale matrix norm up to SMLNUM
401*
402 CALL zlascl( 'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
403 iascl = 1
404 ELSE IF( anrm.GT.bignum ) THEN
405*
406* Scale matrix norm down to BIGNUM
407*
408 CALL zlascl( 'G', 0, 0, anrm, bignum, m, n, a, lda, info )
409 iascl = 2
410 ELSE IF( anrm.EQ.zero ) THEN
411*
412* Matrix all zero. Return zero solution.
413*
414 CALL zlaset( 'F', max( m, n ), nrhs, czero, czero, b, ldb )
415 CALL dlaset( 'F', minmn, 1, zero, zero, s, minmn )
416 rank = 0
417 GO TO 70
418 END IF
419*
420* Scale B if max element outside range [SMLNUM,BIGNUM]
421*
422 bnrm = zlange( 'M', m, nrhs, b, ldb, rwork )
423 ibscl = 0
424 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
425*
426* Scale matrix norm up to SMLNUM
427*
428 CALL zlascl( 'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
429 $ info )
430 ibscl = 1
431 ELSE IF( bnrm.GT.bignum ) THEN
432*
433* Scale matrix norm down to BIGNUM
434*
435 CALL zlascl( 'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
436 $ info )
437 ibscl = 2
438 END IF
439*
440* Overdetermined case
441*
442 IF( m.GE.n ) THEN
443*
444* Path 1 - overdetermined or exactly determined
445*
446 mm = m
447 IF( m.GE.mnthr ) THEN
448*
449* Path 1a - overdetermined, with many more rows than columns
450*
451 mm = n
452 itau = 1
453 iwork = itau + n
454*
455* Compute A=Q*R
456* (CWorkspace: need 2*N, prefer N+N*NB)
457* (RWorkspace: none)
458*
459 CALL zgeqrf( m, n, a, lda, work( itau ), work( iwork ),
460 $ lwork-iwork+1, info )
461*
462* Multiply B by transpose(Q)
463* (CWorkspace: need N+NRHS, prefer N+NRHS*NB)
464* (RWorkspace: none)
465*
466 CALL zunmqr( 'L', 'C', m, nrhs, n, a, lda, work( itau ),
467 $ b,
468 $ ldb, work( iwork ), lwork-iwork+1, info )
469*
470* Zero out below R
471*
472 IF( n.GT.1 )
473 $ CALL zlaset( 'L', n-1, n-1, czero, czero, a( 2, 1 ),
474 $ lda )
475 END IF
476*
477 ie = 1
478 itauq = 1
479 itaup = itauq + n
480 iwork = itaup + n
481*
482* Bidiagonalize R in A
483* (CWorkspace: need 2*N+MM, prefer 2*N+(MM+N)*NB)
484* (RWorkspace: need N)
485*
486 CALL zgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
487 $ work( itaup ), work( iwork ), lwork-iwork+1,
488 $ info )
489*
490* Multiply B by transpose of left bidiagonalizing vectors of R
491* (CWorkspace: need 2*N+NRHS, prefer 2*N+NRHS*NB)
492* (RWorkspace: none)
493*
494 CALL zunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda,
495 $ work( itauq ),
496 $ b, ldb, work( iwork ), lwork-iwork+1, info )
497*
498* Generate right bidiagonalizing vectors of R in A
499* (CWorkspace: need 3*N-1, prefer 2*N+(N-1)*NB)
500* (RWorkspace: none)
501*
502 CALL zungbr( 'P', n, n, n, a, lda, work( itaup ),
503 $ work( iwork ), lwork-iwork+1, info )
504 irwork = ie + n
505*
506* Perform bidiagonal QR iteration
507* multiply B by transpose of left singular vectors
508* compute right singular vectors in A
509* (CWorkspace: none)
510* (RWorkspace: need BDSPAC)
511*
512 CALL zbdsqr( 'U', n, n, 0, nrhs, s, rwork( ie ), a, lda,
513 $ dum,
514 $ 1, b, ldb, rwork( irwork ), info )
515 IF( info.NE.0 )
516 $ GO TO 70
517*
518* Multiply B by reciprocals of singular values
519*
520 thr = max( rcond*s( 1 ), sfmin )
521 IF( rcond.LT.zero )
522 $ thr = max( eps*s( 1 ), sfmin )
523 rank = 0
524 DO 10 i = 1, n
525 IF( s( i ).GT.thr ) THEN
526 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
527 rank = rank + 1
528 ELSE
529 CALL zlaset( 'F', 1, nrhs, czero, czero, b( i, 1 ),
530 $ ldb )
531 END IF
532 10 CONTINUE
533*
534* Multiply B by right singular vectors
535* (CWorkspace: need N, prefer N*NRHS)
536* (RWorkspace: none)
537*
538 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
539 CALL zgemm( 'C', 'N', n, nrhs, n, cone, a, lda, b, ldb,
540 $ czero, work, ldb )
541 CALL zlacpy( 'G', n, nrhs, work, ldb, b, ldb )
542 ELSE IF( nrhs.GT.1 ) THEN
543 chunk = lwork / n
544 DO 20 i = 1, nrhs, chunk
545 bl = min( nrhs-i+1, chunk )
546 CALL zgemm( 'C', 'N', n, bl, n, cone, a, lda, b( 1,
547 $ i ),
548 $ ldb, czero, work, n )
549 CALL zlacpy( 'G', n, bl, work, n, b( 1, i ), ldb )
550 20 CONTINUE
551 ELSE IF( nrhs.EQ.1 ) THEN
552 CALL zgemv( 'C', n, n, cone, a, lda, b, 1, czero, work,
553 $ 1 )
554 CALL zcopy( n, work, 1, b, 1 )
555 END IF
556*
557 ELSE IF( n.GE.mnthr .AND. lwork.GE.3*m+m*m+max( m, nrhs, n-2*m ) )
558 $ THEN
559*
560* Underdetermined case, M much less than N
561*
562* Path 2a - underdetermined, with many more columns than rows
563* and sufficient workspace for an efficient algorithm
564*
565 ldwork = m
566 IF( lwork.GE.3*m+m*lda+max( m, nrhs, n-2*m ) )
567 $ ldwork = lda
568 itau = 1
569 iwork = m + 1
570*
571* Compute A=L*Q
572* (CWorkspace: need 2*M, prefer M+M*NB)
573* (RWorkspace: none)
574*
575 CALL zgelqf( m, n, a, lda, work( itau ), work( iwork ),
576 $ lwork-iwork+1, info )
577 il = iwork
578*
579* Copy L to WORK(IL), zeroing out above it
580*
581 CALL zlacpy( 'L', m, m, a, lda, work( il ), ldwork )
582 CALL zlaset( 'U', m-1, m-1, czero, czero, work( il+ldwork ),
583 $ ldwork )
584 ie = 1
585 itauq = il + ldwork*m
586 itaup = itauq + m
587 iwork = itaup + m
588*
589* Bidiagonalize L in WORK(IL)
590* (CWorkspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
591* (RWorkspace: need M)
592*
593 CALL zgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
594 $ work( itauq ), work( itaup ), work( iwork ),
595 $ lwork-iwork+1, info )
596*
597* Multiply B by transpose of left bidiagonalizing vectors of L
598* (CWorkspace: need M*M+3*M+NRHS, prefer M*M+3*M+NRHS*NB)
599* (RWorkspace: none)
600*
601 CALL zunmbr( 'Q', 'L', 'C', m, nrhs, m, work( il ), ldwork,
602 $ work( itauq ), b, ldb, work( iwork ),
603 $ lwork-iwork+1, info )
604*
605* Generate right bidiagonalizing vectors of R in WORK(IL)
606* (CWorkspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)
607* (RWorkspace: none)
608*
609 CALL zungbr( 'P', m, m, m, work( il ), ldwork,
610 $ work( itaup ),
611 $ work( iwork ), lwork-iwork+1, info )
612 irwork = ie + m
613*
614* Perform bidiagonal QR iteration, computing right singular
615* vectors of L in WORK(IL) and multiplying B by transpose of
616* left singular vectors
617* (CWorkspace: need M*M)
618* (RWorkspace: need BDSPAC)
619*
620 CALL zbdsqr( 'U', m, m, 0, nrhs, s, rwork( ie ), work( il ),
621 $ ldwork, a, lda, b, ldb, rwork( irwork ), info )
622 IF( info.NE.0 )
623 $ GO TO 70
624*
625* Multiply B by reciprocals of singular values
626*
627 thr = max( rcond*s( 1 ), sfmin )
628 IF( rcond.LT.zero )
629 $ thr = max( eps*s( 1 ), sfmin )
630 rank = 0
631 DO 30 i = 1, m
632 IF( s( i ).GT.thr ) THEN
633 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
634 rank = rank + 1
635 ELSE
636 CALL zlaset( 'F', 1, nrhs, czero, czero, b( i, 1 ),
637 $ ldb )
638 END IF
639 30 CONTINUE
640 iwork = il + m*ldwork
641*
642* Multiply B by right singular vectors of L in WORK(IL)
643* (CWorkspace: need M*M+2*M, prefer M*M+M+M*NRHS)
644* (RWorkspace: none)
645*
646 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 ) THEN
647 CALL zgemm( 'C', 'N', m, nrhs, m, cone, work( il ),
648 $ ldwork,
649 $ b, ldb, czero, work( iwork ), ldb )
650 CALL zlacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb )
651 ELSE IF( nrhs.GT.1 ) THEN
652 chunk = ( lwork-iwork+1 ) / m
653 DO 40 i = 1, nrhs, chunk
654 bl = min( nrhs-i+1, chunk )
655 CALL zgemm( 'C', 'N', m, bl, m, cone, work( il ),
656 $ ldwork,
657 $ b( 1, i ), ldb, czero, work( iwork ), m )
658 CALL zlacpy( 'G', m, bl, work( iwork ), m, b( 1, i ),
659 $ ldb )
660 40 CONTINUE
661 ELSE IF( nrhs.EQ.1 ) THEN
662 CALL zgemv( 'C', m, m, cone, work( il ), ldwork, b( 1,
663 $ 1 ), 1, czero, work( iwork ), 1 )
664 CALL zcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
665 END IF
666*
667* Zero out below first M rows of B
668*
669 CALL zlaset( 'F', n-m, nrhs, czero, czero, b( m+1, 1 ),
670 $ ldb )
671 iwork = itau + m
672*
673* Multiply transpose(Q) by B
674* (CWorkspace: need M+NRHS, prefer M+NHRS*NB)
675* (RWorkspace: none)
676*
677 CALL zunmlq( 'L', 'C', n, nrhs, m, a, lda, work( itau ), b,
678 $ ldb, work( iwork ), lwork-iwork+1, info )
679*
680 ELSE
681*
682* Path 2 - remaining underdetermined cases
683*
684 ie = 1
685 itauq = 1
686 itaup = itauq + m
687 iwork = itaup + m
688*
689* Bidiagonalize A
690* (CWorkspace: need 3*M, prefer 2*M+(M+N)*NB)
691* (RWorkspace: need N)
692*
693 CALL zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
694 $ work( itaup ), work( iwork ), lwork-iwork+1,
695 $ info )
696*
697* Multiply B by transpose of left bidiagonalizing vectors
698* (CWorkspace: need 2*M+NRHS, prefer 2*M+NRHS*NB)
699* (RWorkspace: none)
700*
701 CALL zunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda,
702 $ work( itauq ),
703 $ b, ldb, work( iwork ), lwork-iwork+1, info )
704*
705* Generate right bidiagonalizing vectors in A
706* (CWorkspace: need 3*M, prefer 2*M+M*NB)
707* (RWorkspace: none)
708*
709 CALL zungbr( 'P', m, n, m, a, lda, work( itaup ),
710 $ work( iwork ), lwork-iwork+1, info )
711 irwork = ie + m
712*
713* Perform bidiagonal QR iteration,
714* computing right singular vectors of A in A and
715* multiplying B by transpose of left singular vectors
716* (CWorkspace: none)
717* (RWorkspace: need BDSPAC)
718*
719 CALL zbdsqr( 'L', m, n, 0, nrhs, s, rwork( ie ), a, lda,
720 $ dum,
721 $ 1, b, ldb, rwork( irwork ), info )
722 IF( info.NE.0 )
723 $ GO TO 70
724*
725* Multiply B by reciprocals of singular values
726*
727 thr = max( rcond*s( 1 ), sfmin )
728 IF( rcond.LT.zero )
729 $ thr = max( eps*s( 1 ), sfmin )
730 rank = 0
731 DO 50 i = 1, m
732 IF( s( i ).GT.thr ) THEN
733 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
734 rank = rank + 1
735 ELSE
736 CALL zlaset( 'F', 1, nrhs, czero, czero, b( i, 1 ),
737 $ ldb )
738 END IF
739 50 CONTINUE
740*
741* Multiply B by right singular vectors of A
742* (CWorkspace: need N, prefer N*NRHS)
743* (RWorkspace: none)
744*
745 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
746 CALL zgemm( 'C', 'N', n, nrhs, m, cone, a, lda, b, ldb,
747 $ czero, work, ldb )
748 CALL zlacpy( 'G', n, nrhs, work, ldb, b, ldb )
749 ELSE IF( nrhs.GT.1 ) THEN
750 chunk = lwork / n
751 DO 60 i = 1, nrhs, chunk
752 bl = min( nrhs-i+1, chunk )
753 CALL zgemm( 'C', 'N', n, bl, m, cone, a, lda, b( 1,
754 $ i ),
755 $ ldb, czero, work, n )
756 CALL zlacpy( 'F', n, bl, work, n, b( 1, i ), ldb )
757 60 CONTINUE
758 ELSE IF( nrhs.EQ.1 ) THEN
759 CALL zgemv( 'C', m, n, cone, a, lda, b, 1, czero, work,
760 $ 1 )
761 CALL zcopy( n, work, 1, b, 1 )
762 END IF
763 END IF
764*
765* Undo scaling
766*
767 IF( iascl.EQ.1 ) THEN
768 CALL zlascl( 'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
769 $ info )
770 CALL dlascl( 'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
771 $ info )
772 ELSE IF( iascl.EQ.2 ) THEN
773 CALL zlascl( 'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
774 $ info )
775 CALL dlascl( 'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
776 $ info )
777 END IF
778 IF( ibscl.EQ.1 ) THEN
779 CALL zlascl( 'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
780 $ info )
781 ELSE IF( ibscl.EQ.2 ) THEN
782 CALL zlascl( 'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
783 $ info )
784 END IF
785 70 CONTINUE
786 work( 1 ) = maxwrk
787 RETURN
788*
789* End of ZGELSS
790*
791 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine zbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, rwork, info)
ZBDSQR
Definition zbdsqr.f:233
subroutine zcopy(n, zx, incx, zy, incy)
ZCOPY
Definition zcopy.f:81
subroutine zgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
ZGEBRD
Definition zgebrd.f:204
subroutine zgelqf(m, n, a, lda, tau, work, lwork, info)
ZGELQF
Definition zgelqf.f:142
subroutine zgelss(m, n, nrhs, a, lda, b, ldb, s, rcond, rank, work, lwork, rwork, info)
ZGELSS solves overdetermined or underdetermined systems for GE matrices
Definition zgelss.f:176
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
Definition zgemm.f:188
subroutine zgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
ZGEMV
Definition zgemv.f:160
subroutine zgeqrf(m, n, a, lda, tau, work, lwork, info)
ZGEQRF
Definition zgeqrf.f:144
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
Definition zlacpy.f:101
subroutine zlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
ZLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition zlascl.f:142
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition dlascl.f:142
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition dlaset.f:108
subroutine zlaset(uplo, m, n, alpha, beta, a, lda)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition zlaset.f:104
subroutine zdrscl(n, sa, sx, incx)
ZDRSCL multiplies a vector by the reciprocal of a real scalar.
Definition zdrscl.f:82
subroutine zungbr(vect, m, n, k, a, lda, tau, work, lwork, info)
ZUNGBR
Definition zungbr.f:156
subroutine zunmbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMBR
Definition zunmbr.f:194
subroutine zunmlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMLQ
Definition zunmlq.f:165
subroutine zunmqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMQR
Definition zunmqr.f:165