00001 SUBROUTINE CGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
00002 $ WORK, LWORK, RWORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
00011 REAL RCOND
00012
00013
00014 REAL RWORK( * ), S( * )
00015 COMPLEX A( LDA, * ), B( LDB, * ), WORK( * )
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 REAL ZERO, ONE
00108 PARAMETER ( ZERO = 0.0E+0, ONE = 1.0E+0 )
00109 COMPLEX CZERO, CONE
00110 PARAMETER ( CZERO = ( 0.0E+0, 0.0E+0 ),
00111 $ CONE = ( 1.0E+0, 0.0E+0 ) )
00112
00113
00114 LOGICAL LQUERY
00115 INTEGER BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
00116 $ ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
00117 $ MAXWRK, MINMN, MINWRK, MM, MNTHR
00118 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
00119
00120
00121 COMPLEX VDUM( 1 )
00122
00123
00124 EXTERNAL CBDSQR, CCOPY, CGEBRD, CGELQF, CGEMM, CGEMV,
00125 $ CGEQRF, CLACPY, CLASCL, CLASET, CSRSCL, CUNGBR,
00126 $ CUNMBR, CUNMLQ, CUNMQR, SLABAD, SLASCL, SLASET,
00127 $ XERBLA
00128
00129
00130 INTEGER ILAENV
00131 REAL CLANGE, SLAMCH
00132 EXTERNAL ILAENV, CLANGE, SLAMCH
00133
00134
00135 INTRINSIC MAX, MIN
00136
00137
00138
00139
00140
00141 INFO = 0
00142 MINMN = MIN( M, N )
00143 MAXMN = MAX( M, N )
00144 LQUERY = ( LWORK.EQ.-1 )
00145 IF( M.LT.0 ) THEN
00146 INFO = -1
00147 ELSE IF( N.LT.0 ) THEN
00148 INFO = -2
00149 ELSE IF( NRHS.LT.0 ) THEN
00150 INFO = -3
00151 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
00152 INFO = -5
00153 ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THEN
00154 INFO = -7
00155 END IF
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 IF( INFO.EQ.0 ) THEN
00166 MINWRK = 1
00167 MAXWRK = 1
00168 IF( MINMN.GT.0 ) THEN
00169 MM = M
00170 MNTHR = ILAENV( 6, 'CGELSS', ' ', M, N, NRHS, -1 )
00171 IF( M.GE.N .AND. M.GE.MNTHR ) THEN
00172
00173
00174
00175
00176 MM = N
00177 MAXWRK = MAX( MAXWRK, N + N*ILAENV( 1, 'CGEQRF', ' ', M,
00178 $ N, -1, -1 ) )
00179 MAXWRK = MAX( MAXWRK, N + NRHS*ILAENV( 1, 'CUNMQR', 'LC',
00180 $ M, NRHS, N, -1 ) )
00181 END IF
00182 IF( M.GE.N ) THEN
00183
00184
00185
00186 MAXWRK = MAX( MAXWRK, 2*N + ( MM + N )*ILAENV( 1,
00187 $ 'CGEBRD', ' ', MM, N, -1, -1 ) )
00188 MAXWRK = MAX( MAXWRK, 2*N + NRHS*ILAENV( 1, 'CUNMBR',
00189 $ 'QLC', MM, NRHS, N, -1 ) )
00190 MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1,
00191 $ 'CUNGBR', 'P', N, N, N, -1 ) )
00192 MAXWRK = MAX( MAXWRK, N*NRHS )
00193 MINWRK = 2*N + MAX( NRHS, M )
00194 END IF
00195 IF( N.GT.M ) THEN
00196 MINWRK = 2*M + MAX( NRHS, N )
00197 IF( N.GE.MNTHR ) THEN
00198
00199
00200
00201
00202 MAXWRK = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1,
00203 $ -1 )
00204 MAXWRK = MAX( MAXWRK, 3*M + M*M + 2*M*ILAENV( 1,
00205 $ 'CGEBRD', ' ', M, M, -1, -1 ) )
00206 MAXWRK = MAX( MAXWRK, 3*M + M*M + NRHS*ILAENV( 1,
00207 $ 'CUNMBR', 'QLC', M, NRHS, M, -1 ) )
00208 MAXWRK = MAX( MAXWRK, 3*M + M*M + ( M - 1 )*ILAENV( 1,
00209 $ 'CUNGBR', 'P', M, M, M, -1 ) )
00210 IF( NRHS.GT.1 ) THEN
00211 MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
00212 ELSE
00213 MAXWRK = MAX( MAXWRK, M*M + 2*M )
00214 END IF
00215 MAXWRK = MAX( MAXWRK, M + NRHS*ILAENV( 1, 'CUNMLQ',
00216 $ 'LC', N, NRHS, M, -1 ) )
00217 ELSE
00218
00219
00220
00221 MAXWRK = 2*M + ( N + M )*ILAENV( 1, 'CGEBRD', ' ', M,
00222 $ N, -1, -1 )
00223 MAXWRK = MAX( MAXWRK, 2*M + NRHS*ILAENV( 1, 'CUNMBR',
00224 $ 'QLC', M, NRHS, M, -1 ) )
00225 MAXWRK = MAX( MAXWRK, 2*M + M*ILAENV( 1, 'CUNGBR',
00226 $ 'P', M, N, M, -1 ) )
00227 MAXWRK = MAX( MAXWRK, N*NRHS )
00228 END IF
00229 END IF
00230 MAXWRK = MAX( MINWRK, MAXWRK )
00231 END IF
00232 WORK( 1 ) = MAXWRK
00233
00234 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY )
00235 $ INFO = -12
00236 END IF
00237
00238 IF( INFO.NE.0 ) THEN
00239 CALL XERBLA( 'CGELSS', -INFO )
00240 RETURN
00241 ELSE IF( LQUERY ) THEN
00242 RETURN
00243 END IF
00244
00245
00246
00247 IF( M.EQ.0 .OR. N.EQ.0 ) THEN
00248 RANK = 0
00249 RETURN
00250 END IF
00251
00252
00253
00254 EPS = SLAMCH( 'P' )
00255 SFMIN = SLAMCH( 'S' )
00256 SMLNUM = SFMIN / EPS
00257 BIGNUM = ONE / SMLNUM
00258 CALL SLABAD( SMLNUM, BIGNUM )
00259
00260
00261
00262 ANRM = CLANGE( 'M', M, N, A, LDA, RWORK )
00263 IASCL = 0
00264 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00265
00266
00267
00268 CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
00269 IASCL = 1
00270 ELSE IF( ANRM.GT.BIGNUM ) THEN
00271
00272
00273
00274 CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
00275 IASCL = 2
00276 ELSE IF( ANRM.EQ.ZERO ) THEN
00277
00278
00279
00280 CALL CLASET( 'F', MAX( M, N ), NRHS, CZERO, CZERO, B, LDB )
00281 CALL SLASET( 'F', MINMN, 1, ZERO, ZERO, S, MINMN )
00282 RANK = 0
00283 GO TO 70
00284 END IF
00285
00286
00287
00288 BNRM = CLANGE( 'M', M, NRHS, B, LDB, RWORK )
00289 IBSCL = 0
00290 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00291
00292
00293
00294 CALL CLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
00295 IBSCL = 1
00296 ELSE IF( BNRM.GT.BIGNUM ) THEN
00297
00298
00299
00300 CALL CLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
00301 IBSCL = 2
00302 END IF
00303
00304
00305
00306 IF( M.GE.N ) THEN
00307
00308
00309
00310 MM = M
00311 IF( M.GE.MNTHR ) THEN
00312
00313
00314
00315 MM = N
00316 ITAU = 1
00317 IWORK = ITAU + N
00318
00319
00320
00321
00322
00323 CALL CGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
00324 $ LWORK-IWORK+1, INFO )
00325
00326
00327
00328
00329
00330 CALL CUNMQR( 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAU ), B,
00331 $ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
00332
00333
00334
00335 IF( N.GT.1 )
00336 $ CALL CLASET( 'L', N-1, N-1, CZERO, CZERO, A( 2, 1 ),
00337 $ LDA )
00338 END IF
00339
00340 IE = 1
00341 ITAUQ = 1
00342 ITAUP = ITAUQ + N
00343 IWORK = ITAUP + N
00344
00345
00346
00347
00348
00349 CALL CGEBRD( MM, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
00350 $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
00351 $ INFO )
00352
00353
00354
00355
00356
00357 CALL CUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
00358 $ B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
00359
00360
00361
00362
00363
00364 CALL CUNGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
00365 $ WORK( IWORK ), LWORK-IWORK+1, INFO )
00366 IRWORK = IE + N
00367
00368
00369
00370
00371
00372
00373
00374 CALL CBDSQR( 'U', N, N, 0, NRHS, S, RWORK( IE ), A, LDA, VDUM,
00375 $ 1, B, LDB, RWORK( IRWORK ), INFO )
00376 IF( INFO.NE.0 )
00377 $ GO TO 70
00378
00379
00380
00381 THR = MAX( RCOND*S( 1 ), SFMIN )
00382 IF( RCOND.LT.ZERO )
00383 $ THR = MAX( EPS*S( 1 ), SFMIN )
00384 RANK = 0
00385 DO 10 I = 1, N
00386 IF( S( I ).GT.THR ) THEN
00387 CALL CSRSCL( NRHS, S( I ), B( I, 1 ), LDB )
00388 RANK = RANK + 1
00389 ELSE
00390 CALL CLASET( 'F', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
00391 END IF
00392 10 CONTINUE
00393
00394
00395
00396
00397
00398 IF( LWORK.GE.LDB*NRHS .AND. NRHS.GT.1 ) THEN
00399 CALL CGEMM( 'C', 'N', N, NRHS, N, CONE, A, LDA, B, LDB,
00400 $ CZERO, WORK, LDB )
00401 CALL CLACPY( 'G', N, NRHS, WORK, LDB, B, LDB )
00402 ELSE IF( NRHS.GT.1 ) THEN
00403 CHUNK = LWORK / N
00404 DO 20 I = 1, NRHS, CHUNK
00405 BL = MIN( NRHS-I+1, CHUNK )
00406 CALL CGEMM( 'C', 'N', N, BL, N, CONE, A, LDA, B( 1, I ),
00407 $ LDB, CZERO, WORK, N )
00408 CALL CLACPY( 'G', N, BL, WORK, N, B( 1, I ), LDB )
00409 20 CONTINUE
00410 ELSE
00411 CALL CGEMV( 'C', N, N, CONE, A, LDA, B, 1, CZERO, WORK, 1 )
00412 CALL CCOPY( N, WORK, 1, B, 1 )
00413 END IF
00414
00415 ELSE IF( N.GE.MNTHR .AND. LWORK.GE.3*M+M*M+MAX( M, NRHS, N-2*M ) )
00416 $ THEN
00417
00418
00419
00420
00421
00422
00423 LDWORK = M
00424 IF( LWORK.GE.3*M+M*LDA+MAX( M, NRHS, N-2*M ) )
00425 $ LDWORK = LDA
00426 ITAU = 1
00427 IWORK = M + 1
00428
00429
00430
00431
00432
00433 CALL CGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
00434 $ LWORK-IWORK+1, INFO )
00435 IL = IWORK
00436
00437
00438
00439 CALL CLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK )
00440 CALL CLASET( 'U', M-1, M-1, CZERO, CZERO, WORK( IL+LDWORK ),
00441 $ LDWORK )
00442 IE = 1
00443 ITAUQ = IL + LDWORK*M
00444 ITAUP = ITAUQ + M
00445 IWORK = ITAUP + M
00446
00447
00448
00449
00450
00451 CALL CGEBRD( M, M, WORK( IL ), LDWORK, S, RWORK( IE ),
00452 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( IWORK ),
00453 $ LWORK-IWORK+1, INFO )
00454
00455
00456
00457
00458
00459 CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, M, WORK( IL ), LDWORK,
00460 $ WORK( ITAUQ ), B, LDB, WORK( IWORK ),
00461 $ LWORK-IWORK+1, INFO )
00462
00463
00464
00465
00466
00467 CALL CUNGBR( 'P', M, M, M, WORK( IL ), LDWORK, WORK( ITAUP ),
00468 $ WORK( IWORK ), LWORK-IWORK+1, INFO )
00469 IRWORK = IE + M
00470
00471
00472
00473
00474
00475
00476
00477 CALL CBDSQR( 'U', M, M, 0, NRHS, S, RWORK( IE ), WORK( IL ),
00478 $ LDWORK, A, LDA, B, LDB, RWORK( IRWORK ), INFO )
00479 IF( INFO.NE.0 )
00480 $ GO TO 70
00481
00482
00483
00484 THR = MAX( RCOND*S( 1 ), SFMIN )
00485 IF( RCOND.LT.ZERO )
00486 $ THR = MAX( EPS*S( 1 ), SFMIN )
00487 RANK = 0
00488 DO 30 I = 1, M
00489 IF( S( I ).GT.THR ) THEN
00490 CALL CSRSCL( NRHS, S( I ), B( I, 1 ), LDB )
00491 RANK = RANK + 1
00492 ELSE
00493 CALL CLASET( 'F', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
00494 END IF
00495 30 CONTINUE
00496 IWORK = IL + M*LDWORK
00497
00498
00499
00500
00501
00502 IF( LWORK.GE.LDB*NRHS+IWORK-1 .AND. NRHS.GT.1 ) THEN
00503 CALL CGEMM( 'C', 'N', M, NRHS, M, CONE, WORK( IL ), LDWORK,
00504 $ B, LDB, CZERO, WORK( IWORK ), LDB )
00505 CALL CLACPY( 'G', M, NRHS, WORK( IWORK ), LDB, B, LDB )
00506 ELSE IF( NRHS.GT.1 ) THEN
00507 CHUNK = ( LWORK-IWORK+1 ) / M
00508 DO 40 I = 1, NRHS, CHUNK
00509 BL = MIN( NRHS-I+1, CHUNK )
00510 CALL CGEMM( 'C', 'N', M, BL, M, CONE, WORK( IL ), LDWORK,
00511 $ B( 1, I ), LDB, CZERO, WORK( IWORK ), M )
00512 CALL CLACPY( 'G', M, BL, WORK( IWORK ), M, B( 1, I ),
00513 $ LDB )
00514 40 CONTINUE
00515 ELSE
00516 CALL CGEMV( 'C', M, M, CONE, WORK( IL ), LDWORK, B( 1, 1 ),
00517 $ 1, CZERO, WORK( IWORK ), 1 )
00518 CALL CCOPY( M, WORK( IWORK ), 1, B( 1, 1 ), 1 )
00519 END IF
00520
00521
00522
00523 CALL CLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB )
00524 IWORK = ITAU + M
00525
00526
00527
00528
00529
00530 CALL CUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, WORK( ITAU ), B,
00531 $ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
00532
00533 ELSE
00534
00535
00536
00537 IE = 1
00538 ITAUQ = 1
00539 ITAUP = ITAUQ + M
00540 IWORK = ITAUP + M
00541
00542
00543
00544
00545
00546 CALL CGEBRD( M, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
00547 $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
00548 $ INFO )
00549
00550
00551
00552
00553
00554 CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAUQ ),
00555 $ B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
00556
00557
00558
00559
00560
00561 CALL CUNGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
00562 $ WORK( IWORK ), LWORK-IWORK+1, INFO )
00563 IRWORK = IE + M
00564
00565
00566
00567
00568
00569
00570
00571 CALL CBDSQR( 'L', M, N, 0, NRHS, S, RWORK( IE ), A, LDA, VDUM,
00572 $ 1, B, LDB, RWORK( IRWORK ), INFO )
00573 IF( INFO.NE.0 )
00574 $ GO TO 70
00575
00576
00577
00578 THR = MAX( RCOND*S( 1 ), SFMIN )
00579 IF( RCOND.LT.ZERO )
00580 $ THR = MAX( EPS*S( 1 ), SFMIN )
00581 RANK = 0
00582 DO 50 I = 1, M
00583 IF( S( I ).GT.THR ) THEN
00584 CALL CSRSCL( NRHS, S( I ), B( I, 1 ), LDB )
00585 RANK = RANK + 1
00586 ELSE
00587 CALL CLASET( 'F', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
00588 END IF
00589 50 CONTINUE
00590
00591
00592
00593
00594
00595 IF( LWORK.GE.LDB*NRHS .AND. NRHS.GT.1 ) THEN
00596 CALL CGEMM( 'C', 'N', N, NRHS, M, CONE, A, LDA, B, LDB,
00597 $ CZERO, WORK, LDB )
00598 CALL CLACPY( 'G', N, NRHS, WORK, LDB, B, LDB )
00599 ELSE IF( NRHS.GT.1 ) THEN
00600 CHUNK = LWORK / N
00601 DO 60 I = 1, NRHS, CHUNK
00602 BL = MIN( NRHS-I+1, CHUNK )
00603 CALL CGEMM( 'C', 'N', N, BL, M, CONE, A, LDA, B( 1, I ),
00604 $ LDB, CZERO, WORK, N )
00605 CALL CLACPY( 'F', N, BL, WORK, N, B( 1, I ), LDB )
00606 60 CONTINUE
00607 ELSE
00608 CALL CGEMV( 'C', M, N, CONE, A, LDA, B, 1, CZERO, WORK, 1 )
00609 CALL CCOPY( N, WORK, 1, B, 1 )
00610 END IF
00611 END IF
00612
00613
00614
00615 IF( IASCL.EQ.1 ) THEN
00616 CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )
00617 CALL SLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
00618 $ INFO )
00619 ELSE IF( IASCL.EQ.2 ) THEN
00620 CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )
00621 CALL SLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
00622 $ INFO )
00623 END IF
00624 IF( IBSCL.EQ.1 ) THEN
00625 CALL CLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
00626 ELSE IF( IBSCL.EQ.2 ) THEN
00627 CALL CLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )
00628 END IF
00629 70 CONTINUE
00630 WORK( 1 ) = MAXWRK
00631 RETURN
00632
00633
00634
00635 END