LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
sgelss.f
Go to the documentation of this file.
1*> \brief <b> SGELSS solves overdetermined or underdetermined systems for GE matrices</b>
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download SGELSS + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sgelss.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sgelss.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgelss.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE SGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
20* WORK, LWORK, INFO )
21*
22* .. Scalar Arguments ..
23* INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
24* REAL RCOND
25* ..
26* .. Array Arguments ..
27* REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
28* ..
29*
30*
31*> \par Purpose:
32* =============
33*>
34*> \verbatim
35*>
36*> SGELSS computes the minimum norm solution to a real linear least
37*> squares problem:
38*>
39*> Minimize 2-norm(| b - A*x |).
40*>
41*> using the singular value decomposition (SVD) of A. A is an M-by-N
42*> matrix which may be rank-deficient.
43*>
44*> Several right hand side vectors b and solution vectors x can be
45*> handled in a single call; they are stored as the columns of the
46*> M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix
47*> X.
48*>
49*> The effective rank of A is determined by treating as zero those
50*> singular values which are less than RCOND times the largest singular
51*> value.
52*> \endverbatim
53*
54* Arguments:
55* ==========
56*
57*> \param[in] M
58*> \verbatim
59*> M is INTEGER
60*> The number of rows of the matrix A. M >= 0.
61*> \endverbatim
62*>
63*> \param[in] N
64*> \verbatim
65*> N is INTEGER
66*> The number of columns of the matrix A. N >= 0.
67*> \endverbatim
68*>
69*> \param[in] NRHS
70*> \verbatim
71*> NRHS is INTEGER
72*> The number of right hand sides, i.e., the number of columns
73*> of the matrices B and X. NRHS >= 0.
74*> \endverbatim
75*>
76*> \param[in,out] A
77*> \verbatim
78*> A is REAL array, dimension (LDA,N)
79*> On entry, the M-by-N matrix A.
80*> On exit, the first min(m,n) rows of A are overwritten with
81*> its right singular vectors, stored rowwise.
82*> \endverbatim
83*>
84*> \param[in] LDA
85*> \verbatim
86*> LDA is INTEGER
87*> The leading dimension of the array A. LDA >= max(1,M).
88*> \endverbatim
89*>
90*> \param[in,out] B
91*> \verbatim
92*> B is REAL array, dimension (LDB,NRHS)
93*> On entry, the M-by-NRHS right hand side matrix B.
94*> On exit, B is overwritten by the N-by-NRHS solution
95*> matrix X. If m >= n and RANK = n, the residual
96*> sum-of-squares for the solution in the i-th column is given
97*> by the sum of squares of elements n+1:m in that column.
98*> \endverbatim
99*>
100*> \param[in] LDB
101*> \verbatim
102*> LDB is INTEGER
103*> The leading dimension of the array B. LDB >= max(1,max(M,N)).
104*> \endverbatim
105*>
106*> \param[out] S
107*> \verbatim
108*> S is REAL array, dimension (min(M,N))
109*> The singular values of A in decreasing order.
110*> The condition number of A in the 2-norm = S(1)/S(min(m,n)).
111*> \endverbatim
112*>
113*> \param[in] RCOND
114*> \verbatim
115*> RCOND is REAL
116*> RCOND is used to determine the effective rank of A.
117*> Singular values S(i) <= RCOND*S(1) are treated as zero.
118*> If RCOND < 0, machine precision is used instead.
119*> \endverbatim
120*>
121*> \param[out] RANK
122*> \verbatim
123*> RANK is INTEGER
124*> The effective rank of A, i.e., the number of singular values
125*> which are greater than RCOND*S(1).
126*> \endverbatim
127*>
128*> \param[out] WORK
129*> \verbatim
130*> WORK is REAL array, dimension (MAX(1,LWORK))
131*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
132*> \endverbatim
133*>
134*> \param[in] LWORK
135*> \verbatim
136*> LWORK is INTEGER
137*> The dimension of the array WORK. LWORK >= 1, and also:
138*> LWORK >= 3*min(M,N) + max( 2*min(M,N), max(M,N), NRHS )
139*> For good performance, LWORK should generally be larger.
140*>
141*> If LWORK = -1, then a workspace query is assumed; the routine
142*> only calculates the optimal size of the WORK array, returns
143*> this value as the first entry of the WORK array, and no error
144*> message related to LWORK is issued by XERBLA.
145*> \endverbatim
146*>
147*> \param[out] INFO
148*> \verbatim
149*> INFO is INTEGER
150*> = 0: successful exit
151*> < 0: if INFO = -i, the i-th argument had an illegal value.
152*> > 0: the algorithm for computing the SVD failed to converge;
153*> if INFO = i, i off-diagonal elements of an intermediate
154*> bidiagonal form did not converge to zero.
155*> \endverbatim
156*
157* Authors:
158* ========
159*
160*> \author Univ. of Tennessee
161*> \author Univ. of California Berkeley
162*> \author Univ. of Colorado Denver
163*> \author NAG Ltd.
164*
165*> \ingroup gelss
166*
167* =====================================================================
168 SUBROUTINE sgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
169 $ WORK, LWORK, INFO )
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 REAL RCOND
178* ..
179* .. Array Arguments ..
180 REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
181* ..
182*
183* =====================================================================
184*
185* .. Parameters ..
186 REAL ZERO, ONE
187 parameter( zero = 0.0e+0, one = 1.0e+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_SGEQRF, LWORK_SORMQR, LWORK_SGEBRD,
195 $ lwork_sormbr, lwork_sorgbr, lwork_sormlq
196 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
197* ..
198* .. Local Arrays ..
199 REAL DUM( 1 )
200* ..
201* .. External Subroutines ..
202 EXTERNAL sbdsqr, scopy, sgebrd, sgelqf, sgemm,
203 $ sgemv,
206* ..
207* .. External Functions ..
208 INTEGER ILAENV
209 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
210 EXTERNAL ilaenv, slamch, slange,
211 $ sroundup_lwork
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, 'SGELSS', ' ', 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 SGEQRF
255 CALL sgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
256 lwork_sgeqrf = int( dum(1) )
257* Compute space needed for SORMQR
258 CALL sormqr( 'L', 'T', m, nrhs, n, a, lda, dum(1), b,
259 $ ldb, dum(1), -1, info )
260 lwork_sormqr = int( dum(1) )
261 mm = n
262 maxwrk = max( maxwrk, n + lwork_sgeqrf )
263 maxwrk = max( maxwrk, n + lwork_sormqr )
264 END IF
265 IF( m.GE.n ) THEN
266*
267* Path 1 - overdetermined or exactly determined
268*
269* Compute workspace needed for SBDSQR
270*
271 bdspac = max( 1, 5*n )
272* Compute space needed for SGEBRD
273 CALL sgebrd( mm, n, a, lda, s, dum(1), dum(1),
274 $ dum(1), dum(1), -1, info )
275 lwork_sgebrd = int( dum(1) )
276* Compute space needed for SORMBR
277 CALL sormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda,
278 $ dum(1),
279 $ b, ldb, dum(1), -1, info )
280 lwork_sormbr = int( dum(1) )
281* Compute space needed for SORGBR
282 CALL sorgbr( 'P', n, n, n, a, lda, dum(1),
283 $ dum(1), -1, info )
284 lwork_sorgbr = int( dum(1) )
285* Compute total workspace needed
286 maxwrk = max( maxwrk, 3*n + lwork_sgebrd )
287 maxwrk = max( maxwrk, 3*n + lwork_sormbr )
288 maxwrk = max( maxwrk, 3*n + lwork_sorgbr )
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 SBDSQR
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 SGEBRD
306 CALL sgebrd( m, m, a, lda, s, dum(1), dum(1),
307 $ dum(1), dum(1), -1, info )
308 lwork_sgebrd = int( dum(1) )
309* Compute space needed for SORMBR
310 CALL sormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda,
311 $ dum(1), b, ldb, dum(1), -1, info )
312 lwork_sormbr = int( dum(1) )
313* Compute space needed for SORGBR
314 CALL sorgbr( 'P', m, m, m, a, lda, dum(1),
315 $ dum(1), -1, info )
316 lwork_sorgbr = int( dum(1) )
317* Compute space needed for SORMLQ
318 CALL sormlq( 'L', 'T', n, nrhs, m, a, lda, dum(1),
319 $ b, ldb, dum(1), -1, info )
320 lwork_sormlq = int( dum(1) )
321* Compute total workspace needed
322 maxwrk = m + m*ilaenv( 1, 'SGELQF', ' ', m, n, -1,
323 $ -1 )
324 maxwrk = max( maxwrk, m*m + 4*m + lwork_sgebrd )
325 maxwrk = max( maxwrk, m*m + 4*m + lwork_sormbr )
326 maxwrk = max( maxwrk, m*m + 4*m + lwork_sorgbr )
327 maxwrk = max( maxwrk, m*m + m + bdspac )
328 IF( nrhs.GT.1 ) THEN
329 maxwrk = max( maxwrk, m*m + m + m*nrhs )
330 ELSE
331 maxwrk = max( maxwrk, m*m + 2*m )
332 END IF
333 maxwrk = max( maxwrk, m + lwork_sormlq )
334 ELSE
335*
336* Path 2 - underdetermined
337*
338* Compute space needed for SGEBRD
339 CALL sgebrd( m, n, a, lda, s, dum(1), dum(1),
340 $ dum(1), dum(1), -1, info )
341 lwork_sgebrd = int( dum(1) )
342* Compute space needed for SORMBR
343 CALL sormbr( 'Q', 'L', 'T', m, nrhs, m, a, lda,
344 $ dum(1), b, ldb, dum(1), -1, info )
345 lwork_sormbr = int( dum(1) )
346* Compute space needed for SORGBR
347 CALL sorgbr( 'P', m, n, m, a, lda, dum(1),
348 $ dum(1), -1, info )
349 lwork_sorgbr = int( dum(1) )
350 maxwrk = 3*m + lwork_sgebrd
351 maxwrk = max( maxwrk, 3*m + lwork_sormbr )
352 maxwrk = max( maxwrk, 3*m + lwork_sorgbr )
353 maxwrk = max( maxwrk, bdspac )
354 maxwrk = max( maxwrk, n*nrhs )
355 END IF
356 END IF
357 maxwrk = max( minwrk, maxwrk )
358 END IF
359 work( 1 ) = sroundup_lwork(maxwrk)
360*
361 IF( lwork.LT.minwrk .AND. .NOT.lquery )
362 $ info = -12
363 END IF
364*
365 IF( info.NE.0 ) THEN
366 CALL xerbla( 'SGELSS', -info )
367 RETURN
368 ELSE IF( lquery ) THEN
369 RETURN
370 END IF
371*
372* Quick return if possible
373*
374 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
375 rank = 0
376 RETURN
377 END IF
378*
379* Get machine parameters
380*
381 eps = slamch( 'P' )
382 sfmin = slamch( 'S' )
383 smlnum = sfmin / eps
384 bignum = one / smlnum
385*
386* Scale A if max element outside range [SMLNUM,BIGNUM]
387*
388 anrm = slange( 'M', m, n, a, lda, work )
389 iascl = 0
390 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
391*
392* Scale matrix norm up to SMLNUM
393*
394 CALL slascl( 'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
395 iascl = 1
396 ELSE IF( anrm.GT.bignum ) THEN
397*
398* Scale matrix norm down to BIGNUM
399*
400 CALL slascl( 'G', 0, 0, anrm, bignum, m, n, a, lda, info )
401 iascl = 2
402 ELSE IF( anrm.EQ.zero ) THEN
403*
404* Matrix all zero. Return zero solution.
405*
406 CALL slaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb )
407 CALL slaset( 'F', minmn, 1, zero, zero, s, minmn )
408 rank = 0
409 GO TO 70
410 END IF
411*
412* Scale B if max element outside range [SMLNUM,BIGNUM]
413*
414 bnrm = slange( 'M', m, nrhs, b, ldb, work )
415 ibscl = 0
416 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
417*
418* Scale matrix norm up to SMLNUM
419*
420 CALL slascl( 'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
421 $ info )
422 ibscl = 1
423 ELSE IF( bnrm.GT.bignum ) THEN
424*
425* Scale matrix norm down to BIGNUM
426*
427 CALL slascl( 'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
428 $ info )
429 ibscl = 2
430 END IF
431*
432* Overdetermined case
433*
434 IF( m.GE.n ) THEN
435*
436* Path 1 - overdetermined or exactly determined
437*
438 mm = m
439 IF( m.GE.mnthr ) THEN
440*
441* Path 1a - overdetermined, with many more rows than columns
442*
443 mm = n
444 itau = 1
445 iwork = itau + n
446*
447* Compute A=Q*R
448* (Workspace: need 2*N, prefer N+N*NB)
449*
450 CALL sgeqrf( m, n, a, lda, work( itau ), work( iwork ),
451 $ lwork-iwork+1, info )
452*
453* Multiply B by transpose(Q)
454* (Workspace: need N+NRHS, prefer N+NRHS*NB)
455*
456 CALL sormqr( 'L', 'T', m, nrhs, n, a, lda, work( itau ),
457 $ b,
458 $ ldb, work( iwork ), lwork-iwork+1, info )
459*
460* Zero out below R
461*
462 IF( n.GT.1 )
463 $ CALL slaset( 'L', n-1, n-1, zero, zero, a( 2, 1 ),
464 $ 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 sgebrd( 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 sormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda,
483 $ work( itauq ),
484 $ b, ldb, work( iwork ), lwork-iwork+1, info )
485*
486* Generate right bidiagonalizing vectors of R in A
487* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
488*
489 CALL sorgbr( 'P', n, n, n, a, lda, work( itaup ),
490 $ work( iwork ), lwork-iwork+1, info )
491 iwork = ie + n
492*
493* Perform bidiagonal QR iteration
494* multiply B by transpose of left singular vectors
495* compute right singular vectors in A
496* (Workspace: need BDSPAC)
497*
498 CALL sbdsqr( 'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
499 $ 1, b, ldb, work( iwork ), info )
500 IF( info.NE.0 )
501 $ GO TO 70
502*
503* Multiply B by reciprocals of singular values
504*
505 thr = max( rcond*s( 1 ), sfmin )
506 IF( rcond.LT.zero )
507 $ thr = max( eps*s( 1 ), sfmin )
508 rank = 0
509 DO 10 i = 1, n
510 IF( s( i ).GT.thr ) THEN
511 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
512 rank = rank + 1
513 ELSE
514 CALL slaset( 'F', 1, nrhs, zero, zero, b( i, 1 ),
515 $ ldb )
516 END IF
517 10 CONTINUE
518*
519* Multiply B by right singular vectors
520* (Workspace: need N, prefer N*NRHS)
521*
522 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
523 CALL sgemm( 'T', 'N', n, nrhs, n, one, a, lda, b, ldb,
524 $ zero,
525 $ work, ldb )
526 CALL slacpy( 'G', n, nrhs, work, ldb, b, ldb )
527 ELSE IF( nrhs.GT.1 ) THEN
528 chunk = lwork / n
529 DO 20 i = 1, nrhs, chunk
530 bl = min( nrhs-i+1, chunk )
531 CALL sgemm( 'T', 'N', n, bl, n, one, a, lda, b( 1,
532 $ i ),
533 $ ldb, zero, work, n )
534 CALL slacpy( 'G', n, bl, work, n, b( 1, i ), ldb )
535 20 CONTINUE
536 ELSE IF( nrhs.EQ.1 ) THEN
537 CALL sgemv( 'T', n, n, one, a, lda, b, 1, zero, work, 1 )
538 CALL scopy( n, work, 1, b, 1 )
539 END IF
540*
541 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
542 $ max( m, 2*m-4, nrhs, n-3*m ) ) THEN
543*
544* Path 2a - underdetermined, with many more columns than rows
545* and sufficient workspace for an efficient algorithm
546*
547 ldwork = m
548 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
549 $ m*lda+m+m*nrhs ) )ldwork = lda
550 itau = 1
551 iwork = m + 1
552*
553* Compute A=L*Q
554* (Workspace: need 2*M, prefer M+M*NB)
555*
556 CALL sgelqf( m, n, a, lda, work( itau ), work( iwork ),
557 $ lwork-iwork+1, info )
558 il = iwork
559*
560* Copy L to WORK(IL), zeroing out above it
561*
562 CALL slacpy( 'L', m, m, a, lda, work( il ), ldwork )
563 CALL slaset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),
564 $ ldwork )
565 ie = il + ldwork*m
566 itauq = ie + m
567 itaup = itauq + m
568 iwork = itaup + m
569*
570* Bidiagonalize L in WORK(IL)
571* (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB)
572*
573 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
574 $ work( itauq ), work( itaup ), work( iwork ),
575 $ lwork-iwork+1, info )
576*
577* Multiply B by transpose of left bidiagonalizing vectors of L
578* (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)
579*
580 CALL sormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,
581 $ work( itauq ), b, ldb, work( iwork ),
582 $ lwork-iwork+1, info )
583*
584* Generate right bidiagonalizing vectors of R in WORK(IL)
585* (Workspace: need M*M+5*M-1, prefer M*M+4*M+(M-1)*NB)
586*
587 CALL sorgbr( 'P', m, m, m, work( il ), ldwork,
588 $ work( itaup ),
589 $ work( iwork ), lwork-iwork+1, info )
590 iwork = ie + m
591*
592* Perform bidiagonal QR iteration,
593* computing right singular vectors of L in WORK(IL) and
594* multiplying B by transpose of left singular vectors
595* (Workspace: need M*M+M+BDSPAC)
596*
597 CALL sbdsqr( 'U', m, m, 0, nrhs, s, work( ie ), work( il ),
598 $ ldwork, a, lda, b, ldb, work( iwork ), info )
599 IF( info.NE.0 )
600 $ GO TO 70
601*
602* Multiply B by reciprocals of singular values
603*
604 thr = max( rcond*s( 1 ), sfmin )
605 IF( rcond.LT.zero )
606 $ thr = max( eps*s( 1 ), sfmin )
607 rank = 0
608 DO 30 i = 1, m
609 IF( s( i ).GT.thr ) THEN
610 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
611 rank = rank + 1
612 ELSE
613 CALL slaset( 'F', 1, nrhs, zero, zero, b( i, 1 ),
614 $ ldb )
615 END IF
616 30 CONTINUE
617 iwork = ie
618*
619* Multiply B by right singular vectors of L in WORK(IL)
620* (Workspace: need M*M+2*M, prefer M*M+M+M*NRHS)
621*
622 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 ) THEN
623 CALL sgemm( 'T', 'N', m, nrhs, m, one, work( il ),
624 $ ldwork,
625 $ b, ldb, zero, work( iwork ), ldb )
626 CALL slacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb )
627 ELSE IF( nrhs.GT.1 ) THEN
628 chunk = ( lwork-iwork+1 ) / m
629 DO 40 i = 1, nrhs, chunk
630 bl = min( nrhs-i+1, chunk )
631 CALL sgemm( 'T', 'N', m, bl, m, one, work( il ),
632 $ ldwork,
633 $ b( 1, i ), ldb, zero, work( iwork ), m )
634 CALL slacpy( 'G', m, bl, work( iwork ), m, b( 1, i ),
635 $ ldb )
636 40 CONTINUE
637 ELSE IF( nrhs.EQ.1 ) THEN
638 CALL sgemv( 'T', m, m, one, work( il ), ldwork, b( 1,
639 $ 1 ), 1, zero, work( iwork ), 1 )
640 CALL scopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
641 END IF
642*
643* Zero out below first M rows of B
644*
645 CALL slaset( 'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
646 iwork = itau + m
647*
648* Multiply transpose(Q) by B
649* (Workspace: need M+NRHS, prefer M+NRHS*NB)
650*
651 CALL sormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,
652 $ ldb, work( iwork ), lwork-iwork+1, info )
653*
654 ELSE
655*
656* Path 2 - remaining underdetermined cases
657*
658 ie = 1
659 itauq = ie + m
660 itaup = itauq + m
661 iwork = itaup + m
662*
663* Bidiagonalize A
664* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
665*
666 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
667 $ work( itaup ), work( iwork ), lwork-iwork+1,
668 $ info )
669*
670* Multiply B by transpose of left bidiagonalizing vectors
671* (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB)
672*
673 CALL sormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda,
674 $ work( itauq ),
675 $ b, ldb, work( iwork ), lwork-iwork+1, info )
676*
677* Generate right bidiagonalizing vectors in A
678* (Workspace: need 4*M, prefer 3*M+M*NB)
679*
680 CALL sorgbr( 'P', m, n, m, a, lda, work( itaup ),
681 $ work( iwork ), lwork-iwork+1, info )
682 iwork = ie + m
683*
684* Perform bidiagonal QR iteration,
685* computing right singular vectors of A in A and
686* multiplying B by transpose of left singular vectors
687* (Workspace: need BDSPAC)
688*
689 CALL sbdsqr( 'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
690 $ 1, b, ldb, work( iwork ), info )
691 IF( info.NE.0 )
692 $ GO TO 70
693*
694* Multiply B by reciprocals of singular values
695*
696 thr = max( rcond*s( 1 ), sfmin )
697 IF( rcond.LT.zero )
698 $ thr = max( eps*s( 1 ), sfmin )
699 rank = 0
700 DO 50 i = 1, m
701 IF( s( i ).GT.thr ) THEN
702 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
703 rank = rank + 1
704 ELSE
705 CALL slaset( 'F', 1, nrhs, zero, zero, b( i, 1 ),
706 $ ldb )
707 END IF
708 50 CONTINUE
709*
710* Multiply B by right singular vectors of A
711* (Workspace: need N, prefer N*NRHS)
712*
713 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
714 CALL sgemm( 'T', 'N', n, nrhs, m, one, a, lda, b, ldb,
715 $ zero,
716 $ work, ldb )
717 CALL slacpy( 'F', n, nrhs, work, ldb, b, ldb )
718 ELSE IF( nrhs.GT.1 ) THEN
719 chunk = lwork / n
720 DO 60 i = 1, nrhs, chunk
721 bl = min( nrhs-i+1, chunk )
722 CALL sgemm( 'T', 'N', n, bl, m, one, a, lda, b( 1,
723 $ i ),
724 $ ldb, zero, work, n )
725 CALL slacpy( 'F', n, bl, work, n, b( 1, i ), ldb )
726 60 CONTINUE
727 ELSE IF( nrhs.EQ.1 ) THEN
728 CALL sgemv( 'T', m, n, one, a, lda, b, 1, zero, work, 1 )
729 CALL scopy( n, work, 1, b, 1 )
730 END IF
731 END IF
732*
733* Undo scaling
734*
735 IF( iascl.EQ.1 ) THEN
736 CALL slascl( 'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
737 $ info )
738 CALL slascl( 'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
739 $ info )
740 ELSE IF( iascl.EQ.2 ) THEN
741 CALL slascl( 'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
742 $ info )
743 CALL slascl( 'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
744 $ info )
745 END IF
746 IF( ibscl.EQ.1 ) THEN
747 CALL slascl( 'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
748 $ info )
749 ELSE IF( ibscl.EQ.2 ) THEN
750 CALL slascl( 'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
751 $ info )
752 END IF
753*
754 70 CONTINUE
755 work( 1 ) = sroundup_lwork(maxwrk)
756 RETURN
757*
758* End of SGELSS
759*
760 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine sbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
SBDSQR
Definition sbdsqr.f:240
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
Definition scopy.f:82
subroutine sgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
SGEBRD
Definition sgebrd.f:204
subroutine sgelqf(m, n, a, lda, tau, work, lwork, info)
SGELQF
Definition sgelqf.f:142
subroutine sgelss(m, n, nrhs, a, lda, b, ldb, s, rcond, rank, work, lwork, info)
SGELSS solves overdetermined or underdetermined systems for GE matrices
Definition sgelss.f:170
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
Definition sgemm.f:188
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
Definition sgemv.f:158
subroutine sgeqrf(m, n, a, lda, tau, work, lwork, info)
SGEQRF
Definition sgeqrf.f:144
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
Definition slacpy.f:101
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition slascl.f:142
subroutine slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition slaset.f:108
subroutine srscl(n, sa, sx, incx)
SRSCL multiplies a vector by the reciprocal of a real scalar.
Definition srscl.f:82
subroutine sorgbr(vect, m, n, k, a, lda, tau, work, lwork, info)
SORGBR
Definition sorgbr.f:156
subroutine sormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMBR
Definition sormbr.f:194
subroutine sormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMLQ
Definition sormlq.f:166
subroutine sormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMQR
Definition sormqr.f:166