Annotation of rpl/lapack/lapack/zgelsd.f, revision 1.12
1.9 bertrand 1: *> \brief <b> ZGELSD computes the minimum-norm solution to a linear least squares problem for GE matrices</b>
2: *
3: * =========== DOCUMENTATION ===========
4: *
5: * Online html documentation available at
6: * http://www.netlib.org/lapack/explore-html/
7: *
8: *> \htmlonly
9: *> Download ZGELSD + dependencies
10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zgelsd.f">
11: *> [TGZ]</a>
12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zgelsd.f">
13: *> [ZIP]</a>
14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgelsd.f">
15: *> [TXT]</a>
16: *> \endhtmlonly
17: *
18: * Definition:
19: * ===========
20: *
21: * SUBROUTINE ZGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
22: * WORK, LWORK, RWORK, IWORK, INFO )
23: *
24: * .. Scalar Arguments ..
25: * INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
26: * DOUBLE PRECISION RCOND
27: * ..
28: * .. Array Arguments ..
29: * INTEGER IWORK( * )
30: * DOUBLE PRECISION RWORK( * ), S( * )
31: * COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
32: * ..
33: *
34: *
35: *> \par Purpose:
36: * =============
37: *>
38: *> \verbatim
39: *>
40: *> ZGELSD computes the minimum-norm solution to a real linear least
41: *> squares problem:
42: *> minimize 2-norm(| b - A*x |)
43: *> using the singular value decomposition (SVD) of A. A is an M-by-N
44: *> matrix which may be rank-deficient.
45: *>
46: *> Several right hand side vectors b and solution vectors x can be
47: *> handled in a single call; they are stored as the columns of the
48: *> M-by-NRHS right hand side matrix B and the N-by-NRHS solution
49: *> matrix X.
50: *>
51: *> The problem is solved in three steps:
52: *> (1) Reduce the coefficient matrix A to bidiagonal form with
53: *> Householder tranformations, reducing the original problem
54: *> into a "bidiagonal least squares problem" (BLS)
55: *> (2) Solve the BLS using a divide and conquer approach.
56: *> (3) Apply back all the Householder tranformations to solve
57: *> the original least squares problem.
58: *>
59: *> The effective rank of A is determined by treating as zero those
60: *> singular values which are less than RCOND times the largest singular
61: *> value.
62: *>
63: *> The divide and conquer algorithm makes very mild assumptions about
64: *> floating point arithmetic. It will work on machines with a guard
65: *> digit in add/subtract, or on those binary machines without guard
66: *> digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
67: *> Cray-2. It could conceivably fail on hexadecimal or decimal machines
68: *> without guard digits, but we know of none.
69: *> \endverbatim
70: *
71: * Arguments:
72: * ==========
73: *
74: *> \param[in] M
75: *> \verbatim
76: *> M is INTEGER
77: *> The number of rows of the matrix A. M >= 0.
78: *> \endverbatim
79: *>
80: *> \param[in] N
81: *> \verbatim
82: *> N is INTEGER
83: *> The number of columns of the matrix A. N >= 0.
84: *> \endverbatim
85: *>
86: *> \param[in] NRHS
87: *> \verbatim
88: *> NRHS is INTEGER
89: *> The number of right hand sides, i.e., the number of columns
90: *> of the matrices B and X. NRHS >= 0.
91: *> \endverbatim
92: *>
93: *> \param[in] A
94: *> \verbatim
95: *> A is COMPLEX*16 array, dimension (LDA,N)
96: *> On entry, the M-by-N matrix A.
97: *> On exit, A has been destroyed.
98: *> \endverbatim
99: *>
100: *> \param[in] LDA
101: *> \verbatim
102: *> LDA is INTEGER
103: *> The leading dimension of the array A. LDA >= max(1,M).
104: *> \endverbatim
105: *>
106: *> \param[in,out] B
107: *> \verbatim
108: *> B is COMPLEX*16 array, dimension (LDB,NRHS)
109: *> On entry, the M-by-NRHS right hand side matrix B.
110: *> On exit, B is overwritten by the N-by-NRHS solution matrix X.
111: *> If m >= n and RANK = n, the residual sum-of-squares for
112: *> the solution in the i-th column is given by the sum of
113: *> squares of the modulus of elements n+1:m in that column.
114: *> \endverbatim
115: *>
116: *> \param[in] LDB
117: *> \verbatim
118: *> LDB is INTEGER
119: *> The leading dimension of the array B. LDB >= max(1,M,N).
120: *> \endverbatim
121: *>
122: *> \param[out] S
123: *> \verbatim
124: *> S is DOUBLE PRECISION array, dimension (min(M,N))
125: *> The singular values of A in decreasing order.
126: *> The condition number of A in the 2-norm = S(1)/S(min(m,n)).
127: *> \endverbatim
128: *>
129: *> \param[in] RCOND
130: *> \verbatim
131: *> RCOND is DOUBLE PRECISION
132: *> RCOND is used to determine the effective rank of A.
133: *> Singular values S(i) <= RCOND*S(1) are treated as zero.
134: *> If RCOND < 0, machine precision is used instead.
135: *> \endverbatim
136: *>
137: *> \param[out] RANK
138: *> \verbatim
139: *> RANK is INTEGER
140: *> The effective rank of A, i.e., the number of singular values
141: *> which are greater than RCOND*S(1).
142: *> \endverbatim
143: *>
144: *> \param[out] WORK
145: *> \verbatim
146: *> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
147: *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
148: *> \endverbatim
149: *>
150: *> \param[in] LWORK
151: *> \verbatim
152: *> LWORK is INTEGER
153: *> The dimension of the array WORK. LWORK must be at least 1.
154: *> The exact minimum amount of workspace needed depends on M,
155: *> N and NRHS. As long as LWORK is at least
156: *> 2*N + N*NRHS
157: *> if M is greater than or equal to N or
158: *> 2*M + M*NRHS
159: *> if M is less than N, the code will execute correctly.
160: *> For good performance, LWORK should generally be larger.
161: *>
162: *> If LWORK = -1, then a workspace query is assumed; the routine
163: *> only calculates the optimal size of the array WORK and the
164: *> minimum sizes of the arrays RWORK and IWORK, and returns
165: *> these values as the first entries of the WORK, RWORK and
166: *> IWORK arrays, and no error message related to LWORK is issued
167: *> by XERBLA.
168: *> \endverbatim
169: *>
170: *> \param[out] RWORK
171: *> \verbatim
172: *> RWORK is DOUBLE PRECISION array, dimension (MAX(1,LRWORK))
173: *> LRWORK >=
174: *> 10*N + 2*N*SMLSIZ + 8*N*NLVL + 3*SMLSIZ*NRHS +
175: *> MAX( (SMLSIZ+1)**2, N*(1+NRHS) + 2*NRHS )
176: *> if M is greater than or equal to N or
177: *> 10*M + 2*M*SMLSIZ + 8*M*NLVL + 3*SMLSIZ*NRHS +
178: *> MAX( (SMLSIZ+1)**2, N*(1+NRHS) + 2*NRHS )
179: *> if M is less than N, the code will execute correctly.
180: *> SMLSIZ is returned by ILAENV and is equal to the maximum
181: *> size of the subproblems at the bottom of the computation
182: *> tree (usually about 25), and
183: *> NLVL = MAX( 0, INT( LOG_2( MIN( M,N )/(SMLSIZ+1) ) ) + 1 )
184: *> On exit, if INFO = 0, RWORK(1) returns the minimum LRWORK.
185: *> \endverbatim
186: *>
187: *> \param[out] IWORK
188: *> \verbatim
189: *> IWORK is INTEGER array, dimension (MAX(1,LIWORK))
190: *> LIWORK >= max(1, 3*MINMN*NLVL + 11*MINMN),
191: *> where MINMN = MIN( M,N ).
192: *> On exit, if INFO = 0, IWORK(1) returns the minimum LIWORK.
193: *> \endverbatim
194: *>
195: *> \param[out] INFO
196: *> \verbatim
197: *> INFO is INTEGER
198: *> = 0: successful exit
199: *> < 0: if INFO = -i, the i-th argument had an illegal value.
200: *> > 0: the algorithm for computing the SVD failed to converge;
201: *> if INFO = i, i off-diagonal elements of an intermediate
202: *> bidiagonal form did not converge to zero.
203: *> \endverbatim
204: *
205: * Authors:
206: * ========
207: *
208: *> \author Univ. of Tennessee
209: *> \author Univ. of California Berkeley
210: *> \author Univ. of Colorado Denver
211: *> \author NAG Ltd.
212: *
213: *> \date November 2011
214: *
215: *> \ingroup complex16GEsolve
216: *
217: *> \par Contributors:
218: * ==================
219: *>
220: *> Ming Gu and Ren-Cang Li, Computer Science Division, University of
221: *> California at Berkeley, USA \n
222: *> Osni Marques, LBNL/NERSC, USA \n
223: *
224: * =====================================================================
1.1 bertrand 225: SUBROUTINE ZGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
226: $ WORK, LWORK, RWORK, IWORK, INFO )
227: *
1.9 bertrand 228: * -- LAPACK driver routine (version 3.4.0) --
1.1 bertrand 229: * -- LAPACK is a software package provided by Univ. of Tennessee, --
230: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.9 bertrand 231: * November 2011
1.1 bertrand 232: *
233: * .. Scalar Arguments ..
234: INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
235: DOUBLE PRECISION RCOND
236: * ..
237: * .. Array Arguments ..
238: INTEGER IWORK( * )
239: DOUBLE PRECISION RWORK( * ), S( * )
240: COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
241: * ..
242: *
243: * =====================================================================
244: *
245: * .. Parameters ..
246: DOUBLE PRECISION ZERO, ONE, TWO
247: PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )
248: COMPLEX*16 CZERO
249: PARAMETER ( CZERO = ( 0.0D+0, 0.0D+0 ) )
250: * ..
251: * .. Local Scalars ..
252: LOGICAL LQUERY
253: INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
254: $ LDWORK, LIWORK, LRWORK, MAXMN, MAXWRK, MINMN,
255: $ MINWRK, MM, MNTHR, NLVL, NRWORK, NWORK, SMLSIZ
256: DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
257: * ..
258: * .. External Subroutines ..
259: EXTERNAL DLABAD, DLASCL, DLASET, XERBLA, ZGEBRD, ZGELQF,
260: $ ZGEQRF, ZLACPY, ZLALSD, ZLASCL, ZLASET, ZUNMBR,
261: $ ZUNMLQ, ZUNMQR
262: * ..
263: * .. External Functions ..
264: INTEGER ILAENV
265: DOUBLE PRECISION DLAMCH, ZLANGE
266: EXTERNAL ILAENV, DLAMCH, ZLANGE
267: * ..
268: * .. Intrinsic Functions ..
269: INTRINSIC INT, LOG, MAX, MIN, DBLE
270: * ..
271: * .. Executable Statements ..
272: *
273: * Test the input arguments.
274: *
275: INFO = 0
276: MINMN = MIN( M, N )
277: MAXMN = MAX( M, N )
278: LQUERY = ( LWORK.EQ.-1 )
279: IF( M.LT.0 ) THEN
280: INFO = -1
281: ELSE IF( N.LT.0 ) THEN
282: INFO = -2
283: ELSE IF( NRHS.LT.0 ) THEN
284: INFO = -3
285: ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
286: INFO = -5
287: ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THEN
288: INFO = -7
289: END IF
290: *
291: * Compute workspace.
292: * (Note: Comments in the code beginning "Workspace:" describe the
293: * minimal amount of workspace needed at that point in the code,
294: * as well as the preferred amount for good performance.
295: * NB refers to the optimal block size for the immediately
296: * following subroutine, as returned by ILAENV.)
297: *
298: IF( INFO.EQ.0 ) THEN
299: MINWRK = 1
300: MAXWRK = 1
301: LIWORK = 1
302: LRWORK = 1
303: IF( MINMN.GT.0 ) THEN
304: SMLSIZ = ILAENV( 9, 'ZGELSD', ' ', 0, 0, 0, 0 )
305: MNTHR = ILAENV( 6, 'ZGELSD', ' ', M, N, NRHS, -1 )
306: NLVL = MAX( INT( LOG( DBLE( MINMN ) / DBLE( SMLSIZ + 1 ) ) /
307: $ LOG( TWO ) ) + 1, 0 )
308: LIWORK = 3*MINMN*NLVL + 11*MINMN
309: MM = M
310: IF( M.GE.N .AND. M.GE.MNTHR ) THEN
311: *
312: * Path 1a - overdetermined, with many more rows than
313: * columns.
314: *
315: MM = N
316: MAXWRK = MAX( MAXWRK, N*ILAENV( 1, 'ZGEQRF', ' ', M, N,
317: $ -1, -1 ) )
318: MAXWRK = MAX( MAXWRK, NRHS*ILAENV( 1, 'ZUNMQR', 'LC', M,
319: $ NRHS, N, -1 ) )
320: END IF
321: IF( M.GE.N ) THEN
322: *
323: * Path 1 - overdetermined or exactly determined.
324: *
325: LRWORK = 10*N + 2*N*SMLSIZ + 8*N*NLVL + 3*SMLSIZ*NRHS +
1.5 bertrand 326: $ MAX( (SMLSIZ+1)**2, N*(1+NRHS) + 2*NRHS )
1.1 bertrand 327: MAXWRK = MAX( MAXWRK, 2*N + ( MM + N )*ILAENV( 1,
328: $ 'ZGEBRD', ' ', MM, N, -1, -1 ) )
329: MAXWRK = MAX( MAXWRK, 2*N + NRHS*ILAENV( 1, 'ZUNMBR',
330: $ 'QLC', MM, NRHS, N, -1 ) )
331: MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1,
332: $ 'ZUNMBR', 'PLN', N, NRHS, N, -1 ) )
333: MAXWRK = MAX( MAXWRK, 2*N + N*NRHS )
334: MINWRK = MAX( 2*N + MM, 2*N + N*NRHS )
335: END IF
336: IF( N.GT.M ) THEN
337: LRWORK = 10*M + 2*M*SMLSIZ + 8*M*NLVL + 3*SMLSIZ*NRHS +
1.5 bertrand 338: $ MAX( (SMLSIZ+1)**2, N*(1+NRHS) + 2*NRHS )
1.1 bertrand 339: IF( N.GE.MNTHR ) THEN
340: *
341: * Path 2a - underdetermined, with many more columns
342: * than rows.
343: *
344: MAXWRK = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1,
345: $ -1 )
346: MAXWRK = MAX( MAXWRK, M*M + 4*M + 2*M*ILAENV( 1,
347: $ 'ZGEBRD', ' ', M, M, -1, -1 ) )
348: MAXWRK = MAX( MAXWRK, M*M + 4*M + NRHS*ILAENV( 1,
349: $ 'ZUNMBR', 'QLC', M, NRHS, M, -1 ) )
350: MAXWRK = MAX( MAXWRK, M*M + 4*M + ( M - 1 )*ILAENV( 1,
351: $ 'ZUNMLQ', 'LC', N, NRHS, M, -1 ) )
352: IF( NRHS.GT.1 ) THEN
353: MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
354: ELSE
355: MAXWRK = MAX( MAXWRK, M*M + 2*M )
356: END IF
357: MAXWRK = MAX( MAXWRK, M*M + 4*M + M*NRHS )
358: ! XXX: Ensure the Path 2a case below is triggered. The workspace
359: ! calculation should use queries for all routines eventually.
360: MAXWRK = MAX( MAXWRK,
361: $ 4*M+M*M+MAX( M, 2*M-4, NRHS, N-3*M ) )
362: ELSE
363: *
364: * Path 2 - underdetermined.
365: *
366: MAXWRK = 2*M + ( N + M )*ILAENV( 1, 'ZGEBRD', ' ', M,
367: $ N, -1, -1 )
368: MAXWRK = MAX( MAXWRK, 2*M + NRHS*ILAENV( 1, 'ZUNMBR',
369: $ 'QLC', M, NRHS, M, -1 ) )
370: MAXWRK = MAX( MAXWRK, 2*M + M*ILAENV( 1, 'ZUNMBR',
371: $ 'PLN', N, NRHS, M, -1 ) )
372: MAXWRK = MAX( MAXWRK, 2*M + M*NRHS )
373: END IF
374: MINWRK = MAX( 2*M + N, 2*M + M*NRHS )
375: END IF
376: END IF
377: MINWRK = MIN( MINWRK, MAXWRK )
378: WORK( 1 ) = MAXWRK
379: IWORK( 1 ) = LIWORK
380: RWORK( 1 ) = LRWORK
381: *
382: IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
383: INFO = -12
384: END IF
385: END IF
386: *
387: IF( INFO.NE.0 ) THEN
388: CALL XERBLA( 'ZGELSD', -INFO )
389: RETURN
390: ELSE IF( LQUERY ) THEN
391: RETURN
392: END IF
393: *
394: * Quick return if possible.
395: *
396: IF( M.EQ.0 .OR. N.EQ.0 ) THEN
397: RANK = 0
398: RETURN
399: END IF
400: *
401: * Get machine parameters.
402: *
403: EPS = DLAMCH( 'P' )
404: SFMIN = DLAMCH( 'S' )
405: SMLNUM = SFMIN / EPS
406: BIGNUM = ONE / SMLNUM
407: CALL DLABAD( SMLNUM, BIGNUM )
408: *
409: * Scale A if max entry outside range [SMLNUM,BIGNUM].
410: *
411: ANRM = ZLANGE( 'M', M, N, A, LDA, RWORK )
412: IASCL = 0
413: IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
414: *
415: * Scale matrix norm up to SMLNUM
416: *
417: CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
418: IASCL = 1
419: ELSE IF( ANRM.GT.BIGNUM ) THEN
420: *
421: * Scale matrix norm down to BIGNUM.
422: *
423: CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
424: IASCL = 2
425: ELSE IF( ANRM.EQ.ZERO ) THEN
426: *
427: * Matrix all zero. Return zero solution.
428: *
429: CALL ZLASET( 'F', MAX( M, N ), NRHS, CZERO, CZERO, B, LDB )
430: CALL DLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 )
431: RANK = 0
432: GO TO 10
433: END IF
434: *
435: * Scale B if max entry outside range [SMLNUM,BIGNUM].
436: *
437: BNRM = ZLANGE( 'M', M, NRHS, B, LDB, RWORK )
438: IBSCL = 0
439: IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
440: *
441: * Scale matrix norm up to SMLNUM.
442: *
443: CALL ZLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
444: IBSCL = 1
445: ELSE IF( BNRM.GT.BIGNUM ) THEN
446: *
447: * Scale matrix norm down to BIGNUM.
448: *
449: CALL ZLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
450: IBSCL = 2
451: END IF
452: *
453: * If M < N make sure B(M+1:N,:) = 0
454: *
455: IF( M.LT.N )
456: $ CALL ZLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB )
457: *
458: * Overdetermined case.
459: *
460: IF( M.GE.N ) THEN
461: *
462: * Path 1 - overdetermined or exactly determined.
463: *
464: MM = M
465: IF( M.GE.MNTHR ) THEN
466: *
467: * Path 1a - overdetermined, with many more rows than columns
468: *
469: MM = N
470: ITAU = 1
471: NWORK = ITAU + N
472: *
473: * Compute A=Q*R.
474: * (RWorkspace: need N)
475: * (CWorkspace: need N, prefer N*NB)
476: *
477: CALL ZGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
478: $ LWORK-NWORK+1, INFO )
479: *
480: * Multiply B by transpose(Q).
481: * (RWorkspace: need N)
482: * (CWorkspace: need NRHS, prefer NRHS*NB)
483: *
484: CALL ZUNMQR( 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAU ), B,
485: $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
486: *
487: * Zero out below R.
488: *
489: IF( N.GT.1 ) THEN
490: CALL ZLASET( 'L', N-1, N-1, CZERO, CZERO, A( 2, 1 ),
491: $ LDA )
492: END IF
493: END IF
494: *
495: ITAUQ = 1
496: ITAUP = ITAUQ + N
497: NWORK = ITAUP + N
498: IE = 1
499: NRWORK = IE + N
500: *
501: * Bidiagonalize R in A.
502: * (RWorkspace: need N)
503: * (CWorkspace: need 2*N+MM, prefer 2*N+(MM+N)*NB)
504: *
505: CALL ZGEBRD( MM, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
506: $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
507: $ INFO )
508: *
509: * Multiply B by transpose of left bidiagonalizing vectors of R.
510: * (CWorkspace: need 2*N+NRHS, prefer 2*N+NRHS*NB)
511: *
512: CALL ZUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
513: $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
514: *
515: * Solve the bidiagonal least squares problem.
516: *
517: CALL ZLALSD( 'U', SMLSIZ, N, NRHS, S, RWORK( IE ), B, LDB,
518: $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ),
519: $ IWORK, INFO )
520: IF( INFO.NE.0 ) THEN
521: GO TO 10
522: END IF
523: *
524: * Multiply B by right bidiagonalizing vectors of R.
525: *
526: CALL ZUNMBR( 'P', 'L', 'N', N, NRHS, N, A, LDA, WORK( ITAUP ),
527: $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
528: *
529: ELSE IF( N.GE.MNTHR .AND. LWORK.GE.4*M+M*M+
530: $ MAX( M, 2*M-4, NRHS, N-3*M ) ) THEN
531: *
532: * Path 2a - underdetermined, with many more columns than rows
533: * and sufficient workspace for an efficient algorithm.
534: *
535: LDWORK = M
536: IF( LWORK.GE.MAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ),
537: $ M*LDA+M+M*NRHS ) )LDWORK = LDA
538: ITAU = 1
539: NWORK = M + 1
540: *
541: * Compute A=L*Q.
542: * (CWorkspace: need 2*M, prefer M+M*NB)
543: *
544: CALL ZGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
545: $ LWORK-NWORK+1, INFO )
546: IL = NWORK
547: *
548: * Copy L to WORK(IL), zeroing out above its diagonal.
549: *
550: CALL ZLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK )
551: CALL ZLASET( 'U', M-1, M-1, CZERO, CZERO, WORK( IL+LDWORK ),
552: $ LDWORK )
553: ITAUQ = IL + LDWORK*M
554: ITAUP = ITAUQ + M
555: NWORK = ITAUP + M
556: IE = 1
557: NRWORK = IE + M
558: *
559: * Bidiagonalize L in WORK(IL).
560: * (RWorkspace: need M)
561: * (CWorkspace: need M*M+4*M, prefer M*M+4*M+2*M*NB)
562: *
563: CALL ZGEBRD( M, M, WORK( IL ), LDWORK, S, RWORK( IE ),
564: $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
565: $ LWORK-NWORK+1, INFO )
566: *
567: * Multiply B by transpose of left bidiagonalizing vectors of L.
568: * (CWorkspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)
569: *
570: CALL ZUNMBR( 'Q', 'L', 'C', M, NRHS, M, WORK( IL ), LDWORK,
571: $ WORK( ITAUQ ), B, LDB, WORK( NWORK ),
572: $ LWORK-NWORK+1, INFO )
573: *
574: * Solve the bidiagonal least squares problem.
575: *
576: CALL ZLALSD( 'U', SMLSIZ, M, NRHS, S, RWORK( IE ), B, LDB,
577: $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ),
578: $ IWORK, INFO )
579: IF( INFO.NE.0 ) THEN
580: GO TO 10
581: END IF
582: *
583: * Multiply B by right bidiagonalizing vectors of L.
584: *
585: CALL ZUNMBR( 'P', 'L', 'N', M, NRHS, M, WORK( IL ), LDWORK,
586: $ WORK( ITAUP ), B, LDB, WORK( NWORK ),
587: $ LWORK-NWORK+1, INFO )
588: *
589: * Zero out below first M rows of B.
590: *
591: CALL ZLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB )
592: NWORK = ITAU + M
593: *
594: * Multiply transpose(Q) by B.
595: * (CWorkspace: need NRHS, prefer NRHS*NB)
596: *
597: CALL ZUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, WORK( ITAU ), B,
598: $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
599: *
600: ELSE
601: *
602: * Path 2 - remaining underdetermined cases.
603: *
604: ITAUQ = 1
605: ITAUP = ITAUQ + M
606: NWORK = ITAUP + M
607: IE = 1
608: NRWORK = IE + M
609: *
610: * Bidiagonalize A.
611: * (RWorkspace: need M)
612: * (CWorkspace: need 2*M+N, prefer 2*M+(M+N)*NB)
613: *
614: CALL ZGEBRD( M, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
615: $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
616: $ INFO )
617: *
618: * Multiply B by transpose of left bidiagonalizing vectors.
619: * (CWorkspace: need 2*M+NRHS, prefer 2*M+NRHS*NB)
620: *
621: CALL ZUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAUQ ),
622: $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
623: *
624: * Solve the bidiagonal least squares problem.
625: *
626: CALL ZLALSD( 'L', SMLSIZ, M, NRHS, S, RWORK( IE ), B, LDB,
627: $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ),
628: $ IWORK, INFO )
629: IF( INFO.NE.0 ) THEN
630: GO TO 10
631: END IF
632: *
633: * Multiply B by right bidiagonalizing vectors of A.
634: *
635: CALL ZUNMBR( 'P', 'L', 'N', N, NRHS, M, A, LDA, WORK( ITAUP ),
636: $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
637: *
638: END IF
639: *
640: * Undo scaling.
641: *
642: IF( IASCL.EQ.1 ) THEN
643: CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )
644: CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
645: $ INFO )
646: ELSE IF( IASCL.EQ.2 ) THEN
647: CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )
648: CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
649: $ INFO )
650: END IF
651: IF( IBSCL.EQ.1 ) THEN
652: CALL ZLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
653: ELSE IF( IBSCL.EQ.2 ) THEN
654: CALL ZLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )
655: END IF
656: *
657: 10 CONTINUE
658: WORK( 1 ) = MAXWRK
659: IWORK( 1 ) = LIWORK
660: RWORK( 1 ) = LRWORK
661: RETURN
662: *
663: * End of ZGELSD
664: *
665: END
CVSweb interface <joel.bertrand@systella.fr>