1 SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK,
2 $ LWORK, IWORK, INFO )
3 *
4 * -- LAPACK driver routine (version 3.2.1) --
5 * -- LAPACK is a software package provided by Univ. of Tennessee, --
6 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
7 * March 2009
8 *
9 * .. Scalar Arguments ..
10 CHARACTER JOBZ
11 INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N
12 * ..
13 * .. Array Arguments ..
14 INTEGER IWORK( * )
15 DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),
16 $ VT( LDVT, * ), WORK( * )
17 * ..
18 *
19 * Purpose
20 * =======
21 *
22 * DGESDD computes the singular value decomposition (SVD) of a real
23 * M-by-N matrix A, optionally computing the left and right singular
24 * vectors. If singular vectors are desired, it uses a
25 * divide-and-conquer algorithm.
26 *
27 * The SVD is written
28 *
29 * A = U * SIGMA * transpose(V)
30 *
31 * where SIGMA is an M-by-N matrix which is zero except for its
32 * min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
33 * V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
34 * are the singular values of A; they are real and non-negative, and
35 * are returned in descending order. The first min(m,n) columns of
36 * U and V are the left and right singular vectors of A.
37 *
38 * Note that the routine returns VT = V**T, not V.
39 *
40 * The divide and conquer algorithm makes very mild assumptions about
41 * floating point arithmetic. It will work on machines with a guard
42 * digit in add/subtract, or on those binary machines without guard
43 * digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
44 * Cray-2. It could conceivably fail on hexadecimal or decimal machines
45 * without guard digits, but we know of none.
46 *
47 * Arguments
48 * =========
49 *
50 * JOBZ (input) CHARACTER*1
51 * Specifies options for computing all or part of the matrix U:
52 * = 'A': all M columns of U and all N rows of V**T are
53 * returned in the arrays U and VT;
54 * = 'S': the first min(M,N) columns of U and the first
55 * min(M,N) rows of V**T are returned in the arrays U
56 * and VT;
57 * = 'O': If M >= N, the first N columns of U are overwritten
58 * on the array A and all rows of V**T are returned in
59 * the array VT;
60 * otherwise, all columns of U are returned in the
61 * array U and the first M rows of V**T are overwritten
62 * in the array A;
63 * = 'N': no columns of U or rows of V**T are computed.
64 *
65 * M (input) INTEGER
66 * The number of rows of the input matrix A. M >= 0.
67 *
68 * N (input) INTEGER
69 * The number of columns of the input matrix A. N >= 0.
70 *
71 * A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
72 * On entry, the M-by-N matrix A.
73 * On exit,
74 * if JOBZ = 'O', A is overwritten with the first N columns
75 * of U (the left singular vectors, stored
76 * columnwise) if M >= N;
77 * A is overwritten with the first M rows
78 * of V**T (the right singular vectors, stored
79 * rowwise) otherwise.
80 * if JOBZ .ne. 'O', the contents of A are destroyed.
81 *
82 * LDA (input) INTEGER
83 * The leading dimension of the array A. LDA >= max(1,M).
84 *
85 * S (output) DOUBLE PRECISION array, dimension (min(M,N))
86 * The singular values of A, sorted so that S(i) >= S(i+1).
87 *
88 * U (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
89 * UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;
90 * UCOL = min(M,N) if JOBZ = 'S'.
91 * If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M
92 * orthogonal matrix U;
93 * if JOBZ = 'S', U contains the first min(M,N) columns of U
94 * (the left singular vectors, stored columnwise);
95 * if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.
96 *
97 * LDU (input) INTEGER
98 * The leading dimension of the array U. LDU >= 1; if
99 * JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.
100 *
101 * VT (output) DOUBLE PRECISION array, dimension (LDVT,N)
102 * If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
103 * N-by-N orthogonal matrix V**T;
104 * if JOBZ = 'S', VT contains the first min(M,N) rows of
105 * V**T (the right singular vectors, stored rowwise);
106 * if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.
107 *
108 * LDVT (input) INTEGER
109 * The leading dimension of the array VT. LDVT >= 1; if
110 * JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N;
111 * if JOBZ = 'S', LDVT >= min(M,N).
112 *
113 * WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
114 * On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
115 *
116 * LWORK (input) INTEGER
117 * The dimension of the array WORK. LWORK >= 1.
118 * If JOBZ = 'N',
119 * LWORK >= 3*min(M,N) + max(max(M,N),7*min(M,N)).
120 * If JOBZ = 'O',
121 * LWORK >= 3*min(M,N) +
122 * max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)).
123 * If JOBZ = 'S' or 'A'
124 * LWORK >= 3*min(M,N) +
125 * max(max(M,N),4*min(M,N)*min(M,N)+4*min(M,N)).
126 * For good performance, LWORK should generally be larger.
127 * If LWORK = -1 but other input arguments are legal, WORK(1)
128 * returns the optimal LWORK.
129 *
130 * IWORK (workspace) INTEGER array, dimension (8*min(M,N))
131 *
132 * INFO (output) INTEGER
133 * = 0: successful exit.
134 * < 0: if INFO = -i, the i-th argument had an illegal value.
135 * > 0: DBDSDC did not converge, updating process failed.
136 *
137 * Further Details
138 * ===============
139 *
140 * Based on contributions by
141 * Ming Gu and Huan Ren, Computer Science Division, University of
142 * California at Berkeley, USA
143 *
144 * =====================================================================
145 *
146 * .. Parameters ..
147 DOUBLE PRECISION ZERO, ONE
148 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
149 * ..
150 * .. Local Scalars ..
151 LOGICAL LQUERY, WNTQA, WNTQAS, WNTQN, WNTQO, WNTQS
152 INTEGER BDSPAC, BLK, CHUNK, I, IE, IERR, IL,
153 $ IR, ISCL, ITAU, ITAUP, ITAUQ, IU, IVT, LDWKVT,
154 $ LDWRKL, LDWRKR, LDWRKU, MAXWRK, MINMN, MINWRK,
155 $ MNTHR, NWORK, WRKBL
156 DOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM
157 * ..
158 * .. Local Arrays ..
159 INTEGER IDUM( 1 )
160 DOUBLE PRECISION DUM( 1 )
161 * ..
162 * .. External Subroutines ..
163 EXTERNAL DBDSDC, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY,
164 $ DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR,
165 $ XERBLA
166 * ..
167 * .. External Functions ..
168 LOGICAL LSAME
169 INTEGER ILAENV
170 DOUBLE PRECISION DLAMCH, DLANGE
171 EXTERNAL DLAMCH, DLANGE, ILAENV, LSAME
172 * ..
173 * .. Intrinsic Functions ..
174 INTRINSIC INT, MAX, MIN, SQRT
175 * ..
176 * .. Executable Statements ..
177 *
178 * Test the input arguments
179 *
180 INFO = 0
181 MINMN = MIN( M, N )
182 WNTQA = LSAME( JOBZ, 'A' )
183 WNTQS = LSAME( JOBZ, 'S' )
184 WNTQAS = WNTQA .OR. WNTQS
185 WNTQO = LSAME( JOBZ, 'O' )
186 WNTQN = LSAME( JOBZ, 'N' )
187 LQUERY = ( LWORK.EQ.-1 )
188 *
189 IF( .NOT.( WNTQA .OR. WNTQS .OR. WNTQO .OR. WNTQN ) ) THEN
190 INFO = -1
191 ELSE IF( M.LT.0 ) THEN
192 INFO = -2
193 ELSE IF( N.LT.0 ) THEN
194 INFO = -3
195 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
196 INFO = -5
197 ELSE IF( LDU.LT.1 .OR. ( WNTQAS .AND. LDU.LT.M ) .OR.
198 $ ( WNTQO .AND. M.LT.N .AND. LDU.LT.M ) ) THEN
199 INFO = -8
200 ELSE IF( LDVT.LT.1 .OR. ( WNTQA .AND. LDVT.LT.N ) .OR.
201 $ ( WNTQS .AND. LDVT.LT.MINMN ) .OR.
202 $ ( WNTQO .AND. M.GE.N .AND. LDVT.LT.N ) ) THEN
203 INFO = -10
204 END IF
205 *
206 * Compute workspace
207 * (Note: Comments in the code beginning "Workspace:" describe the
208 * minimal amount of workspace needed at that point in the code,
209 * as well as the preferred amount for good performance.
210 * NB refers to the optimal block size for the immediately
211 * following subroutine, as returned by ILAENV.)
212 *
213 IF( INFO.EQ.0 ) THEN
214 MINWRK = 1
215 MAXWRK = 1
216 IF( M.GE.N .AND. MINMN.GT.0 ) THEN
217 *
218 * Compute space needed for DBDSDC
219 *
220 MNTHR = INT( MINMN*11.0D0 / 6.0D0 )
221 IF( WNTQN ) THEN
222 BDSPAC = 7*N
223 ELSE
224 BDSPAC = 3*N*N + 4*N
225 END IF
226 IF( M.GE.MNTHR ) THEN
227 IF( WNTQN ) THEN
228 *
229 * Path 1 (M much larger than N, JOBZ='N')
230 *
231 WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,
232 $ -1 )
233 WRKBL = MAX( WRKBL, 3*N+2*N*
234 $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
235 MAXWRK = MAX( WRKBL, BDSPAC+N )
236 MINWRK = BDSPAC + N
237 ELSE IF( WNTQO ) THEN
238 *
239 * Path 2 (M much larger than N, JOBZ='O')
240 *
241 WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
242 WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
243 $ N, N, -1 ) )
244 WRKBL = MAX( WRKBL, 3*N+2*N*
245 $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
246 WRKBL = MAX( WRKBL, 3*N+N*
247 $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
248 WRKBL = MAX( WRKBL, 3*N+N*
249 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
250 WRKBL = MAX( WRKBL, BDSPAC+3*N )
251 MAXWRK = WRKBL + 2*N*N
252 MINWRK = BDSPAC + 2*N*N + 3*N
253 ELSE IF( WNTQS ) THEN
254 *
255 * Path 3 (M much larger than N, JOBZ='S')
256 *
257 WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
258 WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
259 $ N, N, -1 ) )
260 WRKBL = MAX( WRKBL, 3*N+2*N*
261 $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
262 WRKBL = MAX( WRKBL, 3*N+N*
263 $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
264 WRKBL = MAX( WRKBL, 3*N+N*
265 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
266 WRKBL = MAX( WRKBL, BDSPAC+3*N )
267 MAXWRK = WRKBL + N*N
268 MINWRK = BDSPAC + N*N + 3*N
269 ELSE IF( WNTQA ) THEN
270 *
271 * Path 4 (M much larger than N, JOBZ='A')
272 *
273 WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
274 WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
275 $ M, N, -1 ) )
276 WRKBL = MAX( WRKBL, 3*N+2*N*
277 $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
278 WRKBL = MAX( WRKBL, 3*N+N*
279 $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
280 WRKBL = MAX( WRKBL, 3*N+N*
281 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
282 WRKBL = MAX( WRKBL, BDSPAC+3*N )
283 MAXWRK = WRKBL + N*N
284 MINWRK = BDSPAC + N*N + 3*N
285 END IF
286 ELSE
287 *
288 * Path 5 (M at least N, but not much larger)
289 *
290 WRKBL = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1,
291 $ -1 )
292 IF( WNTQN ) THEN
293 MAXWRK = MAX( WRKBL, BDSPAC+3*N )
294 MINWRK = 3*N + MAX( M, BDSPAC )
295 ELSE IF( WNTQO ) THEN
296 WRKBL = MAX( WRKBL, 3*N+N*
297 $ ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) )
298 WRKBL = MAX( WRKBL, 3*N+N*
299 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
300 WRKBL = MAX( WRKBL, BDSPAC+3*N )
301 MAXWRK = WRKBL + M*N
302 MINWRK = 3*N + MAX( M, N*N+BDSPAC )
303 ELSE IF( WNTQS ) THEN
304 WRKBL = MAX( WRKBL, 3*N+N*
305 $ ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) )
306 WRKBL = MAX( WRKBL, 3*N+N*
307 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
308 MAXWRK = MAX( WRKBL, BDSPAC+3*N )
309 MINWRK = 3*N + MAX( M, BDSPAC )
310 ELSE IF( WNTQA ) THEN
311 WRKBL = MAX( WRKBL, 3*N+M*
312 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
313 WRKBL = MAX( WRKBL, 3*N+N*
314 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
315 MAXWRK = MAX( MAXWRK, BDSPAC+3*N )
316 MINWRK = 3*N + MAX( M, BDSPAC )
317 END IF
318 END IF
319 ELSE IF( MINMN.GT.0 ) THEN
320 *
321 * Compute space needed for DBDSDC
322 *
323 MNTHR = INT( MINMN*11.0D0 / 6.0D0 )
324 IF( WNTQN ) THEN
325 BDSPAC = 7*M
326 ELSE
327 BDSPAC = 3*M*M + 4*M
328 END IF
329 IF( N.GE.MNTHR ) THEN
330 IF( WNTQN ) THEN
331 *
332 * Path 1t (N much larger than M, JOBZ='N')
333 *
334 WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,
335 $ -1 )
336 WRKBL = MAX( WRKBL, 3*M+2*M*
337 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
338 MAXWRK = MAX( WRKBL, BDSPAC+M )
339 MINWRK = BDSPAC + M
340 ELSE IF( WNTQO ) THEN
341 *
342 * Path 2t (N much larger than M, JOBZ='O')
343 *
344 WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
345 WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
346 $ N, M, -1 ) )
347 WRKBL = MAX( WRKBL, 3*M+2*M*
348 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
349 WRKBL = MAX( WRKBL, 3*M+M*
350 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
351 WRKBL = MAX( WRKBL, 3*M+M*
352 $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
353 WRKBL = MAX( WRKBL, BDSPAC+3*M )
354 MAXWRK = WRKBL + 2*M*M
355 MINWRK = BDSPAC + 2*M*M + 3*M
356 ELSE IF( WNTQS ) THEN
357 *
358 * Path 3t (N much larger than M, JOBZ='S')
359 *
360 WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
361 WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
362 $ N, M, -1 ) )
363 WRKBL = MAX( WRKBL, 3*M+2*M*
364 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
365 WRKBL = MAX( WRKBL, 3*M+M*
366 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
367 WRKBL = MAX( WRKBL, 3*M+M*
368 $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
369 WRKBL = MAX( WRKBL, BDSPAC+3*M )
370 MAXWRK = WRKBL + M*M
371 MINWRK = BDSPAC + M*M + 3*M
372 ELSE IF( WNTQA ) THEN
373 *
374 * Path 4t (N much larger than M, JOBZ='A')
375 *
376 WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
377 WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
378 $ N, M, -1 ) )
379 WRKBL = MAX( WRKBL, 3*M+2*M*
380 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
381 WRKBL = MAX( WRKBL, 3*M+M*
382 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
383 WRKBL = MAX( WRKBL, 3*M+M*
384 $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
385 WRKBL = MAX( WRKBL, BDSPAC+3*M )
386 MAXWRK = WRKBL + M*M
387 MINWRK = BDSPAC + M*M + 3*M
388 END IF
389 ELSE
390 *
391 * Path 5t (N greater than M, but not much larger)
392 *
393 WRKBL = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1,
394 $ -1 )
395 IF( WNTQN ) THEN
396 MAXWRK = MAX( WRKBL, BDSPAC+3*M )
397 MINWRK = 3*M + MAX( N, BDSPAC )
398 ELSE IF( WNTQO ) THEN
399 WRKBL = MAX( WRKBL, 3*M+M*
400 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
401 WRKBL = MAX( WRKBL, 3*M+M*
402 $ ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) )
403 WRKBL = MAX( WRKBL, BDSPAC+3*M )
404 MAXWRK = WRKBL + M*N
405 MINWRK = 3*M + MAX( N, M*M+BDSPAC )
406 ELSE IF( WNTQS ) THEN
407 WRKBL = MAX( WRKBL, 3*M+M*
408 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
409 WRKBL = MAX( WRKBL, 3*M+M*
410 $ ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) )
411 MAXWRK = MAX( WRKBL, BDSPAC+3*M )
412 MINWRK = 3*M + MAX( N, BDSPAC )
413 ELSE IF( WNTQA ) THEN
414 WRKBL = MAX( WRKBL, 3*M+M*
415 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
416 WRKBL = MAX( WRKBL, 3*M+M*
417 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, M, -1 ) )
418 MAXWRK = MAX( WRKBL, BDSPAC+3*M )
419 MINWRK = 3*M + MAX( N, BDSPAC )
420 END IF
421 END IF
422 END IF
423 MAXWRK = MAX( MAXWRK, MINWRK )
424 WORK( 1 ) = MAXWRK
425 *
426 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
427 INFO = -12
428 END IF
429 END IF
430 *
431 IF( INFO.NE.0 ) THEN
432 CALL XERBLA( 'DGESDD', -INFO )
433 RETURN
434 ELSE IF( LQUERY ) THEN
435 RETURN
436 END IF
437 *
438 * Quick return if possible
439 *
440 IF( M.EQ.0 .OR. N.EQ.0 ) THEN
441 RETURN
442 END IF
443 *
444 * Get machine constants
445 *
446 EPS = DLAMCH( 'P' )
447 SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
448 BIGNUM = ONE / SMLNUM
449 *
450 * Scale A if max element outside range [SMLNUM,BIGNUM]
451 *
452 ANRM = DLANGE( 'M', M, N, A, LDA, DUM )
453 ISCL = 0
454 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
455 ISCL = 1
456 CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )
457 ELSE IF( ANRM.GT.BIGNUM ) THEN
458 ISCL = 1
459 CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )
460 END IF
461 *
462 IF( M.GE.N ) THEN
463 *
464 * A has at least as many rows as columns. If A has sufficiently
465 * more rows than columns, first reduce using the QR
466 * decomposition (if sufficient workspace available)
467 *
468 IF( M.GE.MNTHR ) THEN
469 *
470 IF( WNTQN ) THEN
471 *
472 * Path 1 (M much larger than N, JOBZ='N')
473 * No singular vectors to be computed
474 *
475 ITAU = 1
476 NWORK = ITAU + N
477 *
478 * Compute A=Q*R
479 * (Workspace: need 2*N, prefer N+N*NB)
480 *
481 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
482 $ LWORK-NWORK+1, IERR )
483 *
484 * Zero out below R
485 *
486 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
487 IE = 1
488 ITAUQ = IE + N
489 ITAUP = ITAUQ + N
490 NWORK = ITAUP + N
491 *
492 * Bidiagonalize R in A
493 * (Workspace: need 4*N, prefer 3*N+2*N*NB)
494 *
495 CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
496 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
497 $ IERR )
498 NWORK = IE + N
499 *
500 * Perform bidiagonal SVD, computing singular values only
501 * (Workspace: need N+BDSPAC)
502 *
503 CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,
504 $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )
505 *
506 ELSE IF( WNTQO ) THEN
507 *
508 * Path 2 (M much larger than N, JOBZ = 'O')
509 * N left singular vectors to be overwritten on A and
510 * N right singular vectors to be computed in VT
511 *
512 IR = 1
513 *
514 * WORK(IR) is LDWRKR by N
515 *
516 IF( LWORK.GE.LDA*N+N*N+3*N+BDSPAC ) THEN
517 LDWRKR = LDA
518 ELSE
519 LDWRKR = ( LWORK-N*N-3*N-BDSPAC ) / N
520 END IF
521 ITAU = IR + LDWRKR*N
522 NWORK = ITAU + N
523 *
524 * Compute A=Q*R
525 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
526 *
527 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
528 $ LWORK-NWORK+1, IERR )
529 *
530 * Copy R to WORK(IR), zeroing out below it
531 *
532 CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
533 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
534 $ LDWRKR )
535 *
536 * Generate Q in A
537 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
538 *
539 CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
540 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
541 IE = ITAU
542 ITAUQ = IE + N
543 ITAUP = ITAUQ + N
544 NWORK = ITAUP + N
545 *
546 * Bidiagonalize R in VT, copying result to WORK(IR)
547 * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
548 *
549 CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
550 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
551 $ LWORK-NWORK+1, IERR )
552 *
553 * WORK(IU) is N by N
554 *
555 IU = NWORK
556 NWORK = IU + N*N
557 *
558 * Perform bidiagonal SVD, computing left singular vectors
559 * of bidiagonal matrix in WORK(IU) and computing right
560 * singular vectors of bidiagonal matrix in VT
561 * (Workspace: need N+N*N+BDSPAC)
562 *
563 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,
564 $ VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
565 $ INFO )
566 *
567 * Overwrite WORK(IU) by left singular vectors of R
568 * and VT by right singular vectors of R
569 * (Workspace: need 2*N*N+3*N, prefer 2*N*N+2*N+N*NB)
570 *
571 CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,
572 $ WORK( ITAUQ ), WORK( IU ), N, WORK( NWORK ),
573 $ LWORK-NWORK+1, IERR )
574 CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,
575 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
576 $ LWORK-NWORK+1, IERR )
577 *
578 * Multiply Q in A by left singular vectors of R in
579 * WORK(IU), storing result in WORK(IR) and copying to A
580 * (Workspace: need 2*N*N, prefer N*N+M*N)
581 *
582 DO 10 I = 1, M, LDWRKR
583 CHUNK = MIN( M-I+1, LDWRKR )
584 CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
585 $ LDA, WORK( IU ), N, ZERO, WORK( IR ),
586 $ LDWRKR )
587 CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,
588 $ A( I, 1 ), LDA )
589 10 CONTINUE
590 *
591 ELSE IF( WNTQS ) THEN
592 *
593 * Path 3 (M much larger than N, JOBZ='S')
594 * N left singular vectors to be computed in U and
595 * N right singular vectors to be computed in VT
596 *
597 IR = 1
598 *
599 * WORK(IR) is N by N
600 *
601 LDWRKR = N
602 ITAU = IR + LDWRKR*N
603 NWORK = ITAU + N
604 *
605 * Compute A=Q*R
606 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
607 *
608 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
609 $ LWORK-NWORK+1, IERR )
610 *
611 * Copy R to WORK(IR), zeroing out below it
612 *
613 CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
614 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
615 $ LDWRKR )
616 *
617 * Generate Q in A
618 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
619 *
620 CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
621 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
622 IE = ITAU
623 ITAUQ = IE + N
624 ITAUP = ITAUQ + N
625 NWORK = ITAUP + N
626 *
627 * Bidiagonalize R in WORK(IR)
628 * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
629 *
630 CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
631 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
632 $ LWORK-NWORK+1, IERR )
633 *
634 * Perform bidiagonal SVD, computing left singular vectors
635 * of bidiagoal matrix in U and computing right singular
636 * vectors of bidiagonal matrix in VT
637 * (Workspace: need N+BDSPAC)
638 *
639 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
640 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
641 $ INFO )
642 *
643 * Overwrite U by left singular vectors of R and VT
644 * by right singular vectors of R
645 * (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)
646 *
647 CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,
648 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
649 $ LWORK-NWORK+1, IERR )
650 *
651 CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,
652 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
653 $ LWORK-NWORK+1, IERR )
654 *
655 * Multiply Q in A by left singular vectors of R in
656 * WORK(IR), storing result in U
657 * (Workspace: need N*N)
658 *
659 CALL DLACPY( 'F', N, N, U, LDU, WORK( IR ), LDWRKR )
660 CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA, WORK( IR ),
661 $ LDWRKR, ZERO, U, LDU )
662 *
663 ELSE IF( WNTQA ) THEN
664 *
665 * Path 4 (M much larger than N, JOBZ='A')
666 * M left singular vectors to be computed in U and
667 * N right singular vectors to be computed in VT
668 *
669 IU = 1
670 *
671 * WORK(IU) is N by N
672 *
673 LDWRKU = N
674 ITAU = IU + LDWRKU*N
675 NWORK = ITAU + N
676 *
677 * Compute A=Q*R, copying result to U
678 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
679 *
680 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
681 $ LWORK-NWORK+1, IERR )
682 CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
683 *
684 * Generate Q in U
685 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
686 CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
687 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
688 *
689 * Produce R in A, zeroing out other entries
690 *
691 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
692 IE = ITAU
693 ITAUQ = IE + N
694 ITAUP = ITAUQ + N
695 NWORK = ITAUP + N
696 *
697 * Bidiagonalize R in A
698 * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
699 *
700 CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
701 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
702 $ IERR )
703 *
704 * Perform bidiagonal SVD, computing left singular vectors
705 * of bidiagonal matrix in WORK(IU) and computing right
706 * singular vectors of bidiagonal matrix in VT
707 * (Workspace: need N+N*N+BDSPAC)
708 *
709 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,
710 $ VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
711 $ INFO )
712 *
713 * Overwrite WORK(IU) by left singular vectors of R and VT
714 * by right singular vectors of R
715 * (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)
716 *
717 CALL DORMBR( 'Q', 'L', 'N', N, N, N, A, LDA,
718 $ WORK( ITAUQ ), WORK( IU ), LDWRKU,
719 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
720 CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
721 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
722 $ LWORK-NWORK+1, IERR )
723 *
724 * Multiply Q in U by left singular vectors of R in
725 * WORK(IU), storing result in A
726 * (Workspace: need N*N)
727 *
728 CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU, WORK( IU ),
729 $ LDWRKU, ZERO, A, LDA )
730 *
731 * Copy left singular vectors of A from A to U
732 *
733 CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
734 *
735 END IF
736 *
737 ELSE
738 *
739 * M .LT. MNTHR
740 *
741 * Path 5 (M at least N, but not much larger)
742 * Reduce to bidiagonal form without QR decomposition
743 *
744 IE = 1
745 ITAUQ = IE + N
746 ITAUP = ITAUQ + N
747 NWORK = ITAUP + N
748 *
749 * Bidiagonalize A
750 * (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)
751 *
752 CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
753 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
754 $ IERR )
755 IF( WNTQN ) THEN
756 *
757 * Perform bidiagonal SVD, only computing singular values
758 * (Workspace: need N+BDSPAC)
759 *
760 CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,
761 $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )
762 ELSE IF( WNTQO ) THEN
763 IU = NWORK
764 IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN
765 *
766 * WORK( IU ) is M by N
767 *
768 LDWRKU = M
769 NWORK = IU + LDWRKU*N
770 CALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IU ),
771 $ LDWRKU )
772 ELSE
773 *
774 * WORK( IU ) is N by N
775 *
776 LDWRKU = N
777 NWORK = IU + LDWRKU*N
778 *
779 * WORK(IR) is LDWRKR by N
780 *
781 IR = NWORK
782 LDWRKR = ( LWORK-N*N-3*N ) / N
783 END IF
784 NWORK = IU + LDWRKU*N
785 *
786 * Perform bidiagonal SVD, computing left singular vectors
787 * of bidiagonal matrix in WORK(IU) and computing right
788 * singular vectors of bidiagonal matrix in VT
789 * (Workspace: need N+N*N+BDSPAC)
790 *
791 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ),
792 $ LDWRKU, VT, LDVT, DUM, IDUM, WORK( NWORK ),
793 $ IWORK, INFO )
794 *
795 * Overwrite VT by right singular vectors of A
796 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
797 *
798 CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
799 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
800 $ LWORK-NWORK+1, IERR )
801 *
802 IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN
803 *
804 * Overwrite WORK(IU) by left singular vectors of A
805 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
806 *
807 CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,
808 $ WORK( ITAUQ ), WORK( IU ), LDWRKU,
809 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
810 *
811 * Copy left singular vectors of A from WORK(IU) to A
812 *
813 CALL DLACPY( 'F', M, N, WORK( IU ), LDWRKU, A, LDA )
814 ELSE
815 *
816 * Generate Q in A
817 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
818 *
819 CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
820 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
821 *
822 * Multiply Q in A by left singular vectors of
823 * bidiagonal matrix in WORK(IU), storing result in
824 * WORK(IR) and copying to A
825 * (Workspace: need 2*N*N, prefer N*N+M*N)
826 *
827 DO 20 I = 1, M, LDWRKR
828 CHUNK = MIN( M-I+1, LDWRKR )
829 CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
830 $ LDA, WORK( IU ), LDWRKU, ZERO,
831 $ WORK( IR ), LDWRKR )
832 CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,
833 $ A( I, 1 ), LDA )
834 20 CONTINUE
835 END IF
836 *
837 ELSE IF( WNTQS ) THEN
838 *
839 * Perform bidiagonal SVD, computing left singular vectors
840 * of bidiagonal matrix in U and computing right singular
841 * vectors of bidiagonal matrix in VT
842 * (Workspace: need N+BDSPAC)
843 *
844 CALL DLASET( 'F', M, N, ZERO, ZERO, U, LDU )
845 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
846 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
847 $ INFO )
848 *
849 * Overwrite U by left singular vectors of A and VT
850 * by right singular vectors of A
851 * (Workspace: need 3*N, prefer 2*N+N*NB)
852 *
853 CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,
854 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
855 $ LWORK-NWORK+1, IERR )
856 CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
857 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
858 $ LWORK-NWORK+1, IERR )
859 ELSE IF( WNTQA ) THEN
860 *
861 * Perform bidiagonal SVD, computing left singular vectors
862 * of bidiagonal matrix in U and computing right singular
863 * vectors of bidiagonal matrix in VT
864 * (Workspace: need N+BDSPAC)
865 *
866 CALL DLASET( 'F', M, M, ZERO, ZERO, U, LDU )
867 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
868 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
869 $ INFO )
870 *
871 * Set the right corner of U to identity matrix
872 *
873 IF( M.GT.N ) THEN
874 CALL DLASET( 'F', M-N, M-N, ZERO, ONE, U( N+1, N+1 ),
875 $ LDU )
876 END IF
877 *
878 * Overwrite U by left singular vectors of A and VT
879 * by right singular vectors of A
880 * (Workspace: need N*N+2*N+M, prefer N*N+2*N+M*NB)
881 *
882 CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
883 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
884 $ LWORK-NWORK+1, IERR )
885 CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA,
886 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
887 $ LWORK-NWORK+1, IERR )
888 END IF
889 *
890 END IF
891 *
892 ELSE
893 *
894 * A has more columns than rows. If A has sufficiently more
895 * columns than rows, first reduce using the LQ decomposition (if
896 * sufficient workspace available)
897 *
898 IF( N.GE.MNTHR ) THEN
899 *
900 IF( WNTQN ) THEN
901 *
902 * Path 1t (N much larger than M, JOBZ='N')
903 * No singular vectors to be computed
904 *
905 ITAU = 1
906 NWORK = ITAU + M
907 *
908 * Compute A=L*Q
909 * (Workspace: need 2*M, prefer M+M*NB)
910 *
911 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
912 $ LWORK-NWORK+1, IERR )
913 *
914 * Zero out above L
915 *
916 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
917 IE = 1
918 ITAUQ = IE + M
919 ITAUP = ITAUQ + M
920 NWORK = ITAUP + M
921 *
922 * Bidiagonalize L in A
923 * (Workspace: need 4*M, prefer 3*M+2*M*NB)
924 *
925 CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
926 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
927 $ IERR )
928 NWORK = IE + M
929 *
930 * Perform bidiagonal SVD, computing singular values only
931 * (Workspace: need M+BDSPAC)
932 *
933 CALL DBDSDC( 'U', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,
934 $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )
935 *
936 ELSE IF( WNTQO ) THEN
937 *
938 * Path 2t (N much larger than M, JOBZ='O')
939 * M right singular vectors to be overwritten on A and
940 * M left singular vectors to be computed in U
941 *
942 IVT = 1
943 *
944 * IVT is M by M
945 *
946 IL = IVT + M*M
947 IF( LWORK.GE.M*N+M*M+3*M+BDSPAC ) THEN
948 *
949 * WORK(IL) is M by N
950 *
951 LDWRKL = M
952 CHUNK = N
953 ELSE
954 LDWRKL = M
955 CHUNK = ( LWORK-M*M ) / M
956 END IF
957 ITAU = IL + LDWRKL*M
958 NWORK = ITAU + M
959 *
960 * Compute A=L*Q
961 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
962 *
963 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
964 $ LWORK-NWORK+1, IERR )
965 *
966 * Copy L to WORK(IL), zeroing about above it
967 *
968 CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )
969 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
970 $ WORK( IL+LDWRKL ), LDWRKL )
971 *
972 * Generate Q in A
973 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
974 *
975 CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
976 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
977 IE = ITAU
978 ITAUQ = IE + M
979 ITAUP = ITAUQ + M
980 NWORK = ITAUP + M
981 *
982 * Bidiagonalize L in WORK(IL)
983 * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
984 *
985 CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),
986 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
987 $ LWORK-NWORK+1, IERR )
988 *
989 * Perform bidiagonal SVD, computing left singular vectors
990 * of bidiagonal matrix in U, and computing right singular
991 * vectors of bidiagonal matrix in WORK(IVT)
992 * (Workspace: need M+M*M+BDSPAC)
993 *
994 CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,
995 $ WORK( IVT ), M, DUM, IDUM, WORK( NWORK ),
996 $ IWORK, INFO )
997 *
998 * Overwrite U by left singular vectors of L and WORK(IVT)
999 * by right singular vectors of L
1000 * (Workspace: need 2*M*M+3*M, prefer 2*M*M+2*M+M*NB)
1001 *
1002 CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,
1003 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1004 $ LWORK-NWORK+1, IERR )
1005 CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,
1006 $ WORK( ITAUP ), WORK( IVT ), M,
1007 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1008 *
1009 * Multiply right singular vectors of L in WORK(IVT) by Q
1010 * in A, storing result in WORK(IL) and copying to A
1011 * (Workspace: need 2*M*M, prefer M*M+M*N)
1012 *
1013 DO 30 I = 1, N, CHUNK
1014 BLK = MIN( N-I+1, CHUNK )
1015 CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ), M,
1016 $ A( 1, I ), LDA, ZERO, WORK( IL ), LDWRKL )
1017 CALL DLACPY( 'F', M, BLK, WORK( IL ), LDWRKL,
1018 $ A( 1, I ), LDA )
1019 30 CONTINUE
1020 *
1021 ELSE IF( WNTQS ) THEN
1022 *
1023 * Path 3t (N much larger than M, JOBZ='S')
1024 * M right singular vectors to be computed in VT and
1025 * M left singular vectors to be computed in U
1026 *
1027 IL = 1
1028 *
1029 * WORK(IL) is M by M
1030 *
1031 LDWRKL = M
1032 ITAU = IL + LDWRKL*M
1033 NWORK = ITAU + M
1034 *
1035 * Compute A=L*Q
1036 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1037 *
1038 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
1039 $ LWORK-NWORK+1, IERR )
1040 *
1041 * Copy L to WORK(IL), zeroing out above it
1042 *
1043 CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )
1044 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
1045 $ WORK( IL+LDWRKL ), LDWRKL )
1046 *
1047 * Generate Q in A
1048 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1049 *
1050 CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
1051 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1052 IE = ITAU
1053 ITAUQ = IE + M
1054 ITAUP = ITAUQ + M
1055 NWORK = ITAUP + M
1056 *
1057 * Bidiagonalize L in WORK(IU), copying result to U
1058 * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
1059 *
1060 CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),
1061 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
1062 $ LWORK-NWORK+1, IERR )
1063 *
1064 * Perform bidiagonal SVD, computing left singular vectors
1065 * of bidiagonal matrix in U and computing right singular
1066 * vectors of bidiagonal matrix in VT
1067 * (Workspace: need M+BDSPAC)
1068 *
1069 CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU, VT,
1070 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
1071 $ INFO )
1072 *
1073 * Overwrite U by left singular vectors of L and VT
1074 * by right singular vectors of L
1075 * (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)
1076 *
1077 CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,
1078 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1079 $ LWORK-NWORK+1, IERR )
1080 CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,
1081 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
1082 $ LWORK-NWORK+1, IERR )
1083 *
1084 * Multiply right singular vectors of L in WORK(IL) by
1085 * Q in A, storing result in VT
1086 * (Workspace: need M*M)
1087 *
1088 CALL DLACPY( 'F', M, M, VT, LDVT, WORK( IL ), LDWRKL )
1089 CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IL ), LDWRKL,
1090 $ A, LDA, ZERO, VT, LDVT )
1091 *
1092 ELSE IF( WNTQA ) THEN
1093 *
1094 * Path 4t (N much larger than M, JOBZ='A')
1095 * N right singular vectors to be computed in VT and
1096 * M left singular vectors to be computed in U
1097 *
1098 IVT = 1
1099 *
1100 * WORK(IVT) is M by M
1101 *
1102 LDWKVT = M
1103 ITAU = IVT + LDWKVT*M
1104 NWORK = ITAU + M
1105 *
1106 * Compute A=L*Q, copying result to VT
1107 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1108 *
1109 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
1110 $ LWORK-NWORK+1, IERR )
1111 CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
1112 *
1113 * Generate Q in VT
1114 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1115 *
1116 CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
1117 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1118 *
1119 * Produce L in A, zeroing out other entries
1120 *
1121 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
1122 IE = ITAU
1123 ITAUQ = IE + M
1124 ITAUP = ITAUQ + M
1125 NWORK = ITAUP + M
1126 *
1127 * Bidiagonalize L in A
1128 * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
1129 *
1130 CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
1131 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
1132 $ IERR )
1133 *
1134 * Perform bidiagonal SVD, computing left singular vectors
1135 * of bidiagonal matrix in U and computing right singular
1136 * vectors of bidiagonal matrix in WORK(IVT)
1137 * (Workspace: need M+M*M+BDSPAC)
1138 *
1139 CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,
1140 $ WORK( IVT ), LDWKVT, DUM, IDUM,
1141 $ WORK( NWORK ), IWORK, INFO )
1142 *
1143 * Overwrite U by left singular vectors of L and WORK(IVT)
1144 * by right singular vectors of L
1145 * (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)
1146 *
1147 CALL DORMBR( 'Q', 'L', 'N', M, M, M, A, LDA,
1148 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1149 $ LWORK-NWORK+1, IERR )
1150 CALL DORMBR( 'P', 'R', 'T', M, M, M, A, LDA,
1151 $ WORK( ITAUP ), WORK( IVT ), LDWKVT,
1152 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1153 *
1154 * Multiply right singular vectors of L in WORK(IVT) by
1155 * Q in VT, storing result in A
1156 * (Workspace: need M*M)
1157 *
1158 CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IVT ), LDWKVT,
1159 $ VT, LDVT, ZERO, A, LDA )
1160 *
1161 * Copy right singular vectors of A from A to VT
1162 *
1163 CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
1164 *
1165 END IF
1166 *
1167 ELSE
1168 *
1169 * N .LT. MNTHR
1170 *
1171 * Path 5t (N greater than M, but not much larger)
1172 * Reduce to bidiagonal form without LQ decomposition
1173 *
1174 IE = 1
1175 ITAUQ = IE + M
1176 ITAUP = ITAUQ + M
1177 NWORK = ITAUP + M
1178 *
1179 * Bidiagonalize A
1180 * (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
1181 *
1182 CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
1183 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
1184 $ IERR )
1185 IF( WNTQN ) THEN
1186 *
1187 * Perform bidiagonal SVD, only computing singular values
1188 * (Workspace: need M+BDSPAC)
1189 *
1190 CALL DBDSDC( 'L', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,
1191 $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )
1192 ELSE IF( WNTQO ) THEN
1193 LDWKVT = M
1194 IVT = NWORK
1195 IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN
1196 *
1197 * WORK( IVT ) is M by N
1198 *
1199 CALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IVT ),
1200 $ LDWKVT )
1201 NWORK = IVT + LDWKVT*N
1202 ELSE
1203 *
1204 * WORK( IVT ) is M by M
1205 *
1206 NWORK = IVT + LDWKVT*M
1207 IL = NWORK
1208 *
1209 * WORK(IL) is M by CHUNK
1210 *
1211 CHUNK = ( LWORK-M*M-3*M ) / M
1212 END IF
1213 *
1214 * Perform bidiagonal SVD, computing left singular vectors
1215 * of bidiagonal matrix in U and computing right singular
1216 * vectors of bidiagonal matrix in WORK(IVT)
1217 * (Workspace: need M*M+BDSPAC)
1218 *
1219 CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU,
1220 $ WORK( IVT ), LDWKVT, DUM, IDUM,
1221 $ WORK( NWORK ), IWORK, INFO )
1222 *
1223 * Overwrite U by left singular vectors of A
1224 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1225 *
1226 CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
1227 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1228 $ LWORK-NWORK+1, IERR )
1229 *
1230 IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN
1231 *
1232 * Overwrite WORK(IVT) by left singular vectors of A
1233 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1234 *
1235 CALL DORMBR( 'P', 'R', 'T', M, N, M, A, LDA,
1236 $ WORK( ITAUP ), WORK( IVT ), LDWKVT,
1237 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1238 *
1239 * Copy right singular vectors of A from WORK(IVT) to A
1240 *
1241 CALL DLACPY( 'F', M, N, WORK( IVT ), LDWKVT, A, LDA )
1242 ELSE
1243 *
1244 * Generate P**T in A
1245 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1246 *
1247 CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
1248 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1249 *
1250 * Multiply Q in A by right singular vectors of
1251 * bidiagonal matrix in WORK(IVT), storing result in
1252 * WORK(IL) and copying to A
1253 * (Workspace: need 2*M*M, prefer M*M+M*N)
1254 *
1255 DO 40 I = 1, N, CHUNK
1256 BLK = MIN( N-I+1, CHUNK )
1257 CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ),
1258 $ LDWKVT, A( 1, I ), LDA, ZERO,
1259 $ WORK( IL ), M )
1260 CALL DLACPY( 'F', M, BLK, WORK( IL ), M, A( 1, I ),
1261 $ LDA )
1262 40 CONTINUE
1263 END IF
1264 ELSE IF( WNTQS ) THEN
1265 *
1266 * Perform bidiagonal SVD, computing left singular vectors
1267 * of bidiagonal matrix in U and computing right singular
1268 * vectors of bidiagonal matrix in VT
1269 * (Workspace: need M+BDSPAC)
1270 *
1271 CALL DLASET( 'F', M, N, ZERO, ZERO, VT, LDVT )
1272 CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,
1273 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
1274 $ INFO )
1275 *
1276 * Overwrite U by left singular vectors of A and VT
1277 * by right singular vectors of A
1278 * (Workspace: need 3*M, prefer 2*M+M*NB)
1279 *
1280 CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
1281 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1282 $ LWORK-NWORK+1, IERR )
1283 CALL DORMBR( 'P', 'R', 'T', M, N, M, A, LDA,
1284 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
1285 $ LWORK-NWORK+1, IERR )
1286 ELSE IF( WNTQA ) THEN
1287 *
1288 * Perform bidiagonal SVD, computing left singular vectors
1289 * of bidiagonal matrix in U and computing right singular
1290 * vectors of bidiagonal matrix in VT
1291 * (Workspace: need M+BDSPAC)
1292 *
1293 CALL DLASET( 'F', N, N, ZERO, ZERO, VT, LDVT )
1294 CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,
1295 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
1296 $ INFO )
1297 *
1298 * Set the right corner of VT to identity matrix
1299 *
1300 IF( N.GT.M ) THEN
1301 CALL DLASET( 'F', N-M, N-M, ZERO, ONE, VT( M+1, M+1 ),
1302 $ LDVT )
1303 END IF
1304 *
1305 * Overwrite U by left singular vectors of A and VT
1306 * by right singular vectors of A
1307 * (Workspace: need 2*M+N, prefer 2*M+N*NB)
1308 *
1309 CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
1310 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1311 $ LWORK-NWORK+1, IERR )
1312 CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA,
1313 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
1314 $ LWORK-NWORK+1, IERR )
1315 END IF
1316 *
1317 END IF
1318 *
1319 END IF
1320 *
1321 * Undo scaling if necessary
1322 *
1323 IF( ISCL.EQ.1 ) THEN
1324 IF( ANRM.GT.BIGNUM )
1325 $ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
1326 $ IERR )
1327 IF( ANRM.LT.SMLNUM )
1328 $ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
1329 $ IERR )
1330 END IF
1331 *
1332 * Return optimal workspace in WORK(1)
1333 *
1334 WORK( 1 ) = MAXWRK
1335 *
1336 RETURN
1337 *
1338 * End of DGESDD
1339 *
1340 END
2 $ LWORK, IWORK, INFO )
3 *
4 * -- LAPACK driver routine (version 3.2.1) --
5 * -- LAPACK is a software package provided by Univ. of Tennessee, --
6 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
7 * March 2009
8 *
9 * .. Scalar Arguments ..
10 CHARACTER JOBZ
11 INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N
12 * ..
13 * .. Array Arguments ..
14 INTEGER IWORK( * )
15 DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),
16 $ VT( LDVT, * ), WORK( * )
17 * ..
18 *
19 * Purpose
20 * =======
21 *
22 * DGESDD computes the singular value decomposition (SVD) of a real
23 * M-by-N matrix A, optionally computing the left and right singular
24 * vectors. If singular vectors are desired, it uses a
25 * divide-and-conquer algorithm.
26 *
27 * The SVD is written
28 *
29 * A = U * SIGMA * transpose(V)
30 *
31 * where SIGMA is an M-by-N matrix which is zero except for its
32 * min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
33 * V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
34 * are the singular values of A; they are real and non-negative, and
35 * are returned in descending order. The first min(m,n) columns of
36 * U and V are the left and right singular vectors of A.
37 *
38 * Note that the routine returns VT = V**T, not V.
39 *
40 * The divide and conquer algorithm makes very mild assumptions about
41 * floating point arithmetic. It will work on machines with a guard
42 * digit in add/subtract, or on those binary machines without guard
43 * digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
44 * Cray-2. It could conceivably fail on hexadecimal or decimal machines
45 * without guard digits, but we know of none.
46 *
47 * Arguments
48 * =========
49 *
50 * JOBZ (input) CHARACTER*1
51 * Specifies options for computing all or part of the matrix U:
52 * = 'A': all M columns of U and all N rows of V**T are
53 * returned in the arrays U and VT;
54 * = 'S': the first min(M,N) columns of U and the first
55 * min(M,N) rows of V**T are returned in the arrays U
56 * and VT;
57 * = 'O': If M >= N, the first N columns of U are overwritten
58 * on the array A and all rows of V**T are returned in
59 * the array VT;
60 * otherwise, all columns of U are returned in the
61 * array U and the first M rows of V**T are overwritten
62 * in the array A;
63 * = 'N': no columns of U or rows of V**T are computed.
64 *
65 * M (input) INTEGER
66 * The number of rows of the input matrix A. M >= 0.
67 *
68 * N (input) INTEGER
69 * The number of columns of the input matrix A. N >= 0.
70 *
71 * A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
72 * On entry, the M-by-N matrix A.
73 * On exit,
74 * if JOBZ = 'O', A is overwritten with the first N columns
75 * of U (the left singular vectors, stored
76 * columnwise) if M >= N;
77 * A is overwritten with the first M rows
78 * of V**T (the right singular vectors, stored
79 * rowwise) otherwise.
80 * if JOBZ .ne. 'O', the contents of A are destroyed.
81 *
82 * LDA (input) INTEGER
83 * The leading dimension of the array A. LDA >= max(1,M).
84 *
85 * S (output) DOUBLE PRECISION array, dimension (min(M,N))
86 * The singular values of A, sorted so that S(i) >= S(i+1).
87 *
88 * U (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
89 * UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;
90 * UCOL = min(M,N) if JOBZ = 'S'.
91 * If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M
92 * orthogonal matrix U;
93 * if JOBZ = 'S', U contains the first min(M,N) columns of U
94 * (the left singular vectors, stored columnwise);
95 * if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.
96 *
97 * LDU (input) INTEGER
98 * The leading dimension of the array U. LDU >= 1; if
99 * JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.
100 *
101 * VT (output) DOUBLE PRECISION array, dimension (LDVT,N)
102 * If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
103 * N-by-N orthogonal matrix V**T;
104 * if JOBZ = 'S', VT contains the first min(M,N) rows of
105 * V**T (the right singular vectors, stored rowwise);
106 * if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.
107 *
108 * LDVT (input) INTEGER
109 * The leading dimension of the array VT. LDVT >= 1; if
110 * JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N;
111 * if JOBZ = 'S', LDVT >= min(M,N).
112 *
113 * WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
114 * On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
115 *
116 * LWORK (input) INTEGER
117 * The dimension of the array WORK. LWORK >= 1.
118 * If JOBZ = 'N',
119 * LWORK >= 3*min(M,N) + max(max(M,N),7*min(M,N)).
120 * If JOBZ = 'O',
121 * LWORK >= 3*min(M,N) +
122 * max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)).
123 * If JOBZ = 'S' or 'A'
124 * LWORK >= 3*min(M,N) +
125 * max(max(M,N),4*min(M,N)*min(M,N)+4*min(M,N)).
126 * For good performance, LWORK should generally be larger.
127 * If LWORK = -1 but other input arguments are legal, WORK(1)
128 * returns the optimal LWORK.
129 *
130 * IWORK (workspace) INTEGER array, dimension (8*min(M,N))
131 *
132 * INFO (output) INTEGER
133 * = 0: successful exit.
134 * < 0: if INFO = -i, the i-th argument had an illegal value.
135 * > 0: DBDSDC did not converge, updating process failed.
136 *
137 * Further Details
138 * ===============
139 *
140 * Based on contributions by
141 * Ming Gu and Huan Ren, Computer Science Division, University of
142 * California at Berkeley, USA
143 *
144 * =====================================================================
145 *
146 * .. Parameters ..
147 DOUBLE PRECISION ZERO, ONE
148 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
149 * ..
150 * .. Local Scalars ..
151 LOGICAL LQUERY, WNTQA, WNTQAS, WNTQN, WNTQO, WNTQS
152 INTEGER BDSPAC, BLK, CHUNK, I, IE, IERR, IL,
153 $ IR, ISCL, ITAU, ITAUP, ITAUQ, IU, IVT, LDWKVT,
154 $ LDWRKL, LDWRKR, LDWRKU, MAXWRK, MINMN, MINWRK,
155 $ MNTHR, NWORK, WRKBL
156 DOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM
157 * ..
158 * .. Local Arrays ..
159 INTEGER IDUM( 1 )
160 DOUBLE PRECISION DUM( 1 )
161 * ..
162 * .. External Subroutines ..
163 EXTERNAL DBDSDC, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY,
164 $ DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR,
165 $ XERBLA
166 * ..
167 * .. External Functions ..
168 LOGICAL LSAME
169 INTEGER ILAENV
170 DOUBLE PRECISION DLAMCH, DLANGE
171 EXTERNAL DLAMCH, DLANGE, ILAENV, LSAME
172 * ..
173 * .. Intrinsic Functions ..
174 INTRINSIC INT, MAX, MIN, SQRT
175 * ..
176 * .. Executable Statements ..
177 *
178 * Test the input arguments
179 *
180 INFO = 0
181 MINMN = MIN( M, N )
182 WNTQA = LSAME( JOBZ, 'A' )
183 WNTQS = LSAME( JOBZ, 'S' )
184 WNTQAS = WNTQA .OR. WNTQS
185 WNTQO = LSAME( JOBZ, 'O' )
186 WNTQN = LSAME( JOBZ, 'N' )
187 LQUERY = ( LWORK.EQ.-1 )
188 *
189 IF( .NOT.( WNTQA .OR. WNTQS .OR. WNTQO .OR. WNTQN ) ) THEN
190 INFO = -1
191 ELSE IF( M.LT.0 ) THEN
192 INFO = -2
193 ELSE IF( N.LT.0 ) THEN
194 INFO = -3
195 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
196 INFO = -5
197 ELSE IF( LDU.LT.1 .OR. ( WNTQAS .AND. LDU.LT.M ) .OR.
198 $ ( WNTQO .AND. M.LT.N .AND. LDU.LT.M ) ) THEN
199 INFO = -8
200 ELSE IF( LDVT.LT.1 .OR. ( WNTQA .AND. LDVT.LT.N ) .OR.
201 $ ( WNTQS .AND. LDVT.LT.MINMN ) .OR.
202 $ ( WNTQO .AND. M.GE.N .AND. LDVT.LT.N ) ) THEN
203 INFO = -10
204 END IF
205 *
206 * Compute workspace
207 * (Note: Comments in the code beginning "Workspace:" describe the
208 * minimal amount of workspace needed at that point in the code,
209 * as well as the preferred amount for good performance.
210 * NB refers to the optimal block size for the immediately
211 * following subroutine, as returned by ILAENV.)
212 *
213 IF( INFO.EQ.0 ) THEN
214 MINWRK = 1
215 MAXWRK = 1
216 IF( M.GE.N .AND. MINMN.GT.0 ) THEN
217 *
218 * Compute space needed for DBDSDC
219 *
220 MNTHR = INT( MINMN*11.0D0 / 6.0D0 )
221 IF( WNTQN ) THEN
222 BDSPAC = 7*N
223 ELSE
224 BDSPAC = 3*N*N + 4*N
225 END IF
226 IF( M.GE.MNTHR ) THEN
227 IF( WNTQN ) THEN
228 *
229 * Path 1 (M much larger than N, JOBZ='N')
230 *
231 WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,
232 $ -1 )
233 WRKBL = MAX( WRKBL, 3*N+2*N*
234 $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
235 MAXWRK = MAX( WRKBL, BDSPAC+N )
236 MINWRK = BDSPAC + N
237 ELSE IF( WNTQO ) THEN
238 *
239 * Path 2 (M much larger than N, JOBZ='O')
240 *
241 WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
242 WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
243 $ N, N, -1 ) )
244 WRKBL = MAX( WRKBL, 3*N+2*N*
245 $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
246 WRKBL = MAX( WRKBL, 3*N+N*
247 $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
248 WRKBL = MAX( WRKBL, 3*N+N*
249 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
250 WRKBL = MAX( WRKBL, BDSPAC+3*N )
251 MAXWRK = WRKBL + 2*N*N
252 MINWRK = BDSPAC + 2*N*N + 3*N
253 ELSE IF( WNTQS ) THEN
254 *
255 * Path 3 (M much larger than N, JOBZ='S')
256 *
257 WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
258 WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
259 $ N, N, -1 ) )
260 WRKBL = MAX( WRKBL, 3*N+2*N*
261 $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
262 WRKBL = MAX( WRKBL, 3*N+N*
263 $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
264 WRKBL = MAX( WRKBL, 3*N+N*
265 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
266 WRKBL = MAX( WRKBL, BDSPAC+3*N )
267 MAXWRK = WRKBL + N*N
268 MINWRK = BDSPAC + N*N + 3*N
269 ELSE IF( WNTQA ) THEN
270 *
271 * Path 4 (M much larger than N, JOBZ='A')
272 *
273 WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
274 WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
275 $ M, N, -1 ) )
276 WRKBL = MAX( WRKBL, 3*N+2*N*
277 $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
278 WRKBL = MAX( WRKBL, 3*N+N*
279 $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
280 WRKBL = MAX( WRKBL, 3*N+N*
281 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
282 WRKBL = MAX( WRKBL, BDSPAC+3*N )
283 MAXWRK = WRKBL + N*N
284 MINWRK = BDSPAC + N*N + 3*N
285 END IF
286 ELSE
287 *
288 * Path 5 (M at least N, but not much larger)
289 *
290 WRKBL = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1,
291 $ -1 )
292 IF( WNTQN ) THEN
293 MAXWRK = MAX( WRKBL, BDSPAC+3*N )
294 MINWRK = 3*N + MAX( M, BDSPAC )
295 ELSE IF( WNTQO ) THEN
296 WRKBL = MAX( WRKBL, 3*N+N*
297 $ ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) )
298 WRKBL = MAX( WRKBL, 3*N+N*
299 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
300 WRKBL = MAX( WRKBL, BDSPAC+3*N )
301 MAXWRK = WRKBL + M*N
302 MINWRK = 3*N + MAX( M, N*N+BDSPAC )
303 ELSE IF( WNTQS ) THEN
304 WRKBL = MAX( WRKBL, 3*N+N*
305 $ ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) )
306 WRKBL = MAX( WRKBL, 3*N+N*
307 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
308 MAXWRK = MAX( WRKBL, BDSPAC+3*N )
309 MINWRK = 3*N + MAX( M, BDSPAC )
310 ELSE IF( WNTQA ) THEN
311 WRKBL = MAX( WRKBL, 3*N+M*
312 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
313 WRKBL = MAX( WRKBL, 3*N+N*
314 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
315 MAXWRK = MAX( MAXWRK, BDSPAC+3*N )
316 MINWRK = 3*N + MAX( M, BDSPAC )
317 END IF
318 END IF
319 ELSE IF( MINMN.GT.0 ) THEN
320 *
321 * Compute space needed for DBDSDC
322 *
323 MNTHR = INT( MINMN*11.0D0 / 6.0D0 )
324 IF( WNTQN ) THEN
325 BDSPAC = 7*M
326 ELSE
327 BDSPAC = 3*M*M + 4*M
328 END IF
329 IF( N.GE.MNTHR ) THEN
330 IF( WNTQN ) THEN
331 *
332 * Path 1t (N much larger than M, JOBZ='N')
333 *
334 WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,
335 $ -1 )
336 WRKBL = MAX( WRKBL, 3*M+2*M*
337 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
338 MAXWRK = MAX( WRKBL, BDSPAC+M )
339 MINWRK = BDSPAC + M
340 ELSE IF( WNTQO ) THEN
341 *
342 * Path 2t (N much larger than M, JOBZ='O')
343 *
344 WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
345 WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
346 $ N, M, -1 ) )
347 WRKBL = MAX( WRKBL, 3*M+2*M*
348 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
349 WRKBL = MAX( WRKBL, 3*M+M*
350 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
351 WRKBL = MAX( WRKBL, 3*M+M*
352 $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
353 WRKBL = MAX( WRKBL, BDSPAC+3*M )
354 MAXWRK = WRKBL + 2*M*M
355 MINWRK = BDSPAC + 2*M*M + 3*M
356 ELSE IF( WNTQS ) THEN
357 *
358 * Path 3t (N much larger than M, JOBZ='S')
359 *
360 WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
361 WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
362 $ N, M, -1 ) )
363 WRKBL = MAX( WRKBL, 3*M+2*M*
364 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
365 WRKBL = MAX( WRKBL, 3*M+M*
366 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
367 WRKBL = MAX( WRKBL, 3*M+M*
368 $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
369 WRKBL = MAX( WRKBL, BDSPAC+3*M )
370 MAXWRK = WRKBL + M*M
371 MINWRK = BDSPAC + M*M + 3*M
372 ELSE IF( WNTQA ) THEN
373 *
374 * Path 4t (N much larger than M, JOBZ='A')
375 *
376 WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
377 WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
378 $ N, M, -1 ) )
379 WRKBL = MAX( WRKBL, 3*M+2*M*
380 $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
381 WRKBL = MAX( WRKBL, 3*M+M*
382 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
383 WRKBL = MAX( WRKBL, 3*M+M*
384 $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
385 WRKBL = MAX( WRKBL, BDSPAC+3*M )
386 MAXWRK = WRKBL + M*M
387 MINWRK = BDSPAC + M*M + 3*M
388 END IF
389 ELSE
390 *
391 * Path 5t (N greater than M, but not much larger)
392 *
393 WRKBL = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1,
394 $ -1 )
395 IF( WNTQN ) THEN
396 MAXWRK = MAX( WRKBL, BDSPAC+3*M )
397 MINWRK = 3*M + MAX( N, BDSPAC )
398 ELSE IF( WNTQO ) THEN
399 WRKBL = MAX( WRKBL, 3*M+M*
400 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
401 WRKBL = MAX( WRKBL, 3*M+M*
402 $ ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) )
403 WRKBL = MAX( WRKBL, BDSPAC+3*M )
404 MAXWRK = WRKBL + M*N
405 MINWRK = 3*M + MAX( N, M*M+BDSPAC )
406 ELSE IF( WNTQS ) THEN
407 WRKBL = MAX( WRKBL, 3*M+M*
408 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
409 WRKBL = MAX( WRKBL, 3*M+M*
410 $ ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) )
411 MAXWRK = MAX( WRKBL, BDSPAC+3*M )
412 MINWRK = 3*M + MAX( N, BDSPAC )
413 ELSE IF( WNTQA ) THEN
414 WRKBL = MAX( WRKBL, 3*M+M*
415 $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
416 WRKBL = MAX( WRKBL, 3*M+M*
417 $ ILAENV( 1, 'DORMBR', 'PRT', N, N, M, -1 ) )
418 MAXWRK = MAX( WRKBL, BDSPAC+3*M )
419 MINWRK = 3*M + MAX( N, BDSPAC )
420 END IF
421 END IF
422 END IF
423 MAXWRK = MAX( MAXWRK, MINWRK )
424 WORK( 1 ) = MAXWRK
425 *
426 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
427 INFO = -12
428 END IF
429 END IF
430 *
431 IF( INFO.NE.0 ) THEN
432 CALL XERBLA( 'DGESDD', -INFO )
433 RETURN
434 ELSE IF( LQUERY ) THEN
435 RETURN
436 END IF
437 *
438 * Quick return if possible
439 *
440 IF( M.EQ.0 .OR. N.EQ.0 ) THEN
441 RETURN
442 END IF
443 *
444 * Get machine constants
445 *
446 EPS = DLAMCH( 'P' )
447 SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
448 BIGNUM = ONE / SMLNUM
449 *
450 * Scale A if max element outside range [SMLNUM,BIGNUM]
451 *
452 ANRM = DLANGE( 'M', M, N, A, LDA, DUM )
453 ISCL = 0
454 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
455 ISCL = 1
456 CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )
457 ELSE IF( ANRM.GT.BIGNUM ) THEN
458 ISCL = 1
459 CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )
460 END IF
461 *
462 IF( M.GE.N ) THEN
463 *
464 * A has at least as many rows as columns. If A has sufficiently
465 * more rows than columns, first reduce using the QR
466 * decomposition (if sufficient workspace available)
467 *
468 IF( M.GE.MNTHR ) THEN
469 *
470 IF( WNTQN ) THEN
471 *
472 * Path 1 (M much larger than N, JOBZ='N')
473 * No singular vectors to be computed
474 *
475 ITAU = 1
476 NWORK = ITAU + N
477 *
478 * Compute A=Q*R
479 * (Workspace: need 2*N, prefer N+N*NB)
480 *
481 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
482 $ LWORK-NWORK+1, IERR )
483 *
484 * Zero out below R
485 *
486 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
487 IE = 1
488 ITAUQ = IE + N
489 ITAUP = ITAUQ + N
490 NWORK = ITAUP + N
491 *
492 * Bidiagonalize R in A
493 * (Workspace: need 4*N, prefer 3*N+2*N*NB)
494 *
495 CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
496 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
497 $ IERR )
498 NWORK = IE + N
499 *
500 * Perform bidiagonal SVD, computing singular values only
501 * (Workspace: need N+BDSPAC)
502 *
503 CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,
504 $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )
505 *
506 ELSE IF( WNTQO ) THEN
507 *
508 * Path 2 (M much larger than N, JOBZ = 'O')
509 * N left singular vectors to be overwritten on A and
510 * N right singular vectors to be computed in VT
511 *
512 IR = 1
513 *
514 * WORK(IR) is LDWRKR by N
515 *
516 IF( LWORK.GE.LDA*N+N*N+3*N+BDSPAC ) THEN
517 LDWRKR = LDA
518 ELSE
519 LDWRKR = ( LWORK-N*N-3*N-BDSPAC ) / N
520 END IF
521 ITAU = IR + LDWRKR*N
522 NWORK = ITAU + N
523 *
524 * Compute A=Q*R
525 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
526 *
527 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
528 $ LWORK-NWORK+1, IERR )
529 *
530 * Copy R to WORK(IR), zeroing out below it
531 *
532 CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
533 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
534 $ LDWRKR )
535 *
536 * Generate Q in A
537 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
538 *
539 CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
540 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
541 IE = ITAU
542 ITAUQ = IE + N
543 ITAUP = ITAUQ + N
544 NWORK = ITAUP + N
545 *
546 * Bidiagonalize R in VT, copying result to WORK(IR)
547 * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
548 *
549 CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
550 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
551 $ LWORK-NWORK+1, IERR )
552 *
553 * WORK(IU) is N by N
554 *
555 IU = NWORK
556 NWORK = IU + N*N
557 *
558 * Perform bidiagonal SVD, computing left singular vectors
559 * of bidiagonal matrix in WORK(IU) and computing right
560 * singular vectors of bidiagonal matrix in VT
561 * (Workspace: need N+N*N+BDSPAC)
562 *
563 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,
564 $ VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
565 $ INFO )
566 *
567 * Overwrite WORK(IU) by left singular vectors of R
568 * and VT by right singular vectors of R
569 * (Workspace: need 2*N*N+3*N, prefer 2*N*N+2*N+N*NB)
570 *
571 CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,
572 $ WORK( ITAUQ ), WORK( IU ), N, WORK( NWORK ),
573 $ LWORK-NWORK+1, IERR )
574 CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,
575 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
576 $ LWORK-NWORK+1, IERR )
577 *
578 * Multiply Q in A by left singular vectors of R in
579 * WORK(IU), storing result in WORK(IR) and copying to A
580 * (Workspace: need 2*N*N, prefer N*N+M*N)
581 *
582 DO 10 I = 1, M, LDWRKR
583 CHUNK = MIN( M-I+1, LDWRKR )
584 CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
585 $ LDA, WORK( IU ), N, ZERO, WORK( IR ),
586 $ LDWRKR )
587 CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,
588 $ A( I, 1 ), LDA )
589 10 CONTINUE
590 *
591 ELSE IF( WNTQS ) THEN
592 *
593 * Path 3 (M much larger than N, JOBZ='S')
594 * N left singular vectors to be computed in U and
595 * N right singular vectors to be computed in VT
596 *
597 IR = 1
598 *
599 * WORK(IR) is N by N
600 *
601 LDWRKR = N
602 ITAU = IR + LDWRKR*N
603 NWORK = ITAU + N
604 *
605 * Compute A=Q*R
606 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
607 *
608 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
609 $ LWORK-NWORK+1, IERR )
610 *
611 * Copy R to WORK(IR), zeroing out below it
612 *
613 CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
614 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
615 $ LDWRKR )
616 *
617 * Generate Q in A
618 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
619 *
620 CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
621 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
622 IE = ITAU
623 ITAUQ = IE + N
624 ITAUP = ITAUQ + N
625 NWORK = ITAUP + N
626 *
627 * Bidiagonalize R in WORK(IR)
628 * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
629 *
630 CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
631 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
632 $ LWORK-NWORK+1, IERR )
633 *
634 * Perform bidiagonal SVD, computing left singular vectors
635 * of bidiagoal matrix in U and computing right singular
636 * vectors of bidiagonal matrix in VT
637 * (Workspace: need N+BDSPAC)
638 *
639 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
640 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
641 $ INFO )
642 *
643 * Overwrite U by left singular vectors of R and VT
644 * by right singular vectors of R
645 * (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)
646 *
647 CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,
648 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
649 $ LWORK-NWORK+1, IERR )
650 *
651 CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,
652 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
653 $ LWORK-NWORK+1, IERR )
654 *
655 * Multiply Q in A by left singular vectors of R in
656 * WORK(IR), storing result in U
657 * (Workspace: need N*N)
658 *
659 CALL DLACPY( 'F', N, N, U, LDU, WORK( IR ), LDWRKR )
660 CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA, WORK( IR ),
661 $ LDWRKR, ZERO, U, LDU )
662 *
663 ELSE IF( WNTQA ) THEN
664 *
665 * Path 4 (M much larger than N, JOBZ='A')
666 * M left singular vectors to be computed in U and
667 * N right singular vectors to be computed in VT
668 *
669 IU = 1
670 *
671 * WORK(IU) is N by N
672 *
673 LDWRKU = N
674 ITAU = IU + LDWRKU*N
675 NWORK = ITAU + N
676 *
677 * Compute A=Q*R, copying result to U
678 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
679 *
680 CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
681 $ LWORK-NWORK+1, IERR )
682 CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
683 *
684 * Generate Q in U
685 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
686 CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
687 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
688 *
689 * Produce R in A, zeroing out other entries
690 *
691 CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
692 IE = ITAU
693 ITAUQ = IE + N
694 ITAUP = ITAUQ + N
695 NWORK = ITAUP + N
696 *
697 * Bidiagonalize R in A
698 * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
699 *
700 CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
701 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
702 $ IERR )
703 *
704 * Perform bidiagonal SVD, computing left singular vectors
705 * of bidiagonal matrix in WORK(IU) and computing right
706 * singular vectors of bidiagonal matrix in VT
707 * (Workspace: need N+N*N+BDSPAC)
708 *
709 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,
710 $ VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
711 $ INFO )
712 *
713 * Overwrite WORK(IU) by left singular vectors of R and VT
714 * by right singular vectors of R
715 * (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)
716 *
717 CALL DORMBR( 'Q', 'L', 'N', N, N, N, A, LDA,
718 $ WORK( ITAUQ ), WORK( IU ), LDWRKU,
719 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
720 CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
721 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
722 $ LWORK-NWORK+1, IERR )
723 *
724 * Multiply Q in U by left singular vectors of R in
725 * WORK(IU), storing result in A
726 * (Workspace: need N*N)
727 *
728 CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU, WORK( IU ),
729 $ LDWRKU, ZERO, A, LDA )
730 *
731 * Copy left singular vectors of A from A to U
732 *
733 CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
734 *
735 END IF
736 *
737 ELSE
738 *
739 * M .LT. MNTHR
740 *
741 * Path 5 (M at least N, but not much larger)
742 * Reduce to bidiagonal form without QR decomposition
743 *
744 IE = 1
745 ITAUQ = IE + N
746 ITAUP = ITAUQ + N
747 NWORK = ITAUP + N
748 *
749 * Bidiagonalize A
750 * (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)
751 *
752 CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
753 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
754 $ IERR )
755 IF( WNTQN ) THEN
756 *
757 * Perform bidiagonal SVD, only computing singular values
758 * (Workspace: need N+BDSPAC)
759 *
760 CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,
761 $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )
762 ELSE IF( WNTQO ) THEN
763 IU = NWORK
764 IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN
765 *
766 * WORK( IU ) is M by N
767 *
768 LDWRKU = M
769 NWORK = IU + LDWRKU*N
770 CALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IU ),
771 $ LDWRKU )
772 ELSE
773 *
774 * WORK( IU ) is N by N
775 *
776 LDWRKU = N
777 NWORK = IU + LDWRKU*N
778 *
779 * WORK(IR) is LDWRKR by N
780 *
781 IR = NWORK
782 LDWRKR = ( LWORK-N*N-3*N ) / N
783 END IF
784 NWORK = IU + LDWRKU*N
785 *
786 * Perform bidiagonal SVD, computing left singular vectors
787 * of bidiagonal matrix in WORK(IU) and computing right
788 * singular vectors of bidiagonal matrix in VT
789 * (Workspace: need N+N*N+BDSPAC)
790 *
791 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ),
792 $ LDWRKU, VT, LDVT, DUM, IDUM, WORK( NWORK ),
793 $ IWORK, INFO )
794 *
795 * Overwrite VT by right singular vectors of A
796 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
797 *
798 CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
799 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
800 $ LWORK-NWORK+1, IERR )
801 *
802 IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN
803 *
804 * Overwrite WORK(IU) by left singular vectors of A
805 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
806 *
807 CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,
808 $ WORK( ITAUQ ), WORK( IU ), LDWRKU,
809 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
810 *
811 * Copy left singular vectors of A from WORK(IU) to A
812 *
813 CALL DLACPY( 'F', M, N, WORK( IU ), LDWRKU, A, LDA )
814 ELSE
815 *
816 * Generate Q in A
817 * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
818 *
819 CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
820 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
821 *
822 * Multiply Q in A by left singular vectors of
823 * bidiagonal matrix in WORK(IU), storing result in
824 * WORK(IR) and copying to A
825 * (Workspace: need 2*N*N, prefer N*N+M*N)
826 *
827 DO 20 I = 1, M, LDWRKR
828 CHUNK = MIN( M-I+1, LDWRKR )
829 CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
830 $ LDA, WORK( IU ), LDWRKU, ZERO,
831 $ WORK( IR ), LDWRKR )
832 CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,
833 $ A( I, 1 ), LDA )
834 20 CONTINUE
835 END IF
836 *
837 ELSE IF( WNTQS ) THEN
838 *
839 * Perform bidiagonal SVD, computing left singular vectors
840 * of bidiagonal matrix in U and computing right singular
841 * vectors of bidiagonal matrix in VT
842 * (Workspace: need N+BDSPAC)
843 *
844 CALL DLASET( 'F', M, N, ZERO, ZERO, U, LDU )
845 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
846 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
847 $ INFO )
848 *
849 * Overwrite U by left singular vectors of A and VT
850 * by right singular vectors of A
851 * (Workspace: need 3*N, prefer 2*N+N*NB)
852 *
853 CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,
854 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
855 $ LWORK-NWORK+1, IERR )
856 CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
857 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
858 $ LWORK-NWORK+1, IERR )
859 ELSE IF( WNTQA ) THEN
860 *
861 * Perform bidiagonal SVD, computing left singular vectors
862 * of bidiagonal matrix in U and computing right singular
863 * vectors of bidiagonal matrix in VT
864 * (Workspace: need N+BDSPAC)
865 *
866 CALL DLASET( 'F', M, M, ZERO, ZERO, U, LDU )
867 CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
868 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
869 $ INFO )
870 *
871 * Set the right corner of U to identity matrix
872 *
873 IF( M.GT.N ) THEN
874 CALL DLASET( 'F', M-N, M-N, ZERO, ONE, U( N+1, N+1 ),
875 $ LDU )
876 END IF
877 *
878 * Overwrite U by left singular vectors of A and VT
879 * by right singular vectors of A
880 * (Workspace: need N*N+2*N+M, prefer N*N+2*N+M*NB)
881 *
882 CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
883 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
884 $ LWORK-NWORK+1, IERR )
885 CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA,
886 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
887 $ LWORK-NWORK+1, IERR )
888 END IF
889 *
890 END IF
891 *
892 ELSE
893 *
894 * A has more columns than rows. If A has sufficiently more
895 * columns than rows, first reduce using the LQ decomposition (if
896 * sufficient workspace available)
897 *
898 IF( N.GE.MNTHR ) THEN
899 *
900 IF( WNTQN ) THEN
901 *
902 * Path 1t (N much larger than M, JOBZ='N')
903 * No singular vectors to be computed
904 *
905 ITAU = 1
906 NWORK = ITAU + M
907 *
908 * Compute A=L*Q
909 * (Workspace: need 2*M, prefer M+M*NB)
910 *
911 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
912 $ LWORK-NWORK+1, IERR )
913 *
914 * Zero out above L
915 *
916 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
917 IE = 1
918 ITAUQ = IE + M
919 ITAUP = ITAUQ + M
920 NWORK = ITAUP + M
921 *
922 * Bidiagonalize L in A
923 * (Workspace: need 4*M, prefer 3*M+2*M*NB)
924 *
925 CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
926 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
927 $ IERR )
928 NWORK = IE + M
929 *
930 * Perform bidiagonal SVD, computing singular values only
931 * (Workspace: need M+BDSPAC)
932 *
933 CALL DBDSDC( 'U', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,
934 $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )
935 *
936 ELSE IF( WNTQO ) THEN
937 *
938 * Path 2t (N much larger than M, JOBZ='O')
939 * M right singular vectors to be overwritten on A and
940 * M left singular vectors to be computed in U
941 *
942 IVT = 1
943 *
944 * IVT is M by M
945 *
946 IL = IVT + M*M
947 IF( LWORK.GE.M*N+M*M+3*M+BDSPAC ) THEN
948 *
949 * WORK(IL) is M by N
950 *
951 LDWRKL = M
952 CHUNK = N
953 ELSE
954 LDWRKL = M
955 CHUNK = ( LWORK-M*M ) / M
956 END IF
957 ITAU = IL + LDWRKL*M
958 NWORK = ITAU + M
959 *
960 * Compute A=L*Q
961 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
962 *
963 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
964 $ LWORK-NWORK+1, IERR )
965 *
966 * Copy L to WORK(IL), zeroing about above it
967 *
968 CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )
969 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
970 $ WORK( IL+LDWRKL ), LDWRKL )
971 *
972 * Generate Q in A
973 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
974 *
975 CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
976 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
977 IE = ITAU
978 ITAUQ = IE + M
979 ITAUP = ITAUQ + M
980 NWORK = ITAUP + M
981 *
982 * Bidiagonalize L in WORK(IL)
983 * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
984 *
985 CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),
986 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
987 $ LWORK-NWORK+1, IERR )
988 *
989 * Perform bidiagonal SVD, computing left singular vectors
990 * of bidiagonal matrix in U, and computing right singular
991 * vectors of bidiagonal matrix in WORK(IVT)
992 * (Workspace: need M+M*M+BDSPAC)
993 *
994 CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,
995 $ WORK( IVT ), M, DUM, IDUM, WORK( NWORK ),
996 $ IWORK, INFO )
997 *
998 * Overwrite U by left singular vectors of L and WORK(IVT)
999 * by right singular vectors of L
1000 * (Workspace: need 2*M*M+3*M, prefer 2*M*M+2*M+M*NB)
1001 *
1002 CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,
1003 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1004 $ LWORK-NWORK+1, IERR )
1005 CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,
1006 $ WORK( ITAUP ), WORK( IVT ), M,
1007 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1008 *
1009 * Multiply right singular vectors of L in WORK(IVT) by Q
1010 * in A, storing result in WORK(IL) and copying to A
1011 * (Workspace: need 2*M*M, prefer M*M+M*N)
1012 *
1013 DO 30 I = 1, N, CHUNK
1014 BLK = MIN( N-I+1, CHUNK )
1015 CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ), M,
1016 $ A( 1, I ), LDA, ZERO, WORK( IL ), LDWRKL )
1017 CALL DLACPY( 'F', M, BLK, WORK( IL ), LDWRKL,
1018 $ A( 1, I ), LDA )
1019 30 CONTINUE
1020 *
1021 ELSE IF( WNTQS ) THEN
1022 *
1023 * Path 3t (N much larger than M, JOBZ='S')
1024 * M right singular vectors to be computed in VT and
1025 * M left singular vectors to be computed in U
1026 *
1027 IL = 1
1028 *
1029 * WORK(IL) is M by M
1030 *
1031 LDWRKL = M
1032 ITAU = IL + LDWRKL*M
1033 NWORK = ITAU + M
1034 *
1035 * Compute A=L*Q
1036 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1037 *
1038 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
1039 $ LWORK-NWORK+1, IERR )
1040 *
1041 * Copy L to WORK(IL), zeroing out above it
1042 *
1043 CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )
1044 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
1045 $ WORK( IL+LDWRKL ), LDWRKL )
1046 *
1047 * Generate Q in A
1048 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1049 *
1050 CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
1051 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1052 IE = ITAU
1053 ITAUQ = IE + M
1054 ITAUP = ITAUQ + M
1055 NWORK = ITAUP + M
1056 *
1057 * Bidiagonalize L in WORK(IU), copying result to U
1058 * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
1059 *
1060 CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),
1061 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
1062 $ LWORK-NWORK+1, IERR )
1063 *
1064 * Perform bidiagonal SVD, computing left singular vectors
1065 * of bidiagonal matrix in U and computing right singular
1066 * vectors of bidiagonal matrix in VT
1067 * (Workspace: need M+BDSPAC)
1068 *
1069 CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU, VT,
1070 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
1071 $ INFO )
1072 *
1073 * Overwrite U by left singular vectors of L and VT
1074 * by right singular vectors of L
1075 * (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)
1076 *
1077 CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,
1078 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1079 $ LWORK-NWORK+1, IERR )
1080 CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,
1081 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
1082 $ LWORK-NWORK+1, IERR )
1083 *
1084 * Multiply right singular vectors of L in WORK(IL) by
1085 * Q in A, storing result in VT
1086 * (Workspace: need M*M)
1087 *
1088 CALL DLACPY( 'F', M, M, VT, LDVT, WORK( IL ), LDWRKL )
1089 CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IL ), LDWRKL,
1090 $ A, LDA, ZERO, VT, LDVT )
1091 *
1092 ELSE IF( WNTQA ) THEN
1093 *
1094 * Path 4t (N much larger than M, JOBZ='A')
1095 * N right singular vectors to be computed in VT and
1096 * M left singular vectors to be computed in U
1097 *
1098 IVT = 1
1099 *
1100 * WORK(IVT) is M by M
1101 *
1102 LDWKVT = M
1103 ITAU = IVT + LDWKVT*M
1104 NWORK = ITAU + M
1105 *
1106 * Compute A=L*Q, copying result to VT
1107 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1108 *
1109 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
1110 $ LWORK-NWORK+1, IERR )
1111 CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
1112 *
1113 * Generate Q in VT
1114 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1115 *
1116 CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
1117 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1118 *
1119 * Produce L in A, zeroing out other entries
1120 *
1121 CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
1122 IE = ITAU
1123 ITAUQ = IE + M
1124 ITAUP = ITAUQ + M
1125 NWORK = ITAUP + M
1126 *
1127 * Bidiagonalize L in A
1128 * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
1129 *
1130 CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
1131 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
1132 $ IERR )
1133 *
1134 * Perform bidiagonal SVD, computing left singular vectors
1135 * of bidiagonal matrix in U and computing right singular
1136 * vectors of bidiagonal matrix in WORK(IVT)
1137 * (Workspace: need M+M*M+BDSPAC)
1138 *
1139 CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,
1140 $ WORK( IVT ), LDWKVT, DUM, IDUM,
1141 $ WORK( NWORK ), IWORK, INFO )
1142 *
1143 * Overwrite U by left singular vectors of L and WORK(IVT)
1144 * by right singular vectors of L
1145 * (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)
1146 *
1147 CALL DORMBR( 'Q', 'L', 'N', M, M, M, A, LDA,
1148 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1149 $ LWORK-NWORK+1, IERR )
1150 CALL DORMBR( 'P', 'R', 'T', M, M, M, A, LDA,
1151 $ WORK( ITAUP ), WORK( IVT ), LDWKVT,
1152 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1153 *
1154 * Multiply right singular vectors of L in WORK(IVT) by
1155 * Q in VT, storing result in A
1156 * (Workspace: need M*M)
1157 *
1158 CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IVT ), LDWKVT,
1159 $ VT, LDVT, ZERO, A, LDA )
1160 *
1161 * Copy right singular vectors of A from A to VT
1162 *
1163 CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
1164 *
1165 END IF
1166 *
1167 ELSE
1168 *
1169 * N .LT. MNTHR
1170 *
1171 * Path 5t (N greater than M, but not much larger)
1172 * Reduce to bidiagonal form without LQ decomposition
1173 *
1174 IE = 1
1175 ITAUQ = IE + M
1176 ITAUP = ITAUQ + M
1177 NWORK = ITAUP + M
1178 *
1179 * Bidiagonalize A
1180 * (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
1181 *
1182 CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
1183 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
1184 $ IERR )
1185 IF( WNTQN ) THEN
1186 *
1187 * Perform bidiagonal SVD, only computing singular values
1188 * (Workspace: need M+BDSPAC)
1189 *
1190 CALL DBDSDC( 'L', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,
1191 $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )
1192 ELSE IF( WNTQO ) THEN
1193 LDWKVT = M
1194 IVT = NWORK
1195 IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN
1196 *
1197 * WORK( IVT ) is M by N
1198 *
1199 CALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IVT ),
1200 $ LDWKVT )
1201 NWORK = IVT + LDWKVT*N
1202 ELSE
1203 *
1204 * WORK( IVT ) is M by M
1205 *
1206 NWORK = IVT + LDWKVT*M
1207 IL = NWORK
1208 *
1209 * WORK(IL) is M by CHUNK
1210 *
1211 CHUNK = ( LWORK-M*M-3*M ) / M
1212 END IF
1213 *
1214 * Perform bidiagonal SVD, computing left singular vectors
1215 * of bidiagonal matrix in U and computing right singular
1216 * vectors of bidiagonal matrix in WORK(IVT)
1217 * (Workspace: need M*M+BDSPAC)
1218 *
1219 CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU,
1220 $ WORK( IVT ), LDWKVT, DUM, IDUM,
1221 $ WORK( NWORK ), IWORK, INFO )
1222 *
1223 * Overwrite U by left singular vectors of A
1224 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1225 *
1226 CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
1227 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1228 $ LWORK-NWORK+1, IERR )
1229 *
1230 IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN
1231 *
1232 * Overwrite WORK(IVT) by left singular vectors of A
1233 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1234 *
1235 CALL DORMBR( 'P', 'R', 'T', M, N, M, A, LDA,
1236 $ WORK( ITAUP ), WORK( IVT ), LDWKVT,
1237 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1238 *
1239 * Copy right singular vectors of A from WORK(IVT) to A
1240 *
1241 CALL DLACPY( 'F', M, N, WORK( IVT ), LDWKVT, A, LDA )
1242 ELSE
1243 *
1244 * Generate P**T in A
1245 * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
1246 *
1247 CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
1248 $ WORK( NWORK ), LWORK-NWORK+1, IERR )
1249 *
1250 * Multiply Q in A by right singular vectors of
1251 * bidiagonal matrix in WORK(IVT), storing result in
1252 * WORK(IL) and copying to A
1253 * (Workspace: need 2*M*M, prefer M*M+M*N)
1254 *
1255 DO 40 I = 1, N, CHUNK
1256 BLK = MIN( N-I+1, CHUNK )
1257 CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ),
1258 $ LDWKVT, A( 1, I ), LDA, ZERO,
1259 $ WORK( IL ), M )
1260 CALL DLACPY( 'F', M, BLK, WORK( IL ), M, A( 1, I ),
1261 $ LDA )
1262 40 CONTINUE
1263 END IF
1264 ELSE IF( WNTQS ) THEN
1265 *
1266 * Perform bidiagonal SVD, computing left singular vectors
1267 * of bidiagonal matrix in U and computing right singular
1268 * vectors of bidiagonal matrix in VT
1269 * (Workspace: need M+BDSPAC)
1270 *
1271 CALL DLASET( 'F', M, N, ZERO, ZERO, VT, LDVT )
1272 CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,
1273 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
1274 $ INFO )
1275 *
1276 * Overwrite U by left singular vectors of A and VT
1277 * by right singular vectors of A
1278 * (Workspace: need 3*M, prefer 2*M+M*NB)
1279 *
1280 CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
1281 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1282 $ LWORK-NWORK+1, IERR )
1283 CALL DORMBR( 'P', 'R', 'T', M, N, M, A, LDA,
1284 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
1285 $ LWORK-NWORK+1, IERR )
1286 ELSE IF( WNTQA ) THEN
1287 *
1288 * Perform bidiagonal SVD, computing left singular vectors
1289 * of bidiagonal matrix in U and computing right singular
1290 * vectors of bidiagonal matrix in VT
1291 * (Workspace: need M+BDSPAC)
1292 *
1293 CALL DLASET( 'F', N, N, ZERO, ZERO, VT, LDVT )
1294 CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,
1295 $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
1296 $ INFO )
1297 *
1298 * Set the right corner of VT to identity matrix
1299 *
1300 IF( N.GT.M ) THEN
1301 CALL DLASET( 'F', N-M, N-M, ZERO, ONE, VT( M+1, M+1 ),
1302 $ LDVT )
1303 END IF
1304 *
1305 * Overwrite U by left singular vectors of A and VT
1306 * by right singular vectors of A
1307 * (Workspace: need 2*M+N, prefer 2*M+N*NB)
1308 *
1309 CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
1310 $ WORK( ITAUQ ), U, LDU, WORK( NWORK ),
1311 $ LWORK-NWORK+1, IERR )
1312 CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA,
1313 $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
1314 $ LWORK-NWORK+1, IERR )
1315 END IF
1316 *
1317 END IF
1318 *
1319 END IF
1320 *
1321 * Undo scaling if necessary
1322 *
1323 IF( ISCL.EQ.1 ) THEN
1324 IF( ANRM.GT.BIGNUM )
1325 $ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
1326 $ IERR )
1327 IF( ANRM.LT.SMLNUM )
1328 $ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
1329 $ IERR )
1330 END IF
1331 *
1332 * Return optimal workspace in WORK(1)
1333 *
1334 WORK( 1 ) = MAXWRK
1335 *
1336 RETURN
1337 *
1338 * End of DGESDD
1339 *
1340 END