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