00001 SUBROUTINE ZGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
00002 $ WORK, LWORK, RWORK, IWORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
00011 DOUBLE PRECISION RCOND
00012
00013
00014 INTEGER IWORK( * )
00015 DOUBLE PRECISION RWORK( * ), S( * )
00016 COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
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
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 DOUBLE PRECISION ZERO, ONE, TWO
00153 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )
00154 COMPLEX*16 CZERO
00155 PARAMETER ( CZERO = ( 0.0D+0, 0.0D+0 ) )
00156
00157
00158 LOGICAL LQUERY
00159 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
00160 $ LDWORK, LIWORK, LRWORK, MAXMN, MAXWRK, MINMN,
00161 $ MINWRK, MM, MNTHR, NLVL, NRWORK, NWORK, SMLSIZ
00162 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
00163
00164
00165 EXTERNAL DLABAD, DLASCL, DLASET, XERBLA, ZGEBRD, ZGELQF,
00166 $ ZGEQRF, ZLACPY, ZLALSD, ZLASCL, ZLASET, ZUNMBR,
00167 $ ZUNMLQ, ZUNMQR
00168
00169
00170 INTEGER ILAENV
00171 DOUBLE PRECISION DLAMCH, ZLANGE
00172 EXTERNAL ILAENV, DLAMCH, ZLANGE
00173
00174
00175 INTRINSIC INT, LOG, MAX, MIN, DBLE
00176
00177
00178
00179
00180
00181 INFO = 0
00182 MINMN = MIN( M, N )
00183 MAXMN = MAX( M, N )
00184 LQUERY = ( LWORK.EQ.-1 )
00185 IF( M.LT.0 ) THEN
00186 INFO = -1
00187 ELSE IF( N.LT.0 ) THEN
00188 INFO = -2
00189 ELSE IF( NRHS.LT.0 ) THEN
00190 INFO = -3
00191 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
00192 INFO = -5
00193 ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THEN
00194 INFO = -7
00195 END IF
00196
00197
00198
00199
00200
00201
00202
00203
00204 IF( INFO.EQ.0 ) THEN
00205 MINWRK = 1
00206 MAXWRK = 1
00207 LIWORK = 1
00208 LRWORK = 1
00209 IF( MINMN.GT.0 ) THEN
00210 SMLSIZ = ILAENV( 9, 'ZGELSD', ' ', 0, 0, 0, 0 )
00211 MNTHR = ILAENV( 6, 'ZGELSD', ' ', M, N, NRHS, -1 )
00212 NLVL = MAX( INT( LOG( DBLE( MINMN ) / DBLE( SMLSIZ + 1 ) ) /
00213 $ LOG( TWO ) ) + 1, 0 )
00214 LIWORK = 3*MINMN*NLVL + 11*MINMN
00215 MM = M
00216 IF( M.GE.N .AND. M.GE.MNTHR ) THEN
00217
00218
00219
00220
00221 MM = N
00222 MAXWRK = MAX( MAXWRK, N*ILAENV( 1, 'ZGEQRF', ' ', M, N,
00223 $ -1, -1 ) )
00224 MAXWRK = MAX( MAXWRK, NRHS*ILAENV( 1, 'ZUNMQR', 'LC', M,
00225 $ NRHS, N, -1 ) )
00226 END IF
00227 IF( M.GE.N ) THEN
00228
00229
00230
00231 LRWORK = 10*N + 2*N*SMLSIZ + 8*N*NLVL + 3*SMLSIZ*NRHS +
00232 $ MAX( (SMLSIZ+1)**2, N*(1+NRHS) + 2*NRHS )
00233 MAXWRK = MAX( MAXWRK, 2*N + ( MM + N )*ILAENV( 1,
00234 $ 'ZGEBRD', ' ', MM, N, -1, -1 ) )
00235 MAXWRK = MAX( MAXWRK, 2*N + NRHS*ILAENV( 1, 'ZUNMBR',
00236 $ 'QLC', MM, NRHS, N, -1 ) )
00237 MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1,
00238 $ 'ZUNMBR', 'PLN', N, NRHS, N, -1 ) )
00239 MAXWRK = MAX( MAXWRK, 2*N + N*NRHS )
00240 MINWRK = MAX( 2*N + MM, 2*N + N*NRHS )
00241 END IF
00242 IF( N.GT.M ) THEN
00243 LRWORK = 10*M + 2*M*SMLSIZ + 8*M*NLVL + 3*SMLSIZ*NRHS +
00244 $ MAX( (SMLSIZ+1)**2, N*(1+NRHS) + 2*NRHS )
00245 IF( N.GE.MNTHR ) THEN
00246
00247
00248
00249
00250 MAXWRK = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1,
00251 $ -1 )
00252 MAXWRK = MAX( MAXWRK, M*M + 4*M + 2*M*ILAENV( 1,
00253 $ 'ZGEBRD', ' ', M, M, -1, -1 ) )
00254 MAXWRK = MAX( MAXWRK, M*M + 4*M + NRHS*ILAENV( 1,
00255 $ 'ZUNMBR', 'QLC', M, NRHS, M, -1 ) )
00256 MAXWRK = MAX( MAXWRK, M*M + 4*M + ( M - 1 )*ILAENV( 1,
00257 $ 'ZUNMLQ', 'LC', N, NRHS, M, -1 ) )
00258 IF( NRHS.GT.1 ) THEN
00259 MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
00260 ELSE
00261 MAXWRK = MAX( MAXWRK, M*M + 2*M )
00262 END IF
00263 MAXWRK = MAX( MAXWRK, M*M + 4*M + M*NRHS )
00264
00265
00266 MAXWRK = MAX( MAXWRK,
00267 $ 4*M+M*M+MAX( M, 2*M-4, NRHS, N-3*M ) )
00268 ELSE
00269
00270
00271
00272 MAXWRK = 2*M + ( N + M )*ILAENV( 1, 'ZGEBRD', ' ', M,
00273 $ N, -1, -1 )
00274 MAXWRK = MAX( MAXWRK, 2*M + NRHS*ILAENV( 1, 'ZUNMBR',
00275 $ 'QLC', M, NRHS, M, -1 ) )
00276 MAXWRK = MAX( MAXWRK, 2*M + M*ILAENV( 1, 'ZUNMBR',
00277 $ 'PLN', N, NRHS, M, -1 ) )
00278 MAXWRK = MAX( MAXWRK, 2*M + M*NRHS )
00279 END IF
00280 MINWRK = MAX( 2*M + N, 2*M + M*NRHS )
00281 END IF
00282 END IF
00283 MINWRK = MIN( MINWRK, MAXWRK )
00284 WORK( 1 ) = MAXWRK
00285 IWORK( 1 ) = LIWORK
00286 RWORK( 1 ) = LRWORK
00287
00288 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00289 INFO = -12
00290 END IF
00291 END IF
00292
00293 IF( INFO.NE.0 ) THEN
00294 CALL XERBLA( 'ZGELSD', -INFO )
00295 RETURN
00296 ELSE IF( LQUERY ) THEN
00297 RETURN
00298 END IF
00299
00300
00301
00302 IF( M.EQ.0 .OR. N.EQ.0 ) THEN
00303 RANK = 0
00304 RETURN
00305 END IF
00306
00307
00308
00309 EPS = DLAMCH( 'P' )
00310 SFMIN = DLAMCH( 'S' )
00311 SMLNUM = SFMIN / EPS
00312 BIGNUM = ONE / SMLNUM
00313 CALL DLABAD( SMLNUM, BIGNUM )
00314
00315
00316
00317 ANRM = ZLANGE( 'M', M, N, A, LDA, RWORK )
00318 IASCL = 0
00319 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00320
00321
00322
00323 CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
00324 IASCL = 1
00325 ELSE IF( ANRM.GT.BIGNUM ) THEN
00326
00327
00328
00329 CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
00330 IASCL = 2
00331 ELSE IF( ANRM.EQ.ZERO ) THEN
00332
00333
00334
00335 CALL ZLASET( 'F', MAX( M, N ), NRHS, CZERO, CZERO, B, LDB )
00336 CALL DLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 )
00337 RANK = 0
00338 GO TO 10
00339 END IF
00340
00341
00342
00343 BNRM = ZLANGE( 'M', M, NRHS, B, LDB, RWORK )
00344 IBSCL = 0
00345 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00346
00347
00348
00349 CALL ZLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
00350 IBSCL = 1
00351 ELSE IF( BNRM.GT.BIGNUM ) THEN
00352
00353
00354
00355 CALL ZLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
00356 IBSCL = 2
00357 END IF
00358
00359
00360
00361 IF( M.LT.N )
00362 $ CALL ZLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB )
00363
00364
00365
00366 IF( M.GE.N ) THEN
00367
00368
00369
00370 MM = M
00371 IF( M.GE.MNTHR ) THEN
00372
00373
00374
00375 MM = N
00376 ITAU = 1
00377 NWORK = ITAU + N
00378
00379
00380
00381
00382
00383 CALL ZGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00384 $ LWORK-NWORK+1, INFO )
00385
00386
00387
00388
00389
00390 CALL ZUNMQR( 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAU ), B,
00391 $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00392
00393
00394
00395 IF( N.GT.1 ) THEN
00396 CALL ZLASET( 'L', N-1, N-1, CZERO, CZERO, A( 2, 1 ),
00397 $ LDA )
00398 END IF
00399 END IF
00400
00401 ITAUQ = 1
00402 ITAUP = ITAUQ + N
00403 NWORK = ITAUP + N
00404 IE = 1
00405 NRWORK = IE + N
00406
00407
00408
00409
00410
00411 CALL ZGEBRD( MM, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
00412 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
00413 $ INFO )
00414
00415
00416
00417
00418 CALL ZUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
00419 $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00420
00421
00422
00423 CALL ZLALSD( 'U', SMLSIZ, N, NRHS, S, RWORK( IE ), B, LDB,
00424 $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ),
00425 $ IWORK, INFO )
00426 IF( INFO.NE.0 ) THEN
00427 GO TO 10
00428 END IF
00429
00430
00431
00432 CALL ZUNMBR( 'P', 'L', 'N', N, NRHS, N, A, LDA, WORK( ITAUP ),
00433 $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00434
00435 ELSE IF( N.GE.MNTHR .AND. LWORK.GE.4*M+M*M+
00436 $ MAX( M, 2*M-4, NRHS, N-3*M ) ) THEN
00437
00438
00439
00440
00441 LDWORK = M
00442 IF( LWORK.GE.MAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ),
00443 $ M*LDA+M+M*NRHS ) )LDWORK = LDA
00444 ITAU = 1
00445 NWORK = M + 1
00446
00447
00448
00449
00450 CALL ZGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00451 $ LWORK-NWORK+1, INFO )
00452 IL = NWORK
00453
00454
00455
00456 CALL ZLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK )
00457 CALL ZLASET( 'U', M-1, M-1, CZERO, CZERO, WORK( IL+LDWORK ),
00458 $ LDWORK )
00459 ITAUQ = IL + LDWORK*M
00460 ITAUP = ITAUQ + M
00461 NWORK = ITAUP + M
00462 IE = 1
00463 NRWORK = IE + M
00464
00465
00466
00467
00468
00469 CALL ZGEBRD( M, M, WORK( IL ), LDWORK, S, RWORK( IE ),
00470 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
00471 $ LWORK-NWORK+1, INFO )
00472
00473
00474
00475
00476 CALL ZUNMBR( 'Q', 'L', 'C', M, NRHS, M, WORK( IL ), LDWORK,
00477 $ WORK( ITAUQ ), B, LDB, WORK( NWORK ),
00478 $ LWORK-NWORK+1, INFO )
00479
00480
00481
00482 CALL ZLALSD( 'U', SMLSIZ, M, NRHS, S, RWORK( IE ), B, LDB,
00483 $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ),
00484 $ IWORK, INFO )
00485 IF( INFO.NE.0 ) THEN
00486 GO TO 10
00487 END IF
00488
00489
00490
00491 CALL ZUNMBR( 'P', 'L', 'N', M, NRHS, M, WORK( IL ), LDWORK,
00492 $ WORK( ITAUP ), B, LDB, WORK( NWORK ),
00493 $ LWORK-NWORK+1, INFO )
00494
00495
00496
00497 CALL ZLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB )
00498 NWORK = ITAU + M
00499
00500
00501
00502
00503 CALL ZUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, WORK( ITAU ), B,
00504 $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00505
00506 ELSE
00507
00508
00509
00510 ITAUQ = 1
00511 ITAUP = ITAUQ + M
00512 NWORK = ITAUP + M
00513 IE = 1
00514 NRWORK = IE + M
00515
00516
00517
00518
00519
00520 CALL ZGEBRD( M, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
00521 $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
00522 $ INFO )
00523
00524
00525
00526
00527 CALL ZUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAUQ ),
00528 $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00529
00530
00531
00532 CALL ZLALSD( 'L', SMLSIZ, M, NRHS, S, RWORK( IE ), B, LDB,
00533 $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ),
00534 $ IWORK, INFO )
00535 IF( INFO.NE.0 ) THEN
00536 GO TO 10
00537 END IF
00538
00539
00540
00541 CALL ZUNMBR( 'P', 'L', 'N', N, NRHS, M, A, LDA, WORK( ITAUP ),
00542 $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )
00543
00544 END IF
00545
00546
00547
00548 IF( IASCL.EQ.1 ) THEN
00549 CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )
00550 CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
00551 $ INFO )
00552 ELSE IF( IASCL.EQ.2 ) THEN
00553 CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )
00554 CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
00555 $ INFO )
00556 END IF
00557 IF( IBSCL.EQ.1 ) THEN
00558 CALL ZLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
00559 ELSE IF( IBSCL.EQ.2 ) THEN
00560 CALL ZLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )
00561 END IF
00562
00563 10 CONTINUE
00564 WORK( 1 ) = MAXWRK
00565 IWORK( 1 ) = LIWORK
00566 RWORK( 1 ) = LRWORK
00567 RETURN
00568
00569
00570
00571 END