LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ dgelss()

subroutine dgelss ( integer m,
integer n,
integer nrhs,
double precision, dimension( lda, * ) a,
integer lda,
double precision, dimension( ldb, * ) b,
integer ldb,
double precision, dimension( * ) s,
double precision rcond,
integer rank,
double precision, dimension( * ) work,
integer lwork,
integer info )

DGELSS solves overdetermined or underdetermined systems for GE matrices

Download DGELSS + dependencies [TGZ] [ZIP] [TXT]

Purpose:
!>
!> DGELSS computes the minimum norm solution to a real linear least
!> squares problem:
!>
!> Minimize 2-norm(| b - A*x |).
!>
!> using the singular value decomposition (SVD) of A. A is an M-by-N
!> matrix which may be rank-deficient.
!>
!> Several right hand side vectors b and solution vectors x can be
!> handled in a single call; they are stored as the columns of the
!> M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix
!> X.
!>
!> The effective rank of A is determined by treating as zero those
!> singular values which are less than RCOND times the largest singular
!> value.
!> 
Parameters
[in]M
!>          M is INTEGER
!>          The number of rows of the matrix A. M >= 0.
!> 
[in]N
!>          N is INTEGER
!>          The number of columns of the matrix A. N >= 0.
!> 
[in]NRHS
!>          NRHS is INTEGER
!>          The number of right hand sides, i.e., the number of columns
!>          of the matrices B and X. NRHS >= 0.
!> 
[in,out]A
!>          A is DOUBLE PRECISION array, dimension (LDA,N)
!>          On entry, the M-by-N matrix A.
!>          On exit, the first min(m,n) rows of A are overwritten with
!>          its right singular vectors, stored rowwise.
!> 
[in]LDA
!>          LDA is INTEGER
!>          The leading dimension of the array A.  LDA >= max(1,M).
!> 
[in,out]B
!>          B is DOUBLE PRECISION array, dimension (LDB,NRHS)
!>          On entry, the M-by-NRHS right hand side matrix B.
!>          On exit, B is overwritten by the N-by-NRHS solution
!>          matrix X.  If m >= n and RANK = n, the residual
!>          sum-of-squares for the solution in the i-th column is given
!>          by the sum of squares of elements n+1:m in that column.
!> 
[in]LDB
!>          LDB is INTEGER
!>          The leading dimension of the array B. LDB >= max(1,max(M,N)).
!> 
[out]S
!>          S is DOUBLE PRECISION array, dimension (min(M,N))
!>          The singular values of A in decreasing order.
!>          The condition number of A in the 2-norm = S(1)/S(min(m,n)).
!> 
[in]RCOND
!>          RCOND is DOUBLE PRECISION
!>          RCOND is used to determine the effective rank of A.
!>          Singular values S(i) <= RCOND*S(1) are treated as zero.
!>          If RCOND < 0, machine precision is used instead.
!> 
[out]RANK
!>          RANK is INTEGER
!>          The effective rank of A, i.e., the number of singular values
!>          which are greater than RCOND*S(1).
!> 
[out]WORK
!>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
!>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
!> 
[in]LWORK
!>          LWORK is INTEGER
!>          The dimension of the array WORK. LWORK >= 1, and also:
!>          LWORK >= 3*min(M,N) + max( 2*min(M,N), max(M,N), NRHS )
!>          For good performance, LWORK should generally be larger.
!>
!>          If LWORK = -1, then a workspace query is assumed; the routine
!>          only calculates the optimal size of the WORK array, returns
!>          this value as the first entry of the WORK array, and no error
!>          message related to LWORK is issued by XERBLA.
!> 
[out]INFO
!>          INFO is INTEGER
!>          = 0:  successful exit
!>          < 0:  if INFO = -i, the i-th argument had an illegal value.
!>          > 0:  the algorithm for computing the SVD failed to converge;
!>                if INFO = i, i off-diagonal elements of an intermediate
!>                bidiagonal form did not converge to zero.
!> 
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.

Definition at line 168 of file dgelss.f.

170*
171* -- LAPACK driver routine --
172* -- LAPACK is a software package provided by Univ. of Tennessee, --
173* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
174*
175* .. Scalar Arguments ..
176 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
177 DOUBLE PRECISION RCOND
178* ..
179* .. Array Arguments ..
180 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
181* ..
182*
183* =====================================================================
184*
185* .. Parameters ..
186 DOUBLE PRECISION ZERO, ONE
187 parameter( zero = 0.0d+0, one = 1.0d+0 )
188* ..
189* .. Local Scalars ..
190 LOGICAL LQUERY
191 INTEGER BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
192 $ ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
193 $ MAXWRK, MINMN, MINWRK, MM, MNTHR
194 INTEGER LWORK_DGEQRF, LWORK_DORMQR, LWORK_DGEBRD,
195 $ LWORK_DORMBR, LWORK_DORGBR, LWORK_DORMLQ,
196 $ LWORK_DGELQF
197 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
198* ..
199* .. Local Arrays ..
200 DOUBLE PRECISION DUM( 1 )
201* ..
202* .. External Subroutines ..
203 EXTERNAL dbdsqr, dcopy, dgebrd, dgelqf, dgemm,
204 $ dgemv,
207* ..
208* .. External Functions ..
209 INTEGER ILAENV
210 DOUBLE PRECISION DLAMCH, DLANGE
211 EXTERNAL ilaenv, dlamch, dlange
212* ..
213* .. Intrinsic Functions ..
214 INTRINSIC max, min
215* ..
216* .. Executable Statements ..
217*
218* Test the input arguments
219*
220 info = 0
221 minmn = min( m, n )
222 maxmn = max( m, n )
223 lquery = ( lwork.EQ.-1 )
224 IF( m.LT.0 ) THEN
225 info = -1
226 ELSE IF( n.LT.0 ) THEN
227 info = -2
228 ELSE IF( nrhs.LT.0 ) THEN
229 info = -3
230 ELSE IF( lda.LT.max( 1, m ) ) THEN
231 info = -5
232 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
233 info = -7
234 END IF
235*
236* Compute workspace
237* (Note: Comments in the code beginning "Workspace:" describe the
238* minimal amount of workspace needed at that point in the code,
239* as well as the preferred amount for good performance.
240* NB refers to the optimal block size for the immediately
241* following subroutine, as returned by ILAENV.)
242*
243 IF( info.EQ.0 ) THEN
244 minwrk = 1
245 maxwrk = 1
246 IF( minmn.GT.0 ) THEN
247 mm = m
248 mnthr = ilaenv( 6, 'DGELSS', ' ', m, n, nrhs, -1 )
249 IF( m.GE.n .AND. m.GE.mnthr ) THEN
250*
251* Path 1a - overdetermined, with many more rows than
252* columns
253*
254* Compute space needed for DGEQRF
255 CALL dgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
256 lwork_dgeqrf = int( dum(1) )
257* Compute space needed for DORMQR
258 CALL dormqr( 'L', 'T', m, nrhs, n, a, lda, dum(1), b,
259 $ ldb, dum(1), -1, info )
260 lwork_dormqr = int( dum(1) )
261 mm = n
262 maxwrk = max( maxwrk, n + lwork_dgeqrf )
263 maxwrk = max( maxwrk, n + lwork_dormqr )
264 END IF
265 IF( m.GE.n ) THEN
266*
267* Path 1 - overdetermined or exactly determined
268*
269* Compute workspace needed for DBDSQR
270*
271 bdspac = max( 1, 5*n )
272* Compute space needed for DGEBRD
273 CALL dgebrd( mm, n, a, lda, s, dum(1), dum(1),
274 $ dum(1), dum(1), -1, info )
275 lwork_dgebrd = int( dum(1) )
276* Compute space needed for DORMBR
277 CALL dormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda,
278 $ dum(1),
279 $ b, ldb, dum(1), -1, info )
280 lwork_dormbr = int( 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 = int( 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 = int( 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 = int( 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 = int( 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 = int( 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 = int( 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 = int( 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 = int( 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 = int( 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*
389* Scale A if max element outside range [SMLNUM,BIGNUM]
390*
391 anrm = dlange( 'M', m, n, a, lda, work )
392 iascl = 0
393 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
394*
395* Scale matrix norm up to SMLNUM
396*
397 CALL dlascl( 'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
398 iascl = 1
399 ELSE IF( anrm.GT.bignum ) THEN
400*
401* Scale matrix norm down to BIGNUM
402*
403 CALL dlascl( 'G', 0, 0, anrm, bignum, m, n, a, lda, info )
404 iascl = 2
405 ELSE IF( anrm.EQ.zero ) THEN
406*
407* Matrix all zero. Return zero solution.
408*
409 CALL dlaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb )
410 CALL dlaset( 'F', minmn, 1, zero, zero, s, minmn )
411 rank = 0
412 GO TO 70
413 END IF
414*
415* Scale B if max element outside range [SMLNUM,BIGNUM]
416*
417 bnrm = dlange( 'M', m, nrhs, b, ldb, work )
418 ibscl = 0
419 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
420*
421* Scale matrix norm up to SMLNUM
422*
423 CALL dlascl( 'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
424 $ 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,
431 $ info )
432 ibscl = 2
433 END IF
434*
435* Overdetermined case
436*
437 IF( m.GE.n ) THEN
438*
439* Path 1 - overdetermined or exactly determined
440*
441 mm = m
442 IF( m.GE.mnthr ) THEN
443*
444* Path 1a - overdetermined, with many more rows than columns
445*
446 mm = n
447 itau = 1
448 iwork = itau + n
449*
450* Compute A=Q*R
451* (Workspace: need 2*N, prefer N+N*NB)
452*
453 CALL dgeqrf( m, n, a, lda, work( itau ), work( iwork ),
454 $ lwork-iwork+1, info )
455*
456* Multiply B by transpose(Q)
457* (Workspace: need N+NRHS, prefer N+NRHS*NB)
458*
459 CALL dormqr( 'L', 'T', m, nrhs, n, a, lda, work( itau ),
460 $ b,
461 $ ldb, work( iwork ), lwork-iwork+1, info )
462*
463* Zero out below R
464*
465 IF( n.GT.1 )
466 $ CALL dlaset( 'L', n-1, n-1, zero, zero, a( 2, 1 ),
467 $ lda )
468 END IF
469*
470 ie = 1
471 itauq = ie + n
472 itaup = itauq + n
473 iwork = itaup + n
474*
475* Bidiagonalize R in A
476* (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB)
477*
478 CALL dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
479 $ work( itaup ), work( iwork ), lwork-iwork+1,
480 $ info )
481*
482* Multiply B by transpose of left bidiagonalizing vectors of R
483* (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB)
484*
485 CALL dormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda,
486 $ work( itauq ),
487 $ b, ldb, work( iwork ), lwork-iwork+1, info )
488*
489* Generate right bidiagonalizing vectors of R in A
490* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
491*
492 CALL dorgbr( 'P', n, n, n, a, lda, work( itaup ),
493 $ work( iwork ), lwork-iwork+1, info )
494 iwork = ie + n
495*
496* Perform bidiagonal QR iteration
497* multiply B by transpose of left singular vectors
498* compute right singular vectors in A
499* (Workspace: need BDSPAC)
500*
501 CALL dbdsqr( 'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
502 $ 1, b, ldb, work( iwork ), info )
503 IF( info.NE.0 )
504 $ GO TO 70
505*
506* Multiply B by reciprocals of singular values
507*
508 thr = max( rcond*s( 1 ), sfmin )
509 IF( rcond.LT.zero )
510 $ thr = max( eps*s( 1 ), sfmin )
511 rank = 0
512 DO 10 i = 1, n
513 IF( s( i ).GT.thr ) THEN
514 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
515 rank = rank + 1
516 ELSE
517 CALL dlaset( 'F', 1, nrhs, zero, zero, b( i, 1 ),
518 $ ldb )
519 END IF
520 10 CONTINUE
521*
522* Multiply B by right singular vectors
523* (Workspace: need N, prefer N*NRHS)
524*
525 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
526 CALL dgemm( 'T', 'N', n, nrhs, n, one, a, lda, b, ldb,
527 $ zero,
528 $ work, ldb )
529 CALL dlacpy( 'G', n, nrhs, work, ldb, b, ldb )
530 ELSE IF( nrhs.GT.1 ) THEN
531 chunk = lwork / n
532 DO 20 i = 1, nrhs, chunk
533 bl = min( nrhs-i+1, chunk )
534 CALL dgemm( 'T', 'N', n, bl, n, one, a, lda, b( 1,
535 $ i ),
536 $ ldb, zero, work, n )
537 CALL dlacpy( 'G', n, bl, work, n, b( 1, i ), ldb )
538 20 CONTINUE
539 ELSE IF( nrhs.EQ.1 ) THEN
540 CALL dgemv( 'T', n, n, one, a, lda, b, 1, zero, work, 1 )
541 CALL dcopy( n, work, 1, b, 1 )
542 END IF
543*
544 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
545 $ max( m, 2*m-4, nrhs, n-3*m ) ) THEN
546*
547* Path 2a - underdetermined, with many more columns than rows
548* and sufficient workspace for an efficient algorithm
549*
550 ldwork = m
551 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
552 $ m*lda+m+m*nrhs ) )ldwork = lda
553 itau = 1
554 iwork = m + 1
555*
556* Compute A=L*Q
557* (Workspace: need 2*M, prefer M+M*NB)
558*
559 CALL dgelqf( m, n, a, lda, work( itau ), work( iwork ),
560 $ lwork-iwork+1, info )
561 il = iwork
562*
563* Copy L to WORK(IL), zeroing out above it
564*
565 CALL dlacpy( 'L', m, m, a, lda, work( il ), ldwork )
566 CALL dlaset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),
567 $ ldwork )
568 ie = il + ldwork*m
569 itauq = ie + m
570 itaup = itauq + m
571 iwork = itaup + m
572*
573* Bidiagonalize L in WORK(IL)
574* (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB)
575*
576 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
577 $ work( itauq ), work( itaup ), work( iwork ),
578 $ lwork-iwork+1, info )
579*
580* Multiply B by transpose of left bidiagonalizing vectors of L
581* (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)
582*
583 CALL dormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,
584 $ work( itauq ), b, ldb, work( iwork ),
585 $ lwork-iwork+1, info )
586*
587* Generate right bidiagonalizing vectors of R in WORK(IL)
588* (Workspace: need M*M+5*M-1, prefer M*M+4*M+(M-1)*NB)
589*
590 CALL dorgbr( 'P', m, m, m, work( il ), ldwork,
591 $ work( itaup ),
592 $ work( iwork ), lwork-iwork+1, info )
593 iwork = ie + m
594*
595* Perform bidiagonal QR iteration,
596* computing right singular vectors of L in WORK(IL) and
597* multiplying B by transpose of left singular vectors
598* (Workspace: need M*M+M+BDSPAC)
599*
600 CALL dbdsqr( 'U', m, m, 0, nrhs, s, work( ie ), work( il ),
601 $ ldwork, a, lda, b, ldb, work( iwork ), info )
602 IF( info.NE.0 )
603 $ GO TO 70
604*
605* Multiply B by reciprocals of singular values
606*
607 thr = max( rcond*s( 1 ), sfmin )
608 IF( rcond.LT.zero )
609 $ thr = max( eps*s( 1 ), sfmin )
610 rank = 0
611 DO 30 i = 1, m
612 IF( s( i ).GT.thr ) THEN
613 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
614 rank = rank + 1
615 ELSE
616 CALL dlaset( 'F', 1, nrhs, zero, zero, b( i, 1 ),
617 $ ldb )
618 END IF
619 30 CONTINUE
620 iwork = ie
621*
622* Multiply B by right singular vectors of L in WORK(IL)
623* (Workspace: need M*M+2*M, prefer M*M+M+M*NRHS)
624*
625 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 ) THEN
626 CALL dgemm( 'T', 'N', m, nrhs, m, one, work( il ),
627 $ ldwork,
628 $ b, ldb, zero, work( iwork ), ldb )
629 CALL dlacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb )
630 ELSE IF( nrhs.GT.1 ) THEN
631 chunk = ( lwork-iwork+1 ) / m
632 DO 40 i = 1, nrhs, chunk
633 bl = min( nrhs-i+1, chunk )
634 CALL dgemm( 'T', 'N', m, bl, m, one, work( il ),
635 $ ldwork,
636 $ b( 1, i ), ldb, zero, work( iwork ), m )
637 CALL dlacpy( 'G', m, bl, work( iwork ), m, b( 1, i ),
638 $ ldb )
639 40 CONTINUE
640 ELSE IF( nrhs.EQ.1 ) THEN
641 CALL dgemv( 'T', m, m, one, work( il ), ldwork, b( 1,
642 $ 1 ),1, zero, work( iwork ), 1 )
643 CALL dcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
644 END IF
645*
646* Zero out below first M rows of B
647*
648 CALL dlaset( 'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
649 iwork = itau + m
650*
651* Multiply transpose(Q) by B
652* (Workspace: need M+NRHS, prefer M+NRHS*NB)
653*
654 CALL dormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,
655 $ ldb, work( iwork ), lwork-iwork+1, info )
656*
657 ELSE
658*
659* Path 2 - remaining underdetermined cases
660*
661 ie = 1
662 itauq = ie + m
663 itaup = itauq + m
664 iwork = itaup + m
665*
666* Bidiagonalize A
667* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
668*
669 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
670 $ work( itaup ), work( iwork ), lwork-iwork+1,
671 $ info )
672*
673* Multiply B by transpose of left bidiagonalizing vectors
674* (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB)
675*
676 CALL dormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda,
677 $ work( itauq ),
678 $ b, ldb, work( iwork ), lwork-iwork+1, info )
679*
680* Generate right bidiagonalizing vectors in A
681* (Workspace: need 4*M, prefer 3*M+M*NB)
682*
683 CALL dorgbr( 'P', m, n, m, a, lda, work( itaup ),
684 $ work( iwork ), lwork-iwork+1, info )
685 iwork = ie + m
686*
687* Perform bidiagonal QR iteration,
688* computing right singular vectors of A in A and
689* multiplying B by transpose of left singular vectors
690* (Workspace: need BDSPAC)
691*
692 CALL dbdsqr( 'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
693 $ 1, b, ldb, work( iwork ), info )
694 IF( info.NE.0 )
695 $ GO TO 70
696*
697* Multiply B by reciprocals of singular values
698*
699 thr = max( rcond*s( 1 ), sfmin )
700 IF( rcond.LT.zero )
701 $ thr = max( eps*s( 1 ), sfmin )
702 rank = 0
703 DO 50 i = 1, m
704 IF( s( i ).GT.thr ) THEN
705 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
706 rank = rank + 1
707 ELSE
708 CALL dlaset( 'F', 1, nrhs, zero, zero, b( i, 1 ),
709 $ ldb )
710 END IF
711 50 CONTINUE
712*
713* Multiply B by right singular vectors of A
714* (Workspace: need N, prefer N*NRHS)
715*
716 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
717 CALL dgemm( 'T', 'N', n, nrhs, m, one, a, lda, b, ldb,
718 $ zero,
719 $ work, ldb )
720 CALL dlacpy( 'F', n, nrhs, work, ldb, b, ldb )
721 ELSE IF( nrhs.GT.1 ) THEN
722 chunk = lwork / n
723 DO 60 i = 1, nrhs, chunk
724 bl = min( nrhs-i+1, chunk )
725 CALL dgemm( 'T', 'N', n, bl, m, one, a, lda, b( 1,
726 $ i ),
727 $ ldb, zero, work, n )
728 CALL dlacpy( 'F', n, bl, work, n, b( 1, i ), ldb )
729 60 CONTINUE
730 ELSE IF( nrhs.EQ.1 ) THEN
731 CALL dgemv( 'T', m, n, one, a, lda, b, 1, zero, work, 1 )
732 CALL dcopy( n, work, 1, b, 1 )
733 END IF
734 END IF
735*
736* Undo scaling
737*
738 IF( iascl.EQ.1 ) THEN
739 CALL dlascl( 'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
740 $ info )
741 CALL dlascl( 'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
742 $ info )
743 ELSE IF( iascl.EQ.2 ) THEN
744 CALL dlascl( 'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
745 $ info )
746 CALL dlascl( 'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
747 $ info )
748 END IF
749 IF( ibscl.EQ.1 ) THEN
750 CALL dlascl( 'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
751 $ info )
752 ELSE IF( ibscl.EQ.2 ) THEN
753 CALL dlascl( 'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
754 $ info )
755 END IF
756*
757 70 CONTINUE
758 work( 1 ) = maxwrk
759 RETURN
760*
761* End of DGELSS
762*
subroutine xerbla(srname, info)
Definition cblat2.f:3285
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 dgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
DGEBRD
Definition dgebrd.f:204
subroutine dgelqf(m, n, a, lda, tau, work, lwork, info)
DGELQF
Definition dgelqf.f:142
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
Definition dgemm.f:188
subroutine dgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
DGEMV
Definition dgemv.f:158
subroutine dgeqrf(m, n, a, lda, tau, work, lwork, info)
DGEQRF
Definition dgeqrf.f:144
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
Definition ilaenv.f:160
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
Definition dlacpy.f:101
double precision function dlamch(cmach)
DLAMCH
Definition dlamch.f:69
double precision function dlange(norm, m, n, a, lda, work)
DLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
Definition dlange.f:112
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition dlascl.f:142
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition dlaset.f:108
subroutine drscl(n, sa, sx, incx)
DRSCL multiplies a vector by the reciprocal of a real scalar.
Definition drscl.f:82
subroutine dorgbr(vect, m, n, k, a, lda, tau, work, lwork, info)
DORGBR
Definition dorgbr.f:156
subroutine dormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMBR
Definition dormbr.f:193
subroutine dormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMLQ
Definition dormlq.f:165
subroutine dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMQR
Definition dormqr.f:165
Here is the call graph for this function:
Here is the caller graph for this function: