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, 205 $ SGEQRF, SLABAD, SLACPY, SLASCL, SLASET, SORGBR, 206 $ SORMBR, SORMLQ, SORMQR, SRSCL, XERBLA 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 IF( NRHS.GT.1 ) 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 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) 361 $ INFO = -12 362 END IF 363* 364 IF( INFO.NE.0 ) 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 IF( M.EQ.0 .OR. N.EQ.0 ) 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 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, INFO ) 421 IBSCL = 1 422 ELSE IF( BNRM.GT.BIGNUM ) 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 IF( M.GE.N ) THEN 433* 434* Path 1 - overdetermined or exactly determined 435* 436 MM = M 437 IF( M.GE.MNTHR ) 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 IF( N.GT.1 ) 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 741