OpenRadioss 2025.1.11
OpenRadioss project
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*> \htmlonly
9*> Download SGELSS + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sgelss.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sgelss.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgelss.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18* Definition:
19* ===========
20*
21* SUBROUTINE SGELSS( 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* REAL RCOND
27* ..
28* .. Array Arguments ..
29* REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
30* ..
31*
32*
33*> \par Purpose:
34* =============
35*>
36*> \verbatim
37*>
38*> SGELSS 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 REAL 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 REAL 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 REAL 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 REAL
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 REAL 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 realGEsolve
168*
169* =====================================================================
170 SUBROUTINE sgelss( 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 REAL RCOND
180* ..
181* .. Array Arguments ..
182 REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
183* ..
184*
185* =====================================================================
186*
187* .. Parameters ..
188 REAL ZERO, ONE
189 parameter( zero = 0.0e+0, one = 1.0e+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_SGEQRF, LWORK_SORMQR, LWORK_SGEBRD,
197 $ lwork_sormbr, lwork_sorgbr, lwork_sormlq
198 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
199* ..
200* .. Local Arrays ..
201 REAL DUM( 1 )
202* ..
203* .. External Subroutines ..
204 EXTERNAL sbdsqr, scopy, sgebrd, sgelqf, sgemm, sgemv,
207* ..
208* .. External Functions ..
209 INTEGER ILAENV
210 REAL SLAMCH, SLANGE
211 EXTERNAL ilaenv, slamch, slange
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=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=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=dum(1)
276* Compute space needed for SORMBR
277 CALL sormbr( 'Q', 'L', 'T', mm, nrhs, n, a, lda, dum(1),
278 $ b, ldb, dum(1), -1, info )
279 lwork_sormbr=dum(1)
280* Compute space needed for SORGBR
281 CALL sorgbr( 'P', n, n, n, a, lda, dum(1),
282 $ dum(1), -1, info )
283 lwork_sorgbr=dum(1)
284* Compute total workspace needed
285 maxwrk = max( maxwrk, 3*n + lwork_sgebrd )
286 maxwrk = max( maxwrk, 3*n + lwork_sormbr )
287 maxwrk = max( maxwrk, 3*n + lwork_sorgbr )
288 maxwrk = max( maxwrk, bdspac )
289 maxwrk = max( maxwrk, n*nrhs )
290 minwrk = max( 3*n + mm, 3*n + nrhs, bdspac )
291 maxwrk = max( minwrk, maxwrk )
292 END IF
293 IF( n.GT.m ) THEN
294*
295* Compute workspace needed for SBDSQR
296*
297 bdspac = max( 1, 5*m )
298 minwrk = max( 3*m+nrhs, 3*m+n, bdspac )
299 IF( n.GE.mnthr ) THEN
300*
301* Path 2a - underdetermined, with many more columns
302* than rows
303*
304* Compute space needed for SGEBRD
305 CALL sgebrd( m, m, a, lda, s, dum(1), dum(1),
306 $ dum(1), dum(1), -1, info )
307 lwork_sgebrd=dum(1)
308* Compute space needed for SORMBR
309 CALL sormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda,
310 $ dum(1), b, ldb, dum(1), -1, info )
311 lwork_sormbr=dum(1)
312* Compute space needed for SORGBR
313 CALL sorgbr( 'p', M, M, M, A, LDA, DUM(1),
314 $ DUM(1), -1, INFO )
315 LWORK_SORGBR=DUM(1)
316* Compute space needed for SORMLQ
317 CALL SORMLQ( 'l', 't', N, NRHS, M, A, LDA, DUM(1),
318 $ B, LDB, DUM(1), -1, INFO )
319 LWORK_SORMLQ=DUM(1)
320* Compute total workspace needed
321 MAXWRK = M + M*ILAENV( 1, 'sgelqf', ' ', M, N, -1,
322 $ -1 )
323 MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SGEBRD )
324 MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SORMBR )
325 MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SORGBR )
326 MAXWRK = MAX( MAXWRK, M*M + M + BDSPAC )
327.GT. IF( NRHS1 ) THEN
328 MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
329 ELSE
330 MAXWRK = MAX( MAXWRK, M*M + 2*M )
331 END IF
332 MAXWRK = MAX( MAXWRK, M + LWORK_SORMLQ )
333 ELSE
334*
335* Path 2 - underdetermined
336*
337* Compute space needed for SGEBRD
338 CALL SGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
339 $ DUM(1), DUM(1), -1, INFO )
340 LWORK_SGEBRD=DUM(1)
341* Compute space needed for SORMBR
342 CALL SORMBR( 'q', 'l', 't', M, NRHS, M, A, LDA,
343 $ DUM(1), B, LDB, DUM(1), -1, INFO )
344 LWORK_SORMBR=DUM(1)
345* Compute space needed for SORGBR
346 CALL SORGBR( 'p', M, N, M, A, LDA, DUM(1),
347 $ DUM(1), -1, INFO )
348 LWORK_SORGBR=DUM(1)
349 MAXWRK = 3*M + LWORK_SGEBRD
350 MAXWRK = MAX( MAXWRK, 3*M + LWORK_SORMBR )
351 MAXWRK = MAX( MAXWRK, 3*M + LWORK_SORGBR )
352 MAXWRK = MAX( MAXWRK, BDSPAC )
353 MAXWRK = MAX( MAXWRK, N*NRHS )
354 END IF
355 END IF
356 MAXWRK = MAX( MINWRK, MAXWRK )
357 END IF
358 WORK( 1 ) = MAXWRK
359*
360.LT..AND..NOT. IF( LWORKMINWRK LQUERY )
361 $ INFO = -12
362 END IF
363*
364.NE. IF( INFO0 ) THEN
365 CALL XERBLA( 'sgelss', -INFO )
366 RETURN
367 ELSE IF( LQUERY ) THEN
368 RETURN
369 END IF
370*
371* Quick return if possible
372*
373.EQ..OR..EQ. IF( M0 N0 ) THEN
374 RANK = 0
375 RETURN
376 END IF
377*
378* Get machine parameters
379*
380 EPS = SLAMCH( 'p' )
381 SFMIN = SLAMCH( 's' )
382 SMLNUM = SFMIN / EPS
383 BIGNUM = ONE / SMLNUM
384 CALL SLABAD( SMLNUM, BIGNUM )
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.GT..AND..LT. IF( ANRMZERO ANRMSMLNUM ) 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.GT. ELSE IF( ANRMBIGNUM ) 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.EQ. ELSE IF( ANRMZERO ) 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.GT..AND..LT. IF( BNRMZERO BNRMSMLNUM ) THEN
417*
418* Scale matrix norm up to SMLNUM
419*
420 CALL SLASCL( 'g', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
421 IBSCL = 1
422.GT. ELSE IF( BNRMBIGNUM ) THEN
423*
424* Scale matrix norm down to BIGNUM
425*
426 CALL SLASCL( 'g', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
427 IBSCL = 2
428 END IF
429*
430* Overdetermined case
431*
432.GE. IF( MN ) THEN
433*
434* Path 1 - overdetermined or exactly determined
435*
436 MM = M
437.GE. IF( MMNTHR ) THEN
438*
439* Path 1a - overdetermined, with many more rows than columns
440*
441 MM = N
442 ITAU = 1
443 IWORK = ITAU + N
444*
445* Compute A=Q*R
446* (Workspace: need 2*N, prefer N+N*NB)
447*
448 CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
449 $ LWORK-IWORK+1, INFO )
450*
451* Multiply B by transpose(Q)
452* (Workspace: need N+NRHS, prefer N+NRHS*NB)
453*
454 CALL SORMQR( 'l', 't', M, NRHS, N, A, LDA, WORK( ITAU ), B,
455 $ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
456*
457* Zero out below R
458*
459.GT. IF( N1 )
460 $ CALL SLASET( 'l', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
461 END IF
462*
463 IE = 1
464 ITAUQ = IE + N
465 ITAUP = ITAUQ + N
466 IWORK = ITAUP + N
467*
468* Bidiagonalize R in A
469* (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB)
470*
471 CALL SGEBRD( MM, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
472 $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
473 $ INFO )
474*
475* Multiply B by transpose of left bidiagonalizing vectors of R
476* (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB)
477*
478 CALL SORMBR( 'q', 'l', 't', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
479 $ B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
480*
481* Generate right bidiagonalizing vectors of R in A
482* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
483*
484 CALL SORGBR( 'p', n, n, n, a, lda, work( itaup ),
485 $ work( iwork ), lwork-iwork+1, info )
486 iwork = ie + n
487*
488* Perform bidiagonal QR iteration
489* multiply B by transpose of left singular vectors
490* compute right singular vectors in A
491* (Workspace: need BDSPAC)
492*
493 CALL sbdsqr( 'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
494 $ 1, b, ldb, work( iwork ), info )
495 IF( info.NE.0 )
496 $ GO TO 70
497*
498* Multiply B by reciprocals of singular values
499*
500 thr = max( rcond*s( 1 ), sfmin )
501 IF( rcond.LT.zero )
502 $ thr = max( eps*s( 1 ), sfmin )
503 rank = 0
504 DO 10 i = 1, n
505 IF( s( i ).GT.thr ) THEN
506 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
507 rank = rank + 1
508 ELSE
509 CALL slaset( 'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
510 END IF
511 10 CONTINUE
512*
513* Multiply B by right singular vectors
514* (Workspace: need N, prefer N*NRHS)
515*
516 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
517 CALL sgemm( 'T', 'N', n, nrhs, n, one, a, lda, b, ldb, zero,
518 $ work, ldb )
519 CALL slacpy( 'G', n, nrhs, work, ldb, b, ldb )
520 ELSE IF( nrhs.GT.1 ) THEN
521 chunk = lwork / n
522 DO 20 i = 1, nrhs, chunk
523 bl = min( nrhs-i+1, chunk )
524 CALL sgemm( 'T', 'N', n, bl, n, one, a, lda, b( 1, i ),
525 $ ldb, zero, work, n )
526 CALL slacpy( 'G', n, bl, work, n, b( 1, i ), ldb )
527 20 CONTINUE
528 ELSE
529 CALL sgemv( 'T', n, n, one, a, lda, b, 1, zero, work, 1 )
530 CALL scopy( n, work, 1, b, 1 )
531 END IF
532*
533 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
534 $ max( m, 2*m-4, nrhs, n-3*m ) ) THEN
535*
536* Path 2a - underdetermined, with many more columns than rows
537* and sufficient workspace for an efficient algorithm
538*
539 ldwork = m
540 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
541 $ m*lda+m+m*nrhs ) )ldwork = lda
542 itau = 1
543 iwork = m + 1
544*
545* Compute A=L*Q
546* (Workspace: need 2*M, prefer M+M*NB)
547*
548 CALL sgelqf( m, n, a, lda, work( itau ), work( iwork ),
549 $ lwork-iwork+1, info )
550 il = iwork
551*
552* Copy L to WORK(IL), zeroing out above it
553*
554 CALL slacpy( 'L', m, m, a, lda, work( il ), ldwork )
555 CALL slaset( 'U', m-1, m-1, zero, zero, work( il+ldwork ),
556 $ ldwork )
557 ie = il + ldwork*m
558 itauq = ie + m
559 itaup = itauq + m
560 iwork = itaup + m
561*
562* Bidiagonalize L in WORK(IL)
563* (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB)
564*
565 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
566 $ work( itauq ), work( itaup ), work( iwork ),
567 $ lwork-iwork+1, info )
568*
569* Multiply B by transpose of left bidiagonalizing vectors of L
570* (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)
571*
572 CALL sormbr( 'Q', 'L', 'T', m, nrhs, m, work( il ), ldwork,
573 $ work( itauq ), b, ldb, work( iwork ),
574 $ lwork-iwork+1, info )
575*
576* Generate right bidiagonalizing vectors of R in WORK(IL)
577* (Workspace: need M*M+5*M-1, prefer M*M+4*M+(M-1)*NB)
578*
579 CALL sorgbr( 'P', m, m, m, work( il ), ldwork, work( itaup ),
580 $ work( iwork ), lwork-iwork+1, info )
581 iwork = ie + m
582*
583* Perform bidiagonal QR iteration,
584* computing right singular vectors of L in WORK(IL) and
585* multiplying B by transpose of left singular vectors
586* (Workspace: need M*M+M+BDSPAC)
587*
588 CALL sbdsqr( 'U', m, m, 0, nrhs, s, work( ie ), work( il ),
589 $ ldwork, a, lda, b, ldb, work( iwork ), info )
590 IF( info.NE.0 )
591 $ GO TO 70
592*
593* Multiply B by reciprocals of singular values
594*
595 thr = max( rcond*s( 1 ), sfmin )
596 IF( rcond.LT.zero )
597 $ thr = max( eps*s( 1 ), sfmin )
598 rank = 0
599 DO 30 i = 1, m
600 IF( s( i ).GT.thr ) THEN
601 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
602 rank = rank + 1
603 ELSE
604 CALL slaset( 'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
605 END IF
606 30 CONTINUE
607 iwork = ie
608*
609* Multiply B by right singular vectors of L in WORK(IL)
610* (Workspace: need M*M+2*M, prefer M*M+M+M*NRHS)
611*
612 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 ) THEN
613 CALL sgemm( 'T', 'N', m, nrhs, m, one, work( il ), ldwork,
614 $ b, ldb, zero, work( iwork ), ldb )
615 CALL slacpy( 'G', m, nrhs, work( iwork ), ldb, b, ldb )
616 ELSE IF( nrhs.GT.1 ) THEN
617 chunk = ( lwork-iwork+1 ) / m
618 DO 40 i = 1, nrhs, chunk
619 bl = min( nrhs-i+1, chunk )
620 CALL sgemm( 'T', 'N', m, bl, m, one, work( il ), ldwork,
621 $ b( 1, i ), ldb, zero, work( iwork ), m )
622 CALL slacpy( 'G', m, bl, work( iwork ), m, b( 1, i ),
623 $ ldb )
624 40 CONTINUE
625 ELSE
626 CALL sgemv( 'T', m, m, one, work( il ), ldwork, b( 1, 1 ),
627 $ 1, zero, work( iwork ), 1 )
628 CALL scopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
629 END IF
630*
631* Zero out below first M rows of B
632*
633 CALL slaset( 'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
634 iwork = itau + m
635*
636* Multiply transpose(Q) by B
637* (Workspace: need M+NRHS, prefer M+NRHS*NB)
638*
639 CALL sormlq( 'L', 'T', n, nrhs, m, a, lda, work( itau ), b,
640 $ ldb, work( iwork ), lwork-iwork+1, info )
641*
642 ELSE
643*
644* Path 2 - remaining underdetermined cases
645*
646 ie = 1
647 itauq = ie + m
648 itaup = itauq + m
649 iwork = itaup + m
650*
651* Bidiagonalize A
652* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
653*
654 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
655 $ work( itaup ), work( iwork ), lwork-iwork+1,
656 $ info )
657*
658* Multiply B by transpose of left bidiagonalizing vectors
659* (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB)
660*
661 CALL sormbr( 'Q', 'L', 'T', m, nrhs, n, a, lda, work( itauq ),
662 $ b, ldb, work( iwork ), lwork-iwork+1, info )
663*
664* Generate right bidiagonalizing vectors in A
665* (Workspace: need 4*M, prefer 3*M+M*NB)
666*
667 CALL sorgbr( 'P', m, n, m, a, lda, work( itaup ),
668 $ work( iwork ), lwork-iwork+1, info )
669 iwork = ie + m
670*
671* Perform bidiagonal QR iteration,
672* computing right singular vectors of A in A and
673* multiplying B by transpose of left singular vectors
674* (Workspace: need BDSPAC)
675*
676 CALL sbdsqr( 'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
677 $ 1, b, ldb, work( iwork ), info )
678 IF( info.NE.0 )
679 $ GO TO 70
680*
681* Multiply B by reciprocals of singular values
682*
683 thr = max( rcond*s( 1 ), sfmin )
684 IF( rcond.LT.zero )
685 $ thr = max( eps*s( 1 ), sfmin )
686 rank = 0
687 DO 50 i = 1, m
688 IF( s( i ).GT.thr ) THEN
689 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
690 rank = rank + 1
691 ELSE
692 CALL slaset( 'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
693 END IF
694 50 CONTINUE
695*
696* Multiply B by right singular vectors of A
697* (Workspace: need N, prefer N*NRHS)
698*
699 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
700 CALL sgemm( 'T', 'N', n, nrhs, m, one, a, lda, b, ldb, zero,
701 $ work, ldb )
702 CALL slacpy( 'F', n, nrhs, work, ldb, b, ldb )
703 ELSE IF( nrhs.GT.1 ) THEN
704 chunk = lwork / n
705 DO 60 i = 1, nrhs, chunk
706 bl = min( nrhs-i+1, chunk )
707 CALL sgemm( 'T', 'N', n, bl, m, one, a, lda, b( 1, i ),
708 $ ldb, zero, work, n )
709 CALL slacpy( 'F', n, bl, work, n, b( 1, i ), ldb )
710 60 CONTINUE
711 ELSE
712 CALL sgemv( 'T', m, n, one, a, lda, b, 1, zero, work, 1 )
713 CALL scopy( n, work, 1, b, 1 )
714 END IF
715 END IF
716*
717* Undo scaling
718*
719 IF( iascl.EQ.1 ) THEN
720 CALL slascl( 'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
721 CALL slascl( 'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
722 $ info )
723 ELSE IF( iascl.EQ.2 ) THEN
724 CALL slascl( 'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
725 CALL slascl( 'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
726 $ info )
727 END IF
728 IF( ibscl.EQ.1 ) THEN
729 CALL slascl( 'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
730 ELSE IF( ibscl.EQ.2 ) THEN
731 CALL slascl( 'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
732 END IF
733*
734 70 CONTINUE
735 work( 1 ) = maxwrk
736 RETURN
737*
738* End of SGELSS
739*
740 END
subroutine slabad(small, large)
SLABAD
Definition slabad.f:74
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:110
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
Definition ilaenv.f:162
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
Definition slacpy.f:103
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:143
subroutine sbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
SBDSQR
Definition sbdsqr.f:240
subroutine xerbla(srname, info)
XERBLA
Definition xerbla.f:60
subroutine sorgbr(vect, m, n, k, a, lda, tau, work, lwork, info)
SORGBR
Definition sorgbr.f:157
subroutine sgeqrf(m, n, a, lda, tau, work, lwork, info)
SGEQRF
Definition sgeqrf.f:146
subroutine sgelqf(m, n, a, lda, tau, work, lwork, info)
SGELQF
Definition sgelqf.f:143
subroutine sgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
SGEBRD
Definition sgebrd.f:205
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:172
subroutine srscl(n, sa, sx, incx)
SRSCL multiplies a vector by the reciprocal of a real scalar.
Definition srscl.f:84
subroutine sormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMBR
Definition sormbr.f:196
subroutine sormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMQR
Definition sormqr.f:168
subroutine sormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMLQ
Definition sormlq.f:168
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
Definition scopy.f:82
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
Definition sgemv.f:156
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
Definition sgemm.f:187
#define min(a, b)
Definition macros.h:20
#define max(a, b)
Definition macros.h:21